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

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

wKioL1PgKmfShi5LAAOgbQwgN90619.jpg

 

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

3

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

wKioL1PgKpSjE3ptAARBy2XFCd0591.jpg

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

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

5

wKiom1PgKYmQ05LqAAHeTWgc08Q737.jpg


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章