標籤: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訊息處理常式(基類)
publicabstractclassHttpMessageHandler : IDisposable { protectedHttpMessageHandler(); publicvoidDispose(); protectedvirtualvoidDispose(booldisposing); protectedinternalabstractTask<HttpResponseMessage>SendAsync(HttpRequestMessagerequest, CancellationTokencancellationToken);}
上面的代碼中定義的是訊息處理常式基類,在管道中的每一個訊息處理部分都是繼承自它。
並且定義了一個會執行非同步作業的SendAsync()方法,這個方法也是串聯管道中各個訊息處理常式的一個入口,但是並不是靠它來串聯。
DelegatingHandler訊息處理常式(基類)
publicabstractclassDelegatingHandler : HttpMessageHandler { protectedDelegatingHandler(); protectedDelegatingHandler(HttpMessageHandlerinnerHandler); publicHttpMessageHandlerInnerHandler { get; set; } protectedoverridevoidDispose(booldisposing); protectedinternaloverrideTask<HttpResponseMessage>SendAsync(HttpRequestMessagerequest, CancellationTokencancellationToken);}
這裡的DelegatingHandler繼承自HttpMessageHandler類型,而且DelegatingHandler也是抽象類別型,DelegatingHandler類型並不是就是簡單的繼承,而是對基類進行了擴充,使之變成一個帶指向箭頭(對象引用)的物件類型也就是InnerHandler屬性,InnerHandler屬性的值就是在當前這個訊息處理常式的下一個訊息處理常式,DelegatingHandler類型對基類的擴充,HttpMessageHandler類型我感覺它的存在就是一個規範,從管道中的第一個處理常式開始一直到最後一個,除了最後一個訊息處理常式,其他的都是DelegatingHandler類型的子類(當然也是HttpMessageHandler的子類),最後一個訊息處理常式是直接繼承自HttpMessageHandler類型,因為它是最後一個處理常式了不必要有指向下一個處理常式的屬性,這種對職責的劃分真的很優美,說不出好在哪就是覺得漂亮。
HttpServer訊息處理常式(實作類別-管道頭)
publicclassHttpServer : DelegatingHandler { publicHttpServer(); publicHttpServer(HttpConfigurationconfiguration); publicHttpServer(HttpMessageHandlerdispatcher); publicHttpServer(HttpConfigurationconfiguration, HttpMessageHandlerdispatcher); publicHttpConfigurationConfiguration { get; } publicHttpMessageHandlerDispatcher { get; } protectedoverridevoidDispose(booldisposing); protectedvirtualvoidInitialize(); protectedoverrideTask<HttpResponseMessage>SendAsync(HttpRequestMessagerequest, CancellationTokencancellationToken);}
HttpServer類型繼承自DelegatingHandler類型,是作為管道中第一個訊息處理的,要說明的是重載的這些建構函式,如果只是採用預設的建構函式的話,HttpConfiguration類型的參數預設的就是執行個體化HttpConfiguration類型,而HttpMEssageHandler類型的參數預設的是執行個體化HttpRoutingDispatcher類型的訊息處理器,並且是賦值到Dispatcher屬性的,是作為管道中最後一個訊息處理器的(真正的操作實際不是它,後面篇幅會有講到)。
HttpRoutingDispatcher訊息處理常式(實作類別-管道尾)
publicclassHttpRoutingDispatcher : HttpMessageHandler { //Fields privatereadonlyHttpConfiguration_configuration; privatereadonlyHttpMessageInvoker_defaultInvoker; //Methods publicHttpRoutingDispatcher(HttpConfigurationconfiguration); publicHttpRoutingDispatcher(HttpConfigurationconfiguration, HttpMessageHandlerdefaultHandler); privatestaticvoidRemoveOptionalRoutingParameters(IDictionary<string, object>routeValueDictionary); protectedoverrideTask<HttpResponseMessage>SendAsync(HttpRequestMessagerequest, CancellationTokencancellationToken);}
HttpRoutingDispatcher類型繼承自HttpMessageHandler類型,上面也說到過它是作為在管道中最後一個訊息處理器的,說是可以這麼說,但是真正執行的卻不是它,而是在執行重載的建構函式的時候會預設的產生HttpControllerDispatcher類型作為HttpMessageHandler類型的建構函式參數,這裡就不對它進行過多的闡述了,後面的篇幅自然會說明的很詳細。
下面我們來看一下ASP.NET Web API管道的大概。
圖1
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/44/36/wKiom1PgKSfT4RsYAAHCZPgZAb0108.jpg" title="webapi1.png" width="738" height="203" border="0" hspace="0" vspace="0" style="width:738px;height:203px;" alt="wKiom1PgKSfT4RsYAAHCZPgZAb0108.jpg" />
(藍色線條表示請求,紅色線條表示響應)
這樣的說明的不是太清晰下面我們用《ASP.NET Web API 開篇介紹樣本》中的SelfHost環境下的樣本來示範一下,這樣大家自然就會清楚這個流程了。
首先我們定義一個訊息處理器類型命令為CustomDelegatingHandler,並且繼承自DelegatingHandler類型。範例程式碼如下
代碼1-1
publicclassCustomDelegatingHandler : DelegatingHandler { protectedoverrideTask<HttpResponseMessage>SendAsync(HttpRequestMessagerequest, System.Threading.CancellationTokencancellationToken) { Console.WriteLine(request.RequestUri.OriginalString+"____"+request.Method.Method); Task<HttpResponseMessage>responseMessage=base.SendAsync(request, cancellationToken); Console.WriteLine(responseMessage.Result.RequestMessage.Method.Method); returnresponseMessage; }}
隨之我們在SelfHost環境下的服務端在註冊路由之後註冊剛才我們建立的訊息處理常式對象,範例程式碼如下:
代碼1-2
staticvoidMain(string[] args) { HttpSelfHostConfigurationselfHostConfiguration= newHttpSelfHostConfiguration("http://localhost/selfhost"); using (HttpSelfHostServerselfHostServer=newHttpSelfHostServer(selfHostConfiguration)) { selfHostServer.Configuration.Routes.MapHttpRoute( "DefaultApi", "api/{controller}/{id}", new { id=RouteParameter.Optional }); RegistrationMessageHandler(selfHostServer.Configuration); selfHostServer.OpenAsync(); Console.WriteLine("伺服器端服務監聽已開啟"); Console.Read(); } } staticvoidRegistrationMessageHandler(HttpConfigurationhttpconfiguration) { httpconfiguration.MessageHandlers.Add(newHttpMessageHandlers.CustomDelegatingHandler()); }
在註冊完畢,並且伺服器已經啟動開啟請求監聽,用戶端也隨之發出請求之後,我們再來看一下用戶端發出的請求以及類型,如。
圖2
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/44/36/wKioL1PgKmfShi5LAAOgbQwgN90619.jpg" title="webapi2.png" alt="wKioL1PgKmfShi5LAAOgbQwgN90619.jpg" />
這個時候我們再來看一下服務端管道處理情況,如。
圖3
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/44/36/wKiom1PgKVuSY0HmAAJFEVKTkr0744.jpg" title="webapi3.png" alt="wKiom1PgKVuSY0HmAAJFEVKTkr0744.jpg" />
每一個紅框圈中的部分都表示著一個請求和響應的流程跟圖2中的所有請求是對應的,可以從代碼1-1中就可以看出輸出的內容。
如果說這樣的樣本並不不明顯,不能讓人很清楚明白的瞭解管道的執行過程以及順序,那我們定義兩個處理常式,並且修改代碼1-1,範例程式碼如下:
代碼1-3
publicclassCustomDelegatingHandler : DelegatingHandler { protectedoverrideTask<HttpResponseMessage>SendAsync(HttpRequestMessagerequest, System.Threading.CancellationTokencancellationToken) { Console.WriteLine(this.GetType().Name+":"+request.RequestUri.OriginalString+"____"+request.Method.Method); Task<HttpResponseMessage>responseMessage=base.SendAsync(request, cancellationToken); Console.WriteLine(this.GetType().Name+":"+responseMessage.Result.RequestMessage.Method.Method); returnresponseMessage; } } publicclassCustomDelegatingHandler_1 : DelegatingHandler { protectedoverrideTask<HttpResponseMessage>SendAsync(HttpRequestMessagerequest, System.Threading.CancellationTokencancellationToken) { Console.WriteLine(this.GetType().Name+":"+request.RequestUri.OriginalString+"____"+request.Method.Method); Task<HttpResponseMessage>responseMessage=base.SendAsync(request, cancellationToken); Console.WriteLine(this.GetType().Name+":"+responseMessage.Result.RequestMessage.Method.Method); returnresponseMessage; }}
隨之我們註冊管理處理常式的地方也要新增一個訊息處理常式,範例程式碼如下:
代碼1-4
staticvoidRegistrationMessageHandler(HttpConfigurationhttpconfiguration) { httpconfiguration.MessageHandlers.Add(newHttpMessageHandlers.CustomDelegatingHandler()); httpconfiguration.MessageHandlers.Add(newHttpMessageHandlers.CustomDelegatingHandler_1()); }
這個時候按照圖2之前的那段說明操作,再看一下服務端的管道處理情況,請求還是那些個請求,看下如下:
圖4
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/44/36/wKioL1PgKpSjE3ptAARBy2XFCd0591.jpg" title="webapi4.png" alt="wKioL1PgKpSjE3ptAARBy2XFCd0591.jpg" />
(紅框部分的代表就是跟上面所說的一樣,一個請求一個響應管道所對應的處理情況)
最後再看一5結合圖4,這樣更好更容易理解。
圖5
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/44/36/wKiom1PgKYmQ05LqAAHeTWgc08Q737.jpg" title="webapi14.png" width="738" height="216" border="0" hspace="0" vspace="0" style="width:738px;height:216px;" alt="wKiom1PgKYmQ05LqAAHeTWgc08Q737.jpg" />
本文出自 “金源” 部落格,請務必保留此出處http://jinyuan.blog.51cto.com/8854733/1535778