您好,登錄后才能下訂單哦!
前言
前面的幾個(gè)篇幅對(duì)Web API中的路由和管道進(jìn)行了簡(jiǎn)單的介紹并沒(méi)有詳細(xì)的去說(shuō)明一些什么,然而ASP.NET Web API這個(gè)框架由于宿主環(huán)境的不同在不同的宿主環(huán)境中管道中的實(shí)現(xiàn)機(jī)制和路由的處理方式有著很大的不同,所以我會(huì)將對(duì)應(yīng)不同的宿主環(huán)境來(lái)分別的做出簡(jiǎn)單的講解。
ASP.NET Web API 開(kāi)篇介紹示例
ASP.NET Web API 路由對(duì)象介紹
ASP.NET Web API 管道模型
ASP.NET Web API selfhost宿主環(huán)境中管道、路由
ASP.NET Web API webhost宿主環(huán)境中管道、路由
首先我們先來(lái)看個(gè)示意圖,大概的描述了在SelfHost宿主環(huán)境中管道形態(tài)。
圖1
因?yàn)樵?/span>WebHost宿主環(huán)境中ASP.NET Web API的管道請(qǐng)求接收以及響應(yīng)的返回最后都是由ASP.NET來(lái)包辦的(下一篇中講解),而在SelfHost宿主環(huán)境中就苦逼了,沒(méi)有那么簡(jiǎn)單了。
我們按照?qǐng)D1中示意的來(lái)講解,首先在SelfHost宿主環(huán)境中的項(xiàng)目啟動(dòng)之后(當(dāng)然項(xiàng)目要使用Web API框架的),會(huì)有一個(gè)HttpBinding對(duì)象(System.Web.Http.SelfHost.Channels),那這個(gè)HttpBinding類型的對(duì)象是干嘛的呢?Httpbinding對(duì)象對(duì)應(yīng)著一些個(gè)BindingElement對(duì)象,而這些BindingElement又各自生成對(duì)應(yīng)的管道層監(jiān)聽(tīng)器,這樣就如圖1中所示的那樣,現(xiàn)在我們看一下如下的示例代碼,看看HttpBinding到底對(duì)應(yīng)著哪些BindingElement對(duì)象。
示例代碼1-1
publicclassHttpBinding : Binding, IBindingRuntimePreferences { publicHttpBinding() { this.Initialize(); } privatevoidInitialize() { this._security=newHttpBindingSecurity(); this._httpTransportBindingElement=newHttpTransportBindingElement(); this._httpTransportBindingElement.ManualAddressing=true; this._httpsTransportBindingElement=newHttpsTransportBindingElement(); this._httpsTransportBindingElement.ManualAddressing=true; this._httpMessageEncodingBindingElement=newHttpMessageEncodingBindingElement(); } }
在示例代碼1-1中我們可以清楚的看到在HttpBinding對(duì)象的構(gòu)造函數(shù)中分別的對(duì)幾種BindingElement進(jìn)行了實(shí)例化賦值,我們只對(duì)其中的HttpTransportBindingElement和HttpMessageEncodingBindingElement進(jìn)行講解也就是圖1中所示的那樣。
HttpTransportBindingElement對(duì)象的主要職責(zé)就是生成相對(duì)應(yīng)的管道監(jiān)聽(tīng)器,這里對(duì)應(yīng)的就是IChannelListener<TChannel>泛型類型了,而生成好對(duì)應(yīng)的管道監(jiān)聽(tīng)器之后,監(jiān)聽(tīng)器之后會(huì)開(kāi)始監(jiān)聽(tīng)與之對(duì)應(yīng)的管道層,與HttpTransportBindingElement對(duì)象以及監(jiān)聽(tīng)器對(duì)應(yīng)的也就是TransprotChannel管道層了,它負(fù)責(zé)請(qǐng)求消息的接收和響應(yīng)消息的發(fā)送。
HttpMessageEncodingBindingElement類型的對(duì)象所做操作同HttpTransportBindingElement類型一致,都是先要生成對(duì)應(yīng)的管道監(jiān)聽(tīng)器,在這里與之對(duì)應(yīng)的就是HttpMessageEncodingChannelListener類型,在監(jiān)聽(tīng)器生成好之后也會(huì)去監(jiān)聽(tīng)對(duì)應(yīng)的EncodingChannel管道層,而EncodingChannel管道層主要的作用就是將請(qǐng)求信息封裝為HttpMessage類型的消息對(duì)象,之后由HttpMessage消息對(duì)象進(jìn)入ASP.NET Web API框架的管道系統(tǒng)中。
上面說(shuō)的是在請(qǐng)求未到達(dá)ASP.NET Web API框架的管道系統(tǒng)中的時(shí)候在外部的一些處理和操作,下面我們就要說(shuō)明一下內(nèi)部,在上篇的《ASP.NET Web API 管道模型》篇幅中有示例代碼演示過(guò)在SelfHost環(huán)境下管道的注冊(cè),我們這里看一下在SelfHost環(huán)境中Web API框架自身的管道系統(tǒng)里的對(duì)象的一些類型。
HttpSelfHostServer消息處理程序(實(shí)現(xiàn)類-管道頭)System.Web.Http.SelfHost
publicsealedclassHttpSelfHostServer : HttpServer { publicHttpSelfHostServer(HttpSelfHostConfigurationconfiguration); publicHttpSelfHostServer(HttpSelfHostConfigurationconfiguration, HttpMessageHandlerdispatcher); publicTaskCloseAsync(); protectedoverridevoidDispose(booldisposing); publicTaskOpenAsync(); }
可以看到HttpSelfHostServer類型繼承自HttpServer,在上篇中我們也就提到過(guò)HttpServer是繼承自DelegatingHandler抽象類型的消息處理程序基類,DelegatingHandler與HttpMessageHandler的不同之處就是多了個(gè)指向下一個(gè)處理程序的引用,當(dāng)然了作為一個(gè)管道系統(tǒng)中第一個(gè)消息處理程序必須是要有指向下一個(gè)處理程序引用的這么一個(gè)標(biāo)識(shí),這樣是合理的。我們?cè)倏?/span>HttpSelfHostServer類型的構(gòu)造函數(shù)的參數(shù)類型。
HttpSelfHostConfiguration類型是繼承自HttpConfiguration類型的,在上篇中我們也說(shuō)過(guò),HttpConfiguration中可以配置管道中的大多數(shù)信息,這個(gè)大家可以自己去看一下。在重載構(gòu)造函數(shù)中有了第二個(gè)構(gòu)造函數(shù)參數(shù),HttpMessageHandler類型的參數(shù),在默認(rèn)使用HttpSelfHostServer的時(shí)候假使不使用這個(gè)重載的構(gòu)造函數(shù),那么在HttpSelfHostServer實(shí)例化的之前先實(shí)例化之前,其基類HttpServer的構(gòu)造函數(shù)開(kāi)始執(zhí)行,所以在看下HttpServer類型的構(gòu)造函數(shù)的時(shí)候我們可以看到這里默認(rèn)設(shè)置的HttpMessageHandler類型的參數(shù)到底是什么樣子的。
publicHttpServer() : this(newHttpConfiguration()) { } publicHttpServer(HttpMessageHandlerdispatcher) : this(newHttpConfiguration(), dispatcher) { } publicHttpServer(HttpConfigurationconfiguration) : this(configuration, newHttpRoutingDispatcher(configuration)) { } publicHttpServer(HttpConfigurationconfiguration, HttpMessageHandlerdispatcher) { this._initializationLock=newobject(); if (configuration==null) { throwSystem.Web.Http.Error.ArgumentNull("configuration"); } if (dispatcher==null) { throwSystem.Web.Http.Error.ArgumentNull("dispatcher"); } this._dispatcher=dispatcher; this._configuration=configuration; }
這里大家可以清楚的看到是HttpRoutingDispatcher類型作為管道的最后一個(gè)處理程序的類型,對(duì)于這個(gè)類型以及詳細(xì)的信息,在下面的路由小節(jié)中會(huì)有說(shuō)明。
對(duì)于路由的其他知識(shí)這里就不說(shuō)了,就是簡(jiǎn)要的提一下在SelfHost中路由、管道的一些細(xì)節(jié)。
圖2
這里要詳細(xì)說(shuō)明的就是HttpRoutingDispatcher類型中的SendAsync()方法,看下源碼中的實(shí)現(xiàn)這樣更清楚。
publicclassHttpRoutingDispatcher : HttpMessageHandler { //Fields privatereadonlyHttpConfiguration_configuration; privatereadonlyHttpMessageInvoker_defaultInvoker; //Methods publicHttpRoutingDispatcher(HttpConfigurationconfiguration) : this(configuration, newHttpControllerDispatcher(configuration)) { } protectedoverrideTask<HttpResponseMessage>SendAsync(HttpRequestMessagerequest, CancellationTokencancellationToken) { IHttpRouteDatarouteData; if (!request.Properties.TryGetValue<IHttpRouteData>(HttpPropertyKeys.HttpRouteDataKey, outrouteData)) { routeData=this._configuration.Routes.GetRouteData(request); if (routeData==null) { returnTaskHelpers.FromResult<HttpResponseMessage>(request.CreateErrorResponse(HttpStatusCode.NotFound, Error.Format(SRResources.ResourceNotFound, newobject[] { request.RequestUri }), SRResources.NoRouteData)); } request.Properties.Add(HttpPropertyKeys.HttpRouteDataKey, routeData); } RemoveOptionalRoutingParameters(routeData.Values); HttpMessageInvokerinvoker= (routeData.Route.Handler==null) ?this._defaultInvoker : newHttpMessageInvoker(routeData.Route.Handler, false); returninvoker.SendAsync(request, cancellationToken); } }
我們先看一下HttpRoutingDispatcher類型中構(gòu)造函數(shù),可以看到在定義的構(gòu)造函數(shù)后面緊接著又在實(shí)例基類的構(gòu)造函數(shù),并且第二個(gè)HttpMessageHandler類型的參數(shù)為HttpControllerDispatcher實(shí)例的對(duì)象,這個(gè)我們先記住就行了。
下面我們還是回到HttpRoutingDispatcher類型的SendAsync()方法中,首先我們會(huì)看到從HttpRequestMessage對(duì)象實(shí)例的Properties屬性集合中獲取路由數(shù)據(jù)對(duì)象。
在SelfHost的環(huán)境下這是獲取不到的,為啥?因?yàn)樯厦嬉约爸暗钠性诠艿赖奶幚碇袥](méi)有提到過(guò)處理路由并且生成路由數(shù)據(jù)的。所以這個(gè)時(shí)候會(huì)根據(jù)HttpConfiguration中的HttpRouteCollection類型的屬性Routes,Routes屬性再根據(jù)SendAsync()方法的參數(shù)類型為HttpRequestMessage的request信息獲取路由數(shù)據(jù)對(duì)象IHttpRouteData。
在匹配成功獲取到路由數(shù)據(jù)對(duì)象(IHttpRouteData)之后便會(huì)添加至HttpRequestMessage對(duì)象實(shí)例(request)的Properties屬性集合中。
之前對(duì)于路由的了解,最后的執(zhí)行的Handler都是起初定義在路由對(duì)象中的,而在實(shí)際情況中,我們注冊(cè)路由的時(shí)候并沒(méi)有,假使這種情況就在現(xiàn)在發(fā)生,可以看到routeData.Route.Hander==null這個(gè)是成立的,所以執(zhí)行的是我們先前說(shuō)過(guò)的在構(gòu)造函數(shù)中的HttpControllerDispatcher類型的實(shí)例的SendAsync()方法(實(shí)際當(dāng)中HttpControllerDispatcher類型被HttpMessageInvoker類型所封裝)。
而HttpControllerDispatcher類型就跟Web API控制器有關(guān)了,這里就不提前說(shuō)了,后面一定會(huì)講到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。