1. Http Message Handler

WebApi中的MessageHandler类似MVC中的filter,可用于请求/响应到达真正目标前对请求或者响应进行修改,比如:用户身份验证,请求头修改,返回数据的修改等。

先看一张webapi的请求流程图:

{Request}                          }  Pipeline 流向从上到下

|= HttpServer

|= { DelegatingHandler }       - 这里是个集合,可能存在0-n 个messagehandler

|= Inner Message Handler       - 内置的一些消息处理

|= HttpRoutingDispatcher

|= HttpControllerDispatcher

|= Controller

| Action

{ Response }                 }  end

从上面webapi:Http message lifecyle简图我们可以看出,在存在DelegatingHandler情况下,任何请求/响应在到达真正的目标前,都要先被DelegatingHandler处理,也就意味着DelegatingHandler拥有了决定继续响应请求和修改返回响应结果的权利.这里的delegatingHandler就是我们的messagehandler。

如果你了解nodejs express框架,你会发现messagehandler跟express框架的中间件在概念上基本是一样的。

通过自定义MessageHandler我们可以做很多针对请求/响应定制性的东西.

2. 自定义Message handler

自定义Messsage handler有两种途径,一种是直接通过继承HttpMessageHandler实现抽象方法SendAsync,另一种是通过继承DelegatingHandler重载SendAysnc方法实现.

(DelegatingHandler本身就是派生与HttpMesssageHandler,实现了SendAsync抽象方法,DelegatingHandlerh和HttpMessageHandler都是abstract类)

public abstract DelegatingHandler: HttpMessageHandler{  //HttpMessageHandler{ [abstrct][method] sendAsync() }
//some some //sendasync
protected Task<HttpResponseMessage> SendAsync(....){
//some
//一些内置的操作
return this.innerHandler.SendAsync(...);
} //innermessagehandle
private HttpMessageHandler innerHandler ;
}

实现了自定义的message handler,同时还需要添加到管线中消息处理器才能起作用,此时的消息处理器是全局的会被应用到所有的请求/响应上,

注册消息处理器可以通过HttpConfiguration::MessageHandlers.Add( 自定义消息处理器 ) .

a.一个简单的消息处理器. 实现了两个操作:

1) 如果请求消息头中没有包含X-TOKEN标识,那么直接返回NotFound,终止消息的继续传递

2) 针对响应消息,在响应消息头添加标识X-CUSTOM-HEADER

public class CustomTokenValidMessageHandler: DelegatingHandler
{
private readonly string X-TOKEN = "X-TOKEN";
//override sendAsync
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request , CancellationToken token )
{
//判断请求头中是否存在X-TOKEN标识以及值
//不存在情况下直接返回notfound,终止请求继续向下传递
if( !request.Headers.Contains(X-TOKEN) ){
var res = new HttpResponseMessage(HttpStatusCode.NotFound);
//这里使用TaskCompletionSource,可以通过setresult手动设置结果
var ts = new TaskCompletionSource<HttpResponseMessage>()
ts.SetResult( res ); return ts.Task;
} //2:t通过修改响应头,添加一个标识X-CUSTOM-HEADER
var response = base.SendAsync(request,token);
response.Result.Headers.Add("X-CUSTOM-HEADER","VIsonme-19-fz");
return response;
}
} //注册Message handler

b. MS官方的一个很好API验证的例子,在现实场景中都是常见的,比如某应用调用第三方WEB API,API方平台都会要求应用拥有一个key或者token.

public class APIKeyValidMessageHandler: DelegatingHandler

{
private string _app_api_key = string.Empty;
public APIKeyValidMessageHandler(string apikey){_app_api_key = apikey;}
private bool CheckApiKey( HttpRequestMessage req )
{
//解析查询字符串
var query_string = req.RequestUri.ParseQueryString();
var k = query_string["key"]; return (k == this._app_api_key);
} protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request , CancellationToken token )
{
if( !this.CheckApiKey( request ))
{
//key无效情况
var res = new HttpResponseMessage(HttpStatusCode.Forbidden);
var ts = new TaskCompletionSource<HttpResponseMessage>()
ts.SetResult( res ); return ts.Task;
} return base.SendAsync(request , token);
}
} //注册message handler

3.给指定的路由添加Message handler.

上面方式注册的消息处理器都是全局的,针对所有请求/响应,在某些场景下我们可能并不想消息处理器全局应用而是只针对某些路由,比如:某些API的访问我只希望一些核心的action需要被验证而其他的接口可以被大众化访问,这个时候就没有必要将身份验证的消息处理器应用到全局了 .

针对某些路由注册Message Handler,可以在HttpConfiguration::Routes::MapHttpRoute中给handler字段指定仅仅在该route上被处理的Message handler.

==> WebApiConfig.cs ==> Register [method]

config.Routes.MapHttpRoute(
name:"route name",
routeTemplate:"api/{controller}/{action}/{id},
default: new{id=RouteParameter.Optional},
constraints:null,
handler: new APIKeyValidMessageHandler("V-198-fz")
); //上面我们指定了handler为APIKeyValidMessageHandler
//那么APIKeyValidMessageHandler仅仅作用在该路由上,而不会
//被应用到全局
//如果希望全局应用只要在config.MessageHandlers.Add(your mh)
//就可以了

这个时候Http message lifecyle简图就变成了:

{ Request }

| = HttpServer

| = Message Handler

| = RouteDispathcer

| ----- 》----------------------{route 1 } ------------

|= Defaut route                  |

|-- Controller dispatcher        |= custom messge handler

|--------------------------------|------------------> { Response }

通过上面我们将messagehandler应用到指定的路由但是从简图我们看出,这个时候我们在route1看不到controller dispathcer了,controller diapathcer被我们自定义的message handler给取代了。

这种情况请不是我们所期望的,我们期望应该是将message hander插入到指定的route中,但是并不应该影响到我们原先route中应该的逻辑,也就是正确的应该是

route1 : 流程应该是这样的

{ custom message handler }

| Controller distatcher

| controller

{ response }

我们需要重新配置我们的message handler,通过HttpClientFactory创建一个路由管道点

DelegatingHandler[] handlers = new DelegatingHandler[]{
new APIKeyValidMessageHandler()
}; var routeHandlers = HttpClientFactory.CreatePipeline( new HttpControllerDispatcher(config),handler); //MAP HTTP ROUTE
config.Routes.MapHttpRoute(
name:"route1",
routeTemplate:"api/{controller}/{id}",
defaults: ///
constraints: null,
handlers:routeHandlers
);

AspNet WebApi : MessageHandler(消息处理器 )的更多相关文章

  1. Asp.Net Web API 2第四课——HttpClient消息处理器

    Asp.Net Web API 导航   Asp.Net Web API第一课:入门http://www.cnblogs.com/aehyok/p/3432158.html Asp.Net Web A ...

  2. WebAPI 消息处理器

    由上图可以看出消息处理器的使用场合和使用方法. 使用场合: HttpServer 得到请求时. public static class WebApiConfig { public static voi ...

  3. 【ASP.NET Web API教程】5.1 HTTP消息处理器

    原文:[ASP.NET Web API教程]5.1 HTTP消息处理器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内容. 5.1 HTTP ...

  4. 【ASP.NET Web API教程】3.4 HttpClient消息处理器

    原文:[ASP.NET Web API教程]3.4 HttpClient消息处理器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. 3.4 ...

  5. vs2012安装Microsoft.AspNet.WebApi.WebHost

    工具---库程序包管理器---程序包管理器控制台:输入下面命令:  Install-Package Microsoft.AspNet.WebApi.WebHost 

  6. AspNet WebApi OData 学习

    OData介绍:是一个查询和更新数据的Web协议.OData应用了web技术如HTTP.Atom发布协议(AtomPub)和JSON等来提供对不同应用程序,服务 和存储的信息访问.除了提供一些基本的操 ...

  7. Asp.Net WebApi+Microsoft.AspNet.WebApi.Core 启用CORS跨域访问

    WebApi中启用CORS跨域访问 1.安装 Nugget包Microsoft.AspNet.WebApi.Cors This package contains the components to e ...

  8. AspNet.WebAPI.OData.ODataPQ

    AspNet.WebAPI.OData.ODataPQ实现WebAPI的分页查询服务 AspNet.WebAPI.OData.ODataPQ实现WebAPI的分页查询服务-(个人拙笔) AspNet. ...

  9. AspNet.WebAPI.OData.ODataPQ实现WebAPI的分页查询服务-(个人拙笔)

    AspNet.WebAPI.OData.ODataPQ 这是针对 Asp.net WebAPI OData 协议下,查询分页.或者是说 本人在使用Asp.Net webAPI 做服务接口时写的一个分页 ...

随机推荐

  1. Codevs 3305 水果姐逛水果街Ⅱ 倍增LCA

    题目:http://codevs.cn/problem/3305/  时间限制: 2 s   空间限制: 256000 KB   题目等级 : 钻石 Diamond 题解       题目描述 Des ...

  2. Sorting Algorithm

    sorting 应该是最容易被考到的东西,自己老是学了背,背了忘.为了方便复习,这里进行总结 1. Bubble Sort 定义:每两个两个比较,每扫完一次,当前扫过的最大值放在了末尾. for i ...

  3. SRM 388(1-250pt)

    题意:定义一个数为k-smooth,如果它最大的质因子不超过k.给定n和k,求不超过n的,k-smooth的数有多少个.(k <= 100, n <= 10^5) 解法:对于一个数t,判断 ...

  4. 利用qemu模拟嵌入式系统制作全过程

    http://www.tinylab.org/using-qemu-simulation-inserts-the-type-system-to-produce-the-whole-process/ 利 ...

  5. disconf实践(一)

    公司目前的应用基本采用分布式部署,通过F5进行集群管理.分布式应用带来的好处是,随着流量的增加,可以快速扩展应用节点,分摊压力.分布式也会带来一定的挑战,譬如配置文件管理.如果某个配置要修改,那么所有 ...

  6. c# 字符串转化成声音 分类: C# 2014-09-24 12:20 316人阅读 评论(0) 收藏

    说明: (1)支持Window 7系统,但是xp系统智能朗读英文和数字: (2)添加引用 Interop.SpeechLib.dll; (3)使用时调用StringToVoice(str)即可. us ...

  7. 使用PDO连接数据库 查询和插入乱码的解决方法

    问题:PDO连接数据库后,查询和插入中文到数据库,出现乱码,如图: 解决方法: 法1: try{ $opts_values = array(PDO::MYSQL_ATTR_INIT_COMMAND=& ...

  8. 手把手教学:详解HTML5移动开发框架PhoneJS

    摘要:HTML/JavaScript的优势自不必说,但却也并非完美,相比之下,原生App占内存更少.响应更快.本文详解了HTML5移动开发框架PhoneJS的使用全过程,通过它,能够让Web应用在移动 ...

  9. WCF服务发布到IIS时候,只能根据hostname访问,不能根据IP地址访问的解决办法

    本文转载:http://www.cnblogs.com/deerbox/archive/2013/05/13/3076248.html 环境: VS2010 sp1,.net framework 4. ...

  10. MFC——error LNK2005: "protected: static struct AFX_MSGMAP

    好久没弄VC程序了,今天弄了下,还会用公司给的窗口重绘作为基类来实现,竟然报了这个错误. 找了一下是这里: 有个窗口重绘类是基类: class CBaseDlg : public CDialog 新建 ...