AspNet WebApi : MessageHandler(消息处理器 )
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(消息处理器 )的更多相关文章
- 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 ...
- WebAPI 消息处理器
由上图可以看出消息处理器的使用场合和使用方法. 使用场合: HttpServer 得到请求时. public static class WebApiConfig { public static voi ...
- 【ASP.NET Web API教程】5.1 HTTP消息处理器
原文:[ASP.NET Web API教程]5.1 HTTP消息处理器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内容. 5.1 HTTP ...
- 【ASP.NET Web API教程】3.4 HttpClient消息处理器
原文:[ASP.NET Web API教程]3.4 HttpClient消息处理器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. 3.4 ...
- vs2012安装Microsoft.AspNet.WebApi.WebHost
工具---库程序包管理器---程序包管理器控制台:输入下面命令: Install-Package Microsoft.AspNet.WebApi.WebHost
- AspNet WebApi OData 学习
OData介绍:是一个查询和更新数据的Web协议.OData应用了web技术如HTTP.Atom发布协议(AtomPub)和JSON等来提供对不同应用程序,服务 和存储的信息访问.除了提供一些基本的操 ...
- Asp.Net WebApi+Microsoft.AspNet.WebApi.Core 启用CORS跨域访问
WebApi中启用CORS跨域访问 1.安装 Nugget包Microsoft.AspNet.WebApi.Cors This package contains the components to e ...
- AspNet.WebAPI.OData.ODataPQ
AspNet.WebAPI.OData.ODataPQ实现WebAPI的分页查询服务 AspNet.WebAPI.OData.ODataPQ实现WebAPI的分页查询服务-(个人拙笔) AspNet. ...
- AspNet.WebAPI.OData.ODataPQ实现WebAPI的分页查询服务-(个人拙笔)
AspNet.WebAPI.OData.ODataPQ 这是针对 Asp.net WebAPI OData 协议下,查询分页.或者是说 本人在使用Asp.Net webAPI 做服务接口时写的一个分页 ...
随机推荐
- 公有云开启全面竞争时代——青云QingCloud
网界网本期[封面报道]公有云开启全面竞争时代 [CNW.com.cn 专稿] 险滩急流之后,公有云[注]服务市场的开拓者们终于看到了一片丰饶之海. 2013年,中国云计算[注]产业起步的第五年,公有云 ...
- [转载]JVM性能调优--JVM参数配置
http://www.cnblogs.com/chen77716/archive/2010/06/26/2130807.html
- Git命令详解(一)-个人使用
本文暂时不会涉及到团队如何使用Git的内容,而是从个人的角度探讨如何用好Git. 约定 绿色的5位字符表示提交的ID,文中用<commit>表示,分别指向父节点.分支用橘色显示,分别指向特 ...
- UVaLive2572 poj1418 UVa1308 Viva Confetti
一次放下n个圆 问最终可见的圆的数量 应该是比较经典的问题吧 考虑一个圆与其他每个圆的交点O(n)个 将其割成了O(n)条弧 那么看每条弧的中点 分别向内向外调动eps这个点 则最上面的覆盖这个点的圆 ...
- UVa1628 UVaLive5847 Pizza Delivery
填坑系列(p.302) 既然不知道后面还要卖多少个就加一维状态嘛.. lrj写的O(n)转移?其实转移可以O(1) 貌似按x排序有奇效? #include<cstdio> #include ...
- Oracle分页查询SQL实现
首先看SQL 怎么写 select * from ( select a.*,ROWNUM rn from ( 最底层查询语句 ) a where ROWNUM <= #{endCol} ) wh ...
- Linq to Object实现分页获取数据
最后调用的CSharp代码可以是: int totalcount = dboperator.Customers.Count(); //总记录数 int pagesize = 100;//每页显示数 / ...
- IE8下提示'console'没有定义错误
在开发的过程中因为调试的原因,在代码中增加console.info("xxxx"),而未进行删除 在IE8下測试该代码所在的页面报错,例如以下: 须要注意的是,使用console对 ...
- 使用 Xcode 和 Android Studio 管理 iOS 和 Android 项目版本
在移动应用开发和运营的过程中,版本管理是一个老生常谈的基础问题,一些版本的基本概念也常常会困扰我们的研发和运营人员.同时,手动管理软件版本,也常常会因为不小心导致后续的发布和更新问题. 这里,我准备了 ...
- FreeCodeCamp 的 Basic Algorithm Scripting 题解(1)
这是本人的原创文章,转载请注明原文链接http://www.cnblogs.com/wusuowiaaa1blog/p/5932121.html. 1.Reverse a String 翻转字符串 先 ...