最近在看老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方法重写”的更多相关文章

  1. ASP.NET Web API框架揭秘:路由系统的几个核心类型

    ASP.NET Web API框架揭秘:路由系统的几个核心类型 虽然ASP.NET Web API框架采用与ASP.NET MVC框架类似的管道式设计,但是ASP.NET Web API管道的核心部分 ...

  2. ASP.NET Web API 框架研究 ASP.NET Web API 路由

    ASP.NET Web API 核心框架是一个独立的.抽象的消息处理管道,ASP.NET Web API有自己独立的路由系统,是消息处理管道的组成部分,其与ASP.NET路由系统有类似的设计,都能找到 ...

  3. ASP.NET Web API 框架研究 核心的消息处理管道

    ASP.NET Web API 的核心框架是一个由一组HttpMessageHandler有序组成的双工消息处理管道:寄宿监听到请求接受后,把消息传入该管道经过所有HttpMessageHandler ...

  4. ASP.NET Web API 框架研究 Action方法介绍

    在根据请求解析出匹配的Controller类型并创建实例后,要在该Controller类型中的众多Action方法中选择与请求匹配的那一个,并执行,然后返回响应. Action方法,其元数据,主要包括 ...

  5. ASP.NET Web API 框架研究 Controller实例的销毁

    我们知道项目中创建的Controller,如ProductController都继承自ApiController抽象类,其又实现了接口IDisposable,所以,框架中自动调用Dispose方法来释 ...

  6. ASP.NET Web API 框架研究 服务容器 ServicesContainer

    ServicesContainer是一个服务的容器,可以理解为—个轻量级的IoC容器,其维护着一个服务接口类型与服务实例之间的映射关系,可以根据服务接口类型获取对应的服务实例.构成ASP.NET We ...

  7. ASP.NET Web API 框架研究 IoC容器 DependencyResolver

    一.概念 1.IoC(Inversion of Control),控制反转 即将依赖对象的创建和维护交给一个外部容器来负责,而不是应用本身.如,在类型A中需要使用类型B的实例,而B的实例的创建不是由A ...

  8. ASP.NET Web API 框架研究 Self Host模式下的消息处理管道

    Self Host模式下的ASP.NET Web API与WCF非常相似,都可以寄宿在任意类型的托管应用程序中,宿主可以是Windows Form .WPF.控制台应用以及Windows Servic ...

  9. ASP.NET Web API 框架研究 Web Host模式下的消息处理管道

    寄宿的作用是开启一个进程为Web API提供一个运行环境以解决持续监听.请求监听和响应回复,即将接收到的请求转换成HttpRequestMessage对象传入管道,并将管道生成并经过处理后的HttpR ...

随机推荐

  1. DeviceOne接受了DevStore的专访

    DevStore隶属深圳尺子科技有限公司,DevStore所有内容(资讯.数据.工具|服务.资源文章.问答……)都贯穿整个项目的生命周期,无论你是设计人员.开发人员.推广人员还是运营人员都可在此找到你 ...

  2. Unity3D手游开发实践

    <腾讯桌球:客户端总结> 本次分享总结,起源于腾讯桌球项目,但是不仅仅限于项目本身.虽然基于Unity3D,很多东西同样适用于Cocos.本文从以下10大点进行阐述: 架构设计 原生插件/ ...

  3. Java中文编码小结

    Java中文编码小结 1. 只有 字符到字节 或者 字节到字符 的转换才存在编码转码; 2. Java String 采用 UTF-16 编码方式存储所有字符.unicode体系采用唯一的码点表示唯一 ...

  4. 如何用django开发一个简易个人Blog

    功能概要:(目前已实现功能) 公共展示部分: 1.网站首页展示已发布的博客记录,包括名称.摘要信息.发布日期.阅读量及评论数. 2.首页文章列表可按照分类筛选. 3.点击标题或阅读全文链接,进入博客阅 ...

  5. (转)Hibernate事务管理

    Hibernate的事务管理 事务(Transaction)是工作中的基本逻辑单位,可以用于确保数据库能够被正确修改,避免数据只修改了一部分而导致数据不完整,或者在修改时受到用户干扰.作为一名软件设计 ...

  6. jQuery使用方法

    使用jQuery的第一步,往往就是将一个选择表达式,放进构造函数jQuery()(简写为$),然后得到被选中的元素. 选择表达式可以是CSS选择器: 1 $(document)//选择整个文档对象2 ...

  7. Java线程:线程栈模型与线程的变量

    Java线程:线程栈模型与线程的变量   要理解线程调度的原理,以及线程执行过程,必须理解线程栈模型. 线程栈是指某时刻时内存中线程调度的栈信息,当前调用的方法总是位于栈顶.线程栈的内容是随着程序的运 ...

  8. [Spring框架] Spring中的 ContextLoaderListener 实现原理.

    前言: 这是关于Spring的第三篇文章, 打算后续还会写入AOP 和Spring 事务管理相关的文章, 这么好的两个周末 都在看code了, 确实是有所收获, 现在就来记录一下. 在上一篇讲解Spr ...

  9. Android后台保活实践总结:即时通讯应用无法根治的“顽疾”

    前言 Android进程和Service的保活,是困扰Android开发人员的一大顽疾.因涉及到省电和内存管理策略,各厂商基于自家的理解,在自已ROOM发布于都对标准Android发行版作为或多或少的 ...

  10. Netty学习三:线程模型

    1 Proactor和Reactor Proactor和Reactor是两种经典的多路复用I/O模型,主要用于在高并发.高吞吐量的环境中进行I/O处理. I/O多路复用机制都依赖于一个事件分发器,事件 ...