HttpMessageHandler管道
在Web API的中,微軟為了更好的進行架構擴展,采用的了一套管道設計----HttpMessageHander(其實WCF也有類似架構).

在整個管道中的頭與尾分別是HttpServer、HttpRoutingDispatcher,它們都繼承HttpMessageHandler,其中ASP.NET 為我們預留了可擴展的DelegatingHandler,下面我們就來看看幾個類之前的關系。
SendAsync為處理請求的方法。在DelegatingHandler中有一類型為HttpMessageHandler的屬性InnerHandler。它是構成管道的關鍵。因為有了這個屬性所以的DelegatingHandler都能夠串聯起來,逐步去經過管道中的每個DelegatingHandler
在HttpServer有兩個新添加的屬性Configuration與Dispatcher,其中Dispatcher指向管道的尾HttpRoutingDispatcher.在HttpConfiguration有一類型為Collection< DelegatingHandler>的屬性MessageHandlers,我們這個集合中添加自定義的DelegatingHandler就可以添加到整個管道中。所以我們可以看出HttpServer中基本已經定義的整個HttpMessagHandler管道。
下面我們定義一個可以進行請求方式Post與Put(當然這只是個例子)
public class HttpMethodChangeHandler : DelegatingHandler
{
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
var method = request.Method;
if(request.Method == HttpMethod.Post)
{
request.Method = HttpMethod.Put;
}
else if(request.Method == HttpMethod.Put)
{
request.Method = HttpMethod.Post;
}
return base.SendAsync(request, cancellationToken);
}
}
我們在HttpApplication.Application_Start中加添加如下語句
GlobalConfiguration.Configure(t => t.MessageHandlers.Add(new HttpMethodChangeHandler()));
在DemoController中定義了Put,Post方法
[HttpPost]
public string Post()
{
return "這是一個Post方法";
}
[HttpPut]
public string Put()
{
return "這是一個Put方法";
}
下面是這四種測試結果:
url:http://localhost:41666/api/Demo/Put Method:Post
結果:"這是一個Put方法"
url: http://localhost:41666/api/Demo/Put Method:Put
結果:{"Message":"請求的資源不支持 http 方法"POST"。"}
url:http://localhost:41666/api/Demo/Post Method:Put
結果:"這是一個Post方法"
url: http://localhost:41666/api/Demo/Post Method:Post
結果:{"Message":"請求的資源不支持 http 方法"PUT"。"}
另外我們再在DemoController定義一個獲取自定義DelegatingHandler的方法GetChains
public IEnumerable<string> GetChains()
{
IEnumerable<string> result = GetChains(GlobalConfiguration.DefaultServer);
return result;
}
private IEnumerable<string> GetChains(DelegatingHandler handler)
{
yield return handler.GetType().FullName;
var innerHander = handler.InnerHandler as DelegatingHandler;
if (innerHander != null)
{
yield return innerHander.GetType().FullName;
}
}

源碼
Github: https://github.com/BarlowDu/WebAPI (API_6)
