WebApi2官网学习记录--HTTP Message Handlers
Message Handlers是一个接收HTTP Request返回HTTP Response的类,继承自HttpMessageHandler
通常,一些列的message handler被链接到一起。第一个handler收到http request做一些处理,然后将request传递到下一个handler。在某时刻,response被创并返回。这种模式被称为delegating hanlder

服务端消息处理
在服务端,WebAPI管道使用一些内建的message handlers
HttpServer从主机获取requestHttpRoutingDispacher基于路由分配requestHttpControllerDispacher发送request到WebAPI的controller
可以在pipline中自定义message handlers,如图,展示了两个自定义的handler

自定义 Message Handlers
自定义message handler需要实现System.Net.Http.DelegatingHandler接口,并重载SendAsync方法。
Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, CancellationToken cancellationToken);
典型的实现通过一些流程:
- 处理request message
 - 调用
base.SendAsync将request传递到内部的handler(inner handler) - 内部的handler返回一个response message(这步是异步的)
 - 处理response并返回给调用者
 
一个简单的例子:
public class MessageHandler1 : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        Debug.WriteLine("Process request");
        // Call the inner handler.
        var response = await base.SendAsync(request, cancellationToken);
        Debug.WriteLine("Process response");
        return response;
    }
}
当然,也可以跳过inner handler,直接创建一个response(这种方式对于验证request很有用)
public class MessageHandler2 : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // Create the response.
        var response = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent("Hello!")
        };
        // Note: TaskCompletionSource creates a task that does not contain a delegate.
        var tsc = new TaskCompletionSource<HttpResponseMessage>();
        tsc.SetResult(response);   // Also sets the task state to "RanToCompletion"
        return tsc.Task;
    }
}

添加Handler到Pipeline
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MessageHandlers.Add(new MessageHandler1());
        config.MessageHandlers.Add(new MessageHandler2());
        // Other code not shown...
    }
}
Message Handler被调用的顺序与添加到MessageHandlers集合的顺序相同,由于是嵌套的response message消息传播的方向正好与此相反。
对于inner handlers我们不需要设置,WebAPI框架会自动连接。
Per-Route Message Handlers
既可以在 HttpConfiguration.MessageHandlers集合中设置Handlers应用到globally范围,也可以在指定路由上添加一个message handler
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "Route1",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        config.Routes.MapHttpRoute(
            name: "Route2",
            routeTemplate: "api2/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: null,
			handler: new MessageHandler2()// per-route message handler
        );
        config.MessageHandlers.Add(new MessageHandler1());  // global message handler
    }
}
通过以上配置,如果URI匹配"Route2",请求将被分配到MessageHandler2。如下图所示:

注意:MessageHandler2会替代默认的HttpControllerDispatcher,匹配"Route2"的request将不能找到对应的controller,可以通过手动建立HttpControllerDispatcher来解决。
// List of delegating handlers.
DelegatingHandler[] handlers = new DelegatingHandler[] {
    new MessageHandler3()
};
// Create a message handler chain with an end-point.
var routeHandlers = HttpClientFactory.CreatePipeline(
    new HttpControllerDispatcher(config), handlers);
config.Routes.MapHttpRoute(
    name: "Route2",
    routeTemplate: "api2/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional },
    constraints: null,
    handler: routeHandlers
);

使用Message Handler的例子
跳过inner handler 直接返回response
/// <summary>
/// 跳过inner handler 直接返回response
/// </summary>
public class MyMessageHandler2:DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Create the response.
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("Hello!")
}; // Note: TaskCompletionSource creates a task that does not contain a delegate.
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response); // Also sets the task state to "RanToCompletion"
// return tsc.Task;
return base.SendAsync(request,cancellationToken);
}
}
重写Request method
/// <summary>
/// 重写Request method
/// </summary>
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.InvariantCulture))
{
request.Method = new HttpMethod(method);
}
}
return base.SendAsync(request, cancellationToken);
}
}
WebApi2官网学习记录--HTTP Message Handlers的更多相关文章
- WebApi2官网学习记录--HttpClient Message Handlers
		
在客户端,HttpClient使用message handle处理request.默认的handler是HttpClientHandler,用来发送请求和获取response从服务端.可以在clien ...
 - WebApi2官网学习记录--- Authentication与Authorization
		
Authentication(认证) WebAPI中的认证既可以使用HttpModel也可以使用HTTP message handler,具体使用哪个可以参考一下依据: 一个HttpModel可以 ...
 - WebApi2官网学习记录---批量处理HTTP Message
		
原文:Batching Handler for ASP.NET Web API 自定义实现HttpMessageHandler public class BatchHandler : HttpMess ...
 - WebApi2官网学习记录---Cookie
		
Cookie的几个参数: Domain.Path.Expires.Max-Age 如果Expires与Max-Age都存在,Max-Age优先级高,如果都没有设置cookie会在会话结束后删除cook ...
 - WebApi2官网学习记录---Tracing
		
安装追踪用的包 Install-Package Microsoft.AspNet.WebApi.Tracing Update-Package Microsoft.AspNet.WebApi.WebHo ...
 - WebApi2官网学习记录---异常处理
		
HttpResponseException 当WebAPI的控制器抛出一个未捕获的异常时,默认情况下,大多数异常被转为status code为500的http response即服务端错误. Http ...
 - WebApi2官网学习记录---Html Form Data
		
HTML Forms概述 <form action="api/values" method="post"> 默认的method是GET,如果使用GE ...
 - WebApi2官网学习记录---Configuring
		
Configuration Settings WebAPI中的configuration settings定义在HttpConfiguration中.有一下成员: DependencyResolver ...
 - WebApi2官网学习记录---单元测试
		
如果没有对应的web api模板,首先使用nuget进行安装 例子1: ProductController 是以硬编码的方式使用StoreAppContext类的实例,可以使用依赖注入模式,在外部指定 ...
 
随机推荐
- position:fixed定位时 “高度坍塌”  问题的解决
			
问题:对于固定定位的元素,固定住高度,后面紧跟的模块会当做前面的固定元素不存在似的,这给布局带来了困扰 解决方法: 1.给第二个模块div设置margin-top的值,margin-top的值设为大于 ...
 - C复习手记(Day3)
			
C预处理器 C 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤.简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理.我们将把 C 预处理器 ...
 - 使用F#开发量化模型都缺什么?
			
量化模型多数是基于统计的,因此,统计运算库应该是必备的.在Matlab.R中包含了大量的统计和概率运算,可以说拿来就用,非常方便,相比之下,F#的资源就很少了,这里给大家提供几个链接,可以解决一部分问 ...
 - C#程序调用cmd执行命令-MySql备份还原
			
1.简单实例 //备份还原mysql public static void TestOne() { Process p = new Process(); p.StartInfo.FileName = ...
 - String.PadLeft - 格式对齐
			
语法:public string PadLeft( int totalWidth, char paddingChar ) 概述,实现的效果是右对齐,返回一个总长度为 totalWidth,如果实际长度 ...
 - linux 虚机增加硬盘大小 转自
			
转自http://blog.csdn.net/tongyu2009/article/details/8525384 当我做到#unzip liunx_oracle时候,提示disk full? [ ...
 - Mysql学习(慕课学习笔记8)插入、更新、删除记录
			
插入记录 Insert[]into] tb1_name[(col_name,…..)] 自动编号的字段,可以用values default Default 可以赋予默认值 INSERT USERS V ...
 - WPF、WinForm(C#)多线程编程并更新界面(UI)(转载积累)
			
using System;using System.Collections.Generic;using System.ComponentModel;using System.Drawing;using ...
 - 在Ajax中将数组转换成字符串(0517-am)
			
一.如何在Ajax中将数组转换成字符串 1. 主页面; <head> <meta http-equiv="Content-Type" content=" ...
 - Responder一点也不神秘————iOS用户响应者链完全剖析
			
一.事件分类 对于IOS设备用户来说,他们操作设备的方式主要有三种:触摸屏幕.晃动设备.通过遥控设施控制设备.对应的事件类型有以下三种: 1.触屏事件(Touch Event) 2.运动事件(Moti ...