天天看點

ASP.NET Web API 管道模型ASP.NET Web API 管道模型

前言

ASP.NET Web API是一個獨立的架構,也有着自己的一套消息處理管道,不管是在WebHost宿主環境還是在SelfHost宿主環境請求和響應都是從消息管道經過的,這是必經之地,本篇就為大家簡單的介紹一下ASP.NET Web API架構中的管道對象模型。

ASP.NET Web API路由、管道

l  ASP.NET Web API 開篇介紹示例

l  ASP.NET Web API 路由對象介紹

l  ASP.NET Web API 管道模型

l  ASP.NET Web API selfhost宿主環境中管道、路由

l  ASP.NET Web API webhost宿主環境中管道、路由

管道模型介紹

HttpMessageHandler消息處理程式(基類)

1

2

3

4

5

6

7

<code>   </code><code>publicabstractclassHttpMessageHandler : IDisposable</code>

<code>   </code><code>{</code>

<code>        </code><code>protectedHttpMessageHandler();</code>

<code>        </code><code>publicvoidDispose();</code>

<code>        </code><code>protectedvirtualvoidDispose(booldisposing);</code>

<code>        </code><code>protectedinternalabstractTask&lt;HttpResponseMessage&gt;SendAsync(HttpRequestMessagerequest, CancellationTokencancellationToken);</code>

<code>}</code>

上面的代碼中定義的是消息處理程式基類,在管道中的每一個消息處理部分都是繼承自它。

并且定義了一個會執行異步操作的SendAsync()方法,這個方法也是串聯管道中各個消息處理程式的一個入口,但是并不是靠它來串聯。

DelegatingHandler消息處理程式(基類)

8

9

<code>   </code><code>publicabstractclassDelegatingHandler : HttpMessageHandler</code>

<code>        </code><code>protectedDelegatingHandler();</code>

<code>        </code><code>protectedDelegatingHandler(HttpMessageHandlerinnerHandler);</code>

<code>        </code><code>publicHttpMessageHandlerInnerHandler { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code> </code> 

<code>        </code><code>protectedoverridevoidDispose(booldisposing);</code>

<code>        </code><code>protectedinternaloverrideTask&lt;HttpResponseMessage&gt;SendAsync(HttpRequestMessagerequest, CancellationTokencancellationToken);</code>

這裡的DelegatingHandler繼承自HttpMessageHandler類型,而且DelegatingHandler也是抽象類型,DelegatingHandler類型并不是就是簡單的繼承,而是對基類進行了擴充,使之變成一個帶指向箭頭(對象引用)的對象類型也就是InnerHandler屬性,InnerHandler屬性的值就是在目前這個消息處理程式的下一個消息處理程式,DelegatingHandler類型對基類的擴充,HttpMessageHandler類型我感覺它的存在就是一個規範,從管道中的第一個處理程式開始一直到最後一個,除了最後一個消息處理程式,其他的都是DelegatingHandler類型的子類(當然也是HttpMessageHandler的子類),最後一個消息處理程式是直接繼承自HttpMessageHandler類型,因為它是最後一個處理程式了不必要有指向下一個處理程式的屬性,這種對職責的劃分真的很優美,說不出好在哪就是覺得漂亮。

HttpServer消息處理程式(實作類-管道頭)

10

11

12

13

<code>publicclassHttpServer : DelegatingHandler</code>

<code>        </code><code>publicHttpServer();</code>

<code>        </code><code>publicHttpServer(HttpConfigurationconfiguration);</code>

<code>        </code><code>publicHttpServer(HttpMessageHandlerdispatcher);</code>

<code>        </code><code>publicHttpServer(HttpConfigurationconfiguration, HttpMessageHandlerdispatcher);</code>

<code>        </code><code>publicHttpConfigurationConfiguration { </code><code>get</code><code>; }</code>

<code>        </code><code>publicHttpMessageHandlerDispatcher { </code><code>get</code><code>; }</code>

<code>        </code><code>protectedvirtualvoidInitialize();</code>

<code>        </code><code>protectedoverrideTask&lt;HttpResponseMessage&gt;SendAsync(HttpRequestMessagerequest, CancellationTokencancellationToken);</code>

HttpServer類型繼承自DelegatingHandler類型,是作為管道中第一個消息處理的,要說明的是重載的這些構造函數,如果隻是采用預設的構造函數的話,HttpConfiguration類型的參數預設的就是執行個體化HttpConfiguration類型,而HttpMEssageHandler類型的參數預設的是執行個體化HttpRoutingDispatcher類型的消息處理器,并且是指派到Dispatcher屬性的,是作為管道中最後一個消息處理器的(真正的操作實際不是它,後面篇幅會有講到)。

HttpRoutingDispatcher消息處理程式(實作類-管道尾)

<code>   </code><code>publicclassHttpRoutingDispatcher : HttpMessageHandler</code>

<code>        </code><code>//Fields</code>

<code>        </code><code>privatereadonlyHttpConfiguration_configuration;</code>

<code>        </code><code>privatereadonlyHttpMessageInvoker_defaultInvoker;</code>

<code>        </code><code>//Methods</code>

<code>        </code><code>publicHttpRoutingDispatcher(HttpConfigurationconfiguration);</code>

<code>        </code><code>publicHttpRoutingDispatcher(HttpConfigurationconfiguration, HttpMessageHandlerdefaultHandler);</code>

<code>        </code><code>privatestaticvoidRemoveOptionalRoutingParameters(IDictionary&lt;</code><code>string</code><code>, </code><code>object</code><code>&gt;routeValueDictionary);</code>

HttpRoutingDispatcher類型繼承自HttpMessageHandler類型,上面也說到過它是作為在管道中最後一個消息處理器的,說是可以這麼說,但是真正執行的卻不是它,而是在執行重載的構造函數的時候會預設的生成HttpControllerDispatcher類型作為HttpMessageHandler類型的構造函數參數,這裡就不對它進行過多的闡述了,後面的篇幅自然會說明的很詳細。

下面我們來看一下ASP.NET Web API管道的大概示意圖。

圖1

<a href="http://s3.51cto.com/wyfs02/M02/44/36/wKiom1PgKSfT4RsYAAHCZPgZAb0108.jpg" target="_blank"></a>

(藍色線條表示請求,紅色線條表示響應)

這樣的示意圖說明的不是太清晰下面我們用《ASP.NET Web API 開篇介紹示例》中的SelfHost環境下的示例來示範一下,這樣大家自然就會清楚這個流程了。

首先我們定義一個消息處理器類型指令為CustomDelegatingHandler,并且繼承自DelegatingHandler類型。示例代碼如下

代碼1-1

<code>   </code><code>publicclassCustomDelegatingHandler : DelegatingHandler</code>

<code>        </code><code>protectedoverrideTask&lt;HttpResponseMessage&gt;SendAsync(HttpRequestMessagerequest, System.Threading.CancellationTokencancellationToken)</code>

<code>        </code><code>{</code>

<code>            </code><code>Console.WriteLine(request.RequestUri.OriginalString+</code><code>"____"</code><code>+request.Method.Method);</code>

<code>            </code><code>Task&lt;HttpResponseMessage&gt;responseMessage=</code><code>base</code><code>.SendAsync(request, cancellationToken);</code>

<code>            </code><code>Console.WriteLine(responseMessage.Result.RequestMessage.Method.Method);</code>

<code>            </code><code>returnresponseMessage;</code>

<code>        </code><code>}</code>

随之我們在SelfHost環境下的服務端在注冊路由之後注冊剛才我們建立的消息處理程式對象,示例代碼如下:

代碼1-2

14

15

16

17

18

19

20

21

<code>staticvoidMain(</code><code>string</code><code>[] args)</code>

<code>            </code><code>HttpSelfHostConfigurationselfHostConfiguration=</code>

<code>                </code><code>newHttpSelfHostConfiguration(</code><code>"http://localhost/selfhost"</code><code>);</code>

<code>            </code><code>using</code> <code>(HttpSelfHostServerselfHostServer=newHttpSelfHostServer(selfHostConfiguration))</code>

<code>            </code><code>{</code>

<code>                </code><code>selfHostServer.Configuration.Routes.MapHttpRoute(</code>

<code>                    </code><code>"DefaultApi"</code><code>, </code><code>"api/{controller}/{id}"</code><code>, </code><code>new</code> <code>{ id=RouteParameter.Optional });</code>

<code>                </code><code>RegistrationMessageHandler(selfHostServer.Configuration);</code>

<code>                </code><code>selfHostServer.OpenAsync();</code>

<code>                </code><code>Console.WriteLine(</code><code>"伺服器端服務監聽已開啟"</code><code>);</code>

<code>                </code><code>Console.Read();</code>

<code>            </code><code>}</code>

<code>        </code><code>staticvoidRegistrationMessageHandler(HttpConfigurationhttpconfiguration)</code>

<code>            </code><code>httpconfiguration.MessageHandlers.Add(newHttpMessageHandlers.CustomDelegatingHandler());</code>

在注冊完畢,并且伺服器已經啟動開啟請求監聽,用戶端也随之送出請求之後,我們再來看一下用戶端發出的請求以及類型,如下圖。

圖2

<a href="http://s3.51cto.com/wyfs02/M01/44/36/wKioL1PgKmfShi5LAAOgbQwgN90619.jpg" target="_blank"></a>

這個時候我們再來看一下服務端管道處理情況,如下圖。

圖3

<a href="http://s3.51cto.com/wyfs02/M00/44/36/wKiom1PgKVuSY0HmAAJFEVKTkr0744.jpg" target="_blank"></a>

每一個紅框圈中的部分都表示着一個請求和響應的流程跟圖2中的所有請求是對應的,可以從代碼1-1中就可以看出輸出的内容。

如果說這樣的示例并不不明顯,不能讓人很清楚明白的了解管道的執行過程以及順序,那我們定義兩個處理程式,并且修改代碼1-1,示例代碼如下:

代碼1-3

22

23

24

25

26

27

<code>            </code><code>Console.WriteLine(</code><code>this</code><code>.GetType().Name+</code><code>":"</code><code>+request.RequestUri.OriginalString+</code><code>"____"</code><code>+request.Method.Method);</code>

<code>            </code><code>Console.WriteLine(</code><code>this</code><code>.GetType().Name+</code><code>":"</code><code>+responseMessage.Result.RequestMessage.Method.Method);</code>

<code>   </code><code>}</code>

<code>   </code><code>publicclassCustomDelegatingHandler_1 : DelegatingHandler</code>

随之我們注冊管理處理程式的地方也要新增一個消息處理程式,示例代碼如下:

代碼1-4

<code>            </code><code>httpconfiguration.MessageHandlers.Add(newHttpMessageHandlers.CustomDelegatingHandler_1());</code>

這個時候按照圖2之前的那段說明操作,再看一下服務端的管道處理情況,請求還是那些個請求,看下示意圖如下:

圖4

<a href="http://s3.51cto.com/wyfs02/M02/44/36/wKioL1PgKpSjE3ptAARBy2XFCd0591.jpg" target="_blank"></a>

(紅框部分的代表就是跟上面所說的一樣,一個請求一個響應管道所對應的處理情況)

最後再看一下圖5結合圖4,這樣更好更容易了解。

圖5

<a href="http://s3.51cto.com/wyfs02/M01/44/36/wKiom1PgKYmQ05LqAAHeTWgc08Q737.jpg" target="_blank"></a>

     本文轉自jinyuan0829 51CTO部落格,原文連結:http://blog.51cto.com/jinyuan/1535778,如需轉載請自行聯系原作者

繼續閱讀