学习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 ...
随机推荐
- 我的ORM之十-- MyOql实现原理
我的ORM索引 ORM的功能 两个基本功能 翻译:对象查询转化为SQL 映射:把查询结果转化为实体 更多功能 如果仅仅实现这两个功能,那这两个是可以独立的,实现起来也就很简单了.但MyOql的目标还有 ...
- 【转】一个lucene的官网例子
创建索引: import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import jav ...
- SharePoint—用REST方式访问列表
REST的定义与作用 在SharePoint 2010中,基本上有如下几种数据访问方式: 服务器端对象模型 LINQ to SharePoint Web Service 客户端对象模型 ADO.NET ...
- [我给Unity官方视频教程做中文字幕]beginner Graphics – Lessons系列之网格Meshes
[我给Unity官方视频教程做中文字幕]beginner Graphics – Lessons系列之网格Meshes 本篇分享一下第5个已完工的视频,即<beginner Graphics – ...
- svn add 添加到版本库
转 svn add-添加到版本库 常用操作1.添加一个文件到工作拷贝:$ svn add foo.c 2.当添加一个目录,svn add缺省的行为方式是递归的:$ svn add testdir 3. ...
- redis常用命令小结
转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/107.html?1455867352 1.redis-benchmarkr ...
- php版的redis操作库predis操作大全
转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/146.html predis是php连接redis的操作库,由于它完全使用 ...
- loglikelihood ratio 相似度
摘要: 在机器学习中常用到各种距离或者相似度,今天在看美团推荐系统重排序的文章时看到了loglikelihood ratio 相似度,特总结起来.以后有时间再把常用的相似度或者距离梳理到一篇文章. 背 ...
- JavaScript中this的一些怪异现象
<!--JavaScript伪协议和内联事件对于this的指向不同--> <a href="#" onclick="alert(this.tagName ...
- Atitit oodbms的查询,面向对象的sql查询jpa jpql hql
Atitit oodbms的查询,面向对象的sql查询jpa jpql hql 1.1. 标准API历史1 1.2. JPA定义了独特的JPQL(Java Persistence Query Lang ...