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 做服务接口时写的一个分页 ...
随机推荐
- [cocos2d-x3.0]Android+NDK+Eclipse环境搭建及编译步骤~
1: 必要准备 1): jdk&jre 2): adt-bundle 3): android ndk r9 4): python2.7 5): cocos2d-x 3.0 alpha0 2: ...
- 12个强大的Web服务测试工具
在过去的几年中,web服务或API的普及和使用有所增加. web服务或API是程序或软件组件的集合,可以帮助应用程序进行交互或通过形成其他应用程序或服务器之间的连接执行一些进程/事务处理.基本上有两种 ...
- js事件的方法
事件的方法:onclick 鼠标单击ondblclick 鼠标双击onkeyup 按下并释放键盘上的一个键时触发 onchange 文本内容或 ...
- python 多级菜单 纯循环与分支
源代码: dic1 = {'湖南':{'衡阳':{'珠晖区':'湖南工学院'},'湘潭':{'晖晖':'啦啦'}}, '北京':{'朝阳': {"德玛:北京大学"}}}print( ...
- oracle中 sql%rowcount 使用方法
sql%rowcount用于记录改动的条数,必须放在一个更新或者删除等改动类语句后面运行,select语句用于查询的话无法使用, 当你运行多条改动语句时,依照sql%rowcount 之前运行的最后一 ...
- [RxJS] Combination operator: withLatestFrom
Operator combineLatest is not the only AND-style combinator. In this lesson we will explore withLate ...
- Android如何创建背景透明的Dialog
一:控制Dialog 的背景方法:1.定义一个无背景主题主题<!--去掉背景Dialog--> <style name="NobackDialog" parent ...
- myeclipse配置svn亲测
1.安装目录更改为myeclipse install 目录:E:\MyEclipse85\MyEclipse 8.5common 目录: E:\MyEclipse85\Common ...
- Java中获得程序当前路径的4中方法
Java中获得程序当前路径的4中方法: 在Application中: import java.util.*; public class TestUserDir { public static void ...
- centos mysql 编译安装
centos mysql 编译安装 1.安装 创建MySQL用户 sudo useradd mysql 下载MySQL的源码包,我们这里使用的时5.5.18 安装依赖 sudo yum -y inst ...