干货.NET WebApi HttpMessageHandler管道
Posted lonelyxmas
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了干货.NET WebApi HttpMessageHandler管道相关的知识,希望对你有一定的参考价值。
原文:【干货】.NET WebApi HttpMessageHandler管道
消息拦截器是一个类,接收 HTTP request并返回 HTTP response,Message handler 继承自抽象类 HttpMessageHandler,那么学习消息过滤器之前你应该了解下webapi的执行流程。
以上是webapi的执行流程,先是从response开始执行一套顺序之后通过network再回到了Request,其中经过了messageHandler,因为它是webapi架构中给我们可以自定义handler的地方,这和以往的webform差不多。都是基于http请求的。
有可能你会说这和过滤器Aop模式差不多啊,但你可以看完这篇文章之后再比比谁强大,当然它两者的用处都不同。
那消息拦截器有什么用呢,听名字我觉得你应该就知道是怎么回事,它是可以在客户端请求用修改请求信息的中间层,再次其中我们可以修改;添加 response headers,在到达 controller 之前,进行参数验证!
自定义 MessageHandler 需要继承 System.Net.Http.DelegatingHander
并且重载 SendAsync 方法
1 2 3 4 5 6 7 8 9 10 11 | public class MessageHandler1 : DelegatingHandler { protected async override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { Debug.WriteLine( "hello" ); var response = await base .SendAsync(request, cancellationToken); Debug.WriteLine( "bye" ); return response; } } |
这是最基本的处理流程,当然自此期间你需要去添加配置。
1 2 3 4 5 6 7 8 | public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add( new MessageHandler1()); config.MessageHandlers.Add( new MessageHandler2()); } } |
在消息拦截器中常见的是要判断用户信息,因为像ActionFilterAttribute、ApiControllerActionInvoker、ExceptionFilterAttribute 这些都是在action之前的,那我们就要在之前进行判断。
在HttpRequestMessage中包含了以下属性,这些你都是可以改的。
如何操作header?
1 2 3 4 5 6 7 | protected async override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { HttpResponseMessage response = await base .SendAsync(request, cancellationToken); response.Headers.Add( "X-Custom-Header" , "This is my custom header." ); return response; } |
首先调用sendAsync将请求传递给inner handler,让它返回响应信息,但是它在创建异步的时候,响应消息是不可用的。
只能全局去配置吗?
1 2 3 4 5 6 7 | //路由中指定Message Handler config.Routes.MapHttpRoute( name: "Route2" , routeTemplate: "api2/{controller}/{id}" , defaults: new { id = RouteParameter.Optional }, handler: new MessageHandler2() // per-route message handler ); |
这时MessageHandler2替换默认的HttpControllerDispatcher。这个栗子中MessageHandler2创建响应,匹配“Route2”的请求永远不会转到控制器。这使我们可以使用自己的自定义响应替换整个Web API控制器机制。
不知道你有没有想过,如果你的webapi不支持一些特殊的请求,你该怎么办呢,这个时候呵呵,你应该知道了吧!
在这个实例中我们定义了一个集合,在post请求中,一定不是get,那么就有可能是put 或者delete等待的请求头,那么我们可以获取进行修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class MethodOverrideHandler : DelegatingHandler { readonly string [] _methods = { "DELETE" , "HEAD" , "PUT" }; const string _header = "X-HTTP-Method-Override" ; protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { if (request.Method == HttpMethod.Post && request.Headers.Contains(_header)) { var method = request.Headers.GetValues(_header).FirstOrDefault(); if (_methods.Contains(method, StringComparer.InvariantCultureIgnoreCase)) { request.Method = new HttpMethod(method); } } return base .SendAsync(request, cancellationToken); } } |
那我们可以获取请求头,如何进行添加呢??
1 2 3 4 5 6 7 8 9 10 | public class CustomHeaderHandler : DelegatingHandler { async protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { HttpResponseMessage response = await base .SendAsync(request, cancellationToken); response.Headers.Add( "X-Custom-Header" , "This is my custom-header." ); return response; } } |
在以上代码中我们通过base.SendAsync调用内部消息处理器返回相应结果,base.SendAsync之前是不可响应获取消息的。
这个示例使用了await关键字,以便在SendAsync完成之后异步地执行任务。
1 2 3 4 5 6 7 8 9 10 11 12 | protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { return base .SendAsync(request, cancellationToken).ContinueWith( (task) => { HttpResponseMessage response = task.Result; response.Headers.Add( "X-Custom-Header" , "This is my custom header." ); return response; } ); } |
以上是关于干货.NET WebApi HttpMessageHandler管道的主要内容,如果未能解决你的问题,请参考以下文章
#yyds干货盘点#想说爱你不容易 | 使用最小 WEB API 实现文件上传
ASP.NET Core启动地址配置方法及优先级顺序 | .NET 6 版本 #yyds干货盘点#
Python3中HTTPMessage object has no attribute getheaders错误解决办法
HttpComponents 基础接口/类与HTTP message的对应关系