• 【干货】.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 方法

    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;
      }
    }

     这是最基本的处理流程,当然自此期间你需要去添加配置。

    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?

     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,让它返回响应信息,但是它在创建异步的时候,响应消息是不可用的。

    只能全局去配置吗?

    //路由中指定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等待的请求头,那么我们可以获取进行修改。

    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);
                }
            }
    

      那我们可以获取请求头,如何进行添加呢??

    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完成之后异步地执行任务。

      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; 
                } 
            ); 
        } 
  • 相关阅读:
    URL模块之parse方法
    结合GET(),POST()实现一个简单、完整的服务器
    Node.js初探之实现能向前台返回东西的简单服务器
    float和position
    回归博客园·共享onload事件
    百度地图api的用法
    美丽数列
    低位值
    删括号
    牛牛找工作
  • 原文地址:https://www.cnblogs.com/ZaraNet/p/10041289.html
Copyright © 2020-2023  润新知