学习ASP.NET Web API框架揭秘之“HTTP方法重写”
最近在看老A的《ASP.NET Web API 框架揭秘》,这本书对于本人现阶段来说还是比较合适的(对于调用已经较为熟悉,用其开发过项目,但未深入理解过很多内容为何可以这样“调用”)。看到第四章了,有些内容看着虽能理解,但未遇到过具体的问题,看起来也就没有豁然开朗之感。同时,有些内容是一眼就觉得“这是干货”,可能是之前遇到过某些问题,当时用一些搓办法解决,但现在看到书中的示例就如获至宝。所以,就挑些单独能拎出来且马上就能在项目中应用的内容出来与大家分享交流下吧。其中会穿插一些框架中的知识点。不合适之处,请指教。万分感谢。
起因:理想的RESTful Web API采用面向资源的架构,并使用请求的HTTP方法表示针对目标资源的操作类型,但是理想和现实是有距离的。虽然HTTP协议提供了一系列原生的HTTP方法,但是在具体的网络环境中,很多是不支持的。比如:
1、有的浏览器只能发送GET和POS请求,客户端发送的PUT请求也不一定能够被服务器理解。
2、除了客户端和服务器对请求采用的HTTP方法的制约外,像代理(Proxy)、网关(Gateway)等这些中间部件都具有针对HTTP方法的限制
如何解决呢,我们一般采用“http方法重写”来解决这个问题。本示例自定义HttpMessageHandler(目的是替换请求的HTTP方法)实现HTTP方法重写。
具体步骤如下:
一、新建一个空的ASP.NET Web API应用,创建一个DemoController
这个就不多说了,直接贴个代码。
定义了不同Http方法对应的访问接口,同时返回对应的Http方法名,方便下面对其进行发送请求后,通过其返回值判断具体请求时是采用的哪个Http方法。
public class DemoController : ApiController
{
public string Get()
{
return "Get";
} public string Post()
{
return "Post";
} public string Put()
{
return "Put";
} public string Delete()
{
return "Delete";
} }
二、创建一个HttpMessageHandler实现Http方法的覆盖,注册到Web API的消息处理管道中
这个有个名词,管道,什么意思呢?书上是这么定义的,ASP.NET Web API的核心框架是一个消息处理管道,这个管道是一组HttpmessageHandler的有序组合。这是一个双工管道,请求消息从一端流入并依次经过所有HttpMessageHandler的处理。在另一端,目标HttpController被激活,Action方法被执行,响应消息随之被生成。

初看,有点糊涂,不知道是我自身的底子不够还是为何,一堆文字下来,我会晕,但好在有代码,看完代码,再看文字,理解起来,舒服得多。
上面这段在我目前的理解来看就是:为何你敲个Uri,ASP.NET Web API就能找到对应的action执行并返回呢,这其实在浏览器(客户端)发起请求到action执行这段过程中经过了一系列的操作,这一系列操作被分门别类的分离开来,每一个都可视为单独存在,称之为一个HttpMessageHandler,多个HttpMessageHandler组成了所谓管道。你可以先将其理解为一堆过滤器。
再来说我们要创建的这个HttpMessageHandler,作用就是实现Http方法的覆盖,即重写。我们创建完毕后,将这玩意儿加入到Web API的消息处理管道中,这样我们的请求过来后就必须经过我们自定义的HttpMessageHandler的“审查”。
实现:
1、新建我们的HttpMessageHandler,重写方法SendAsync,关键其实就是把请求头中的key-value的"X-HTTP-Method-Override"取出来,覆盖掉请求自身的Http方法,为何叫这名字呢?约定俗成,或者叫--规矩?
(如果跟我在一个频道上的朋友可能注意到,现在有个问题就是如何设置"X-HTTP-Method-Override"的值,这个待会儿再讲0 0)
public class HttpMethodOverrideHandler:DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
IEnumerable<string> methodOverrideHeader;
if (request.Headers.TryGetValues("X-HTTP-Method-Override",out methodOverrideHeader))
{
//这样就将请求自身的HTTP方法替换成"X-HTTP-Method-Override"内定义的方法了
request.Method = new HttpMethod(methodOverrideHeader.First());
}
return base.SendAsync(request, cancellationToken);
}
}
这里的DelegatingHandler即继承自HttpMessageHandler

2、HttpMessageHandler建立好后,那就是要添加到管道中
很简单,在我们的Global.asax.cs中的Application_Start()中添加如下一行代码
GlobalConfiguration.Configuration.MessageHandlers.Add(new HttpMethodOverrideHandler());

至此,服务端的工作完毕。我们已经在一个空的ASP.NET Web API项目中添加一个可供访问的demoController以及创建了一个用于Http方法重写(通过获取请求头的X-HTTP-Method-Override来覆盖Http方法)的HttpMessageHandler且加入到Web API的消息处理管道中了。接下来就是客户端模拟调用了。
三、创建一个客户端,进行访问测试
对于客户端,本身并无要求,可以是web页面浏览器来调用,也可以写个winform,wpf之类。这里就用控制台来进行示例,书中也是控制台,待会儿我还会用web页面上JS来调用,毕竟这才是我们工作的常态。
1、新建一个空的控制台应用层程序
直接贴代码 Program.cs
创建了四个请求,1跟2的请求头未设置X-HTTP-Method-Override,1自身的Http方法设置为Get,其他三个均为Post。
class Program
{ static void Main(string[] args)
{
HttpClient httpClient1 = new HttpClient();
HttpClient httpClient2 = new HttpClient();
HttpClient httpClient3 = new HttpClient();
HttpClient httpClient4 = new HttpClient(); httpClient3.DefaultRequestHeaders.Add("X-HTTP-Method-Override", "PUT");
httpClient4.DefaultRequestHeaders.Add("X-HTTP-Method-Override", "DELETE"); Console.WriteLine("{0,-7}{1,-24}{2,-12}{3,-24}","Method", "X-HTTP-Method-Override","Action","第几次请求"); InvokeWebApi(httpClient1, HttpMethod.Get,);
InvokeWebApi(httpClient2, HttpMethod.Post,);
InvokeWebApi(httpClient3, HttpMethod.Post,);
InvokeWebApi(httpClient4, HttpMethod.Post,); Console.Read();
} async static void InvokeWebApi(HttpClient httpClient, HttpMethod method,int requestTime)
{
string requestUri = "http://localhost:52697/api/demo";//上面创建的web api项目的地址
HttpRequestMessage request = new HttpRequestMessage(method, requestUri);
HttpResponseMessage response = await httpClient.SendAsync(request);
IEnumerable<string> methodsOverride; httpClient.DefaultRequestHeaders.TryGetValues("X-HTTP-Method-Override", out methodsOverride);
string actionName = response.Content.ReadAsStringAsync().Result;
string methodOverride = methodsOverride == null ? "N/A" : methodsOverride.First();
Console.WriteLine("{0,-7}{1,-24}{2,-12}{3,-24}", method, methodOverride, actionName.Trim('"'), requestTime);
}
}
代码很简单,按照我们之前讲的,输出不出问题的话,应该的设置了X-HTTP-Method-Override的请求,自身Http请求方法会被请求头中X-HTTP-Method-Override对应的值给覆盖掉。因此,得到如下输出结果:

第3、4次请求的Http方法均被“重写”了。任务完成。
有的同学要提问了,那么我们用JS发起ajax请求的时候如何操作呢,关键其实就是ajax如何操作请求头。这里同样给个示例
在上面的Web API项目中添加个HTML页面(这里用jquery操作ajax)添加代码如下:

若不出意外,按照我们的设想,应该是弹出“PUT”,而非“POST”,那么事实呢?

bingo~~睡觉!好久没更新博客园了,不能懒惰了。
学习ASP.NET Web API框架揭秘之“HTTP方法重写”的更多相关文章
- ASP.NET Web API框架揭秘:路由系统的几个核心类型
ASP.NET Web API框架揭秘:路由系统的几个核心类型 虽然ASP.NET Web API框架采用与ASP.NET MVC框架类似的管道式设计,但是ASP.NET Web API管道的核心部分 ...
- ASP.NET Web API 框架研究 ASP.NET Web API 路由
ASP.NET Web API 核心框架是一个独立的.抽象的消息处理管道,ASP.NET Web API有自己独立的路由系统,是消息处理管道的组成部分,其与ASP.NET路由系统有类似的设计,都能找到 ...
- ASP.NET Web API 框架研究 核心的消息处理管道
ASP.NET Web API 的核心框架是一个由一组HttpMessageHandler有序组成的双工消息处理管道:寄宿监听到请求接受后,把消息传入该管道经过所有HttpMessageHandler ...
- ASP.NET Web API 框架研究 Action方法介绍
在根据请求解析出匹配的Controller类型并创建实例后,要在该Controller类型中的众多Action方法中选择与请求匹配的那一个,并执行,然后返回响应. Action方法,其元数据,主要包括 ...
- ASP.NET Web API 框架研究 Controller实例的销毁
我们知道项目中创建的Controller,如ProductController都继承自ApiController抽象类,其又实现了接口IDisposable,所以,框架中自动调用Dispose方法来释 ...
- ASP.NET Web API 框架研究 服务容器 ServicesContainer
ServicesContainer是一个服务的容器,可以理解为—个轻量级的IoC容器,其维护着一个服务接口类型与服务实例之间的映射关系,可以根据服务接口类型获取对应的服务实例.构成ASP.NET We ...
- ASP.NET Web API 框架研究 IoC容器 DependencyResolver
一.概念 1.IoC(Inversion of Control),控制反转 即将依赖对象的创建和维护交给一个外部容器来负责,而不是应用本身.如,在类型A中需要使用类型B的实例,而B的实例的创建不是由A ...
- ASP.NET Web API 框架研究 Self Host模式下的消息处理管道
Self Host模式下的ASP.NET Web API与WCF非常相似,都可以寄宿在任意类型的托管应用程序中,宿主可以是Windows Form .WPF.控制台应用以及Windows Servic ...
- ASP.NET Web API 框架研究 Web Host模式下的消息处理管道
寄宿的作用是开启一个进程为Web API提供一个运行环境以解决持续监听.请求监听和响应回复,即将接收到的请求转换成HttpRequestMessage对象传入管道,并将管道生成并经过处理后的HttpR ...
随机推荐
- 分享:写了一个 java 调用 C语言 开发的动态库的范例
分享:写了一个 java 调用 C语言 开发的动态库的范例 cfunction.h 代码#pragma once#ifdef __cplusplusextern "C" {#e ...
- [stm32] 一个简单的stm32vet6驱动2.4寸240X320的8位并口tft屏DEMO
书接上文: 最近在研究用低速.低RAM的单片机来驱动小LCD或TFT彩屏实现动画效果 首先我用一个16MHz晶振的m0内核的8位单片机nRF51822尝试驱动一个1.77寸的4线SPI屏(128X16 ...
- Unity3d + NGUI 的多分辨率适配
一.当下移动设备的主流分辨率(数据来自“腾讯分析移动设备屏幕分辨率分析报告”) 1.1 iOS设备的分辨率主要有: 宽 高 宽高比 960 640 1.5 1136 640 1.775 1024 ...
- jQuery实现在线文档
1.1.1 摘要 现在,许多网站都提供在线图片和图书阅读的功能,这种方式比下载后阅读来的直观和人性化,要实现该功能涉及到点击处理和图片动态加载. 在接下来的博文中,我们将通过Javascript方式实 ...
- as3 同屏1000+动画,不掉帧。解决方案。
原理就是在一个enterframe里面,把1000个对象画到一个bitmapdata,然后交给舞台显示.
- ehcache2拾遗之write和load
问题描述 在cache系统中writeThrough和writeBehind是两个常用的模式. writeThrough是指,当用户更新缓存时,自动将值写入到数据源. writeBehind是指,在用 ...
- IOS Socket 02-Socket基础知识
1. 简介 Socket就是为网络服务提供的一种机制 通信的两端都是Socket 网络通信其实就是Socket间的通信 数据在两个Socket间通过IO传输 2. Socket通信流程图 3. 模拟Q ...
- cmd复制文件
cmd复制文件 复制文件夹,自动覆盖 xcopy /E/I/Y "D:\GitHub\Qriket\lucky\SPA\dist" "D:\GitHub\lucky\ww ...
- 复杂 XML 的 序列化 反序列化
已知.xml(再此命名default.xml)文件,请将其反序列化到一个实例对象. <?xml version="1.0" encoding="utf-8" ...
- 移动端 几个css3属性的练习
转行做前端,上班有一个星期了,什么都不懂,今天学习了几个新的css3属性,记录下来. 注:所有的测试均是在chrome上手机模式测试,与真实的手机环境可能有误差 1:-webkit-tap-heigh ...