ASP.NET Web API 管道模型

ASP.NET Web API 管道模型

前言

ASP.NET Web API是一個獨立的框架,也有着本身的一套消息處理管道,無論是在WebHost宿主環境仍是在SelfHost宿主環境請求和響應都是從消息管道通過的,這是必經之地,本篇就爲你們簡單的介紹一下ASP.NET Web API框架中的管道對象模型。web

 

ASP.NET Web API路由、管道

  • ASP.NET Web API 開篇介紹示例
  • ASP.NET Web API 路由對象介紹
  • ASP.NET Web API 管道模型
  • ASP.NET Web API selfhost宿主環境中管道、路由
  • ASP.NET Web API webhost宿主環境中管道、路由

 

 

管道模型介紹

HttpMessageHandler消息處理程序(基類)api

    public abstract class HttpMessageHandler : IDisposable
    {
        protected HttpMessageHandler();
        public void Dispose();
        protected virtual void Dispose(bool disposing);
        protected internal abstract Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
    }

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

而且定義了一個會執行異步操做的SendAsync()方法,這個方法也是串聯管道中各個消息處理程序的一個入口,可是並非靠它來串聯。框架

 

DelegatingHandler消息處理程序(基類)異步

    public abstract class DelegatingHandler : HttpMessageHandler
    {
        protected DelegatingHandler();
        protected DelegatingHandler(HttpMessageHandler innerHandler);
        public HttpMessageHandler InnerHandler { get; set; }

        protected override void Dispose(bool disposing);
        protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
    }

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

 

HttpServer消息處理程序(實現類-管道頭)函數

public class HttpServer : DelegatingHandler
    {
        public HttpServer();
        public HttpServer(HttpConfiguration configuration);
        public HttpServer(HttpMessageHandler dispatcher);
        public HttpServer(HttpConfiguration configuration, HttpMessageHandler dispatcher);
        public HttpConfiguration Configuration { get; }
        public HttpMessageHandler Dispatcher { get; }

        protected override void Dispose(bool disposing);
        protected virtual void Initialize();
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
    }

HttpServer類型繼承自DelegatingHandler類型,是做爲管道中第一個消息處理的,要說明的是重載的這些構造函數,若是隻是採用默認的構造函數的話,HttpConfiguration類型的參數默認的就是實例化HttpConfiguration類型,而HttpMEssageHandler類型的參數默認的是實例化HttpRoutingDispatcher類型的消息處理器,而且是賦值到Dispatcher屬性的,是做爲管道中最後一個消息處理器的(真正的操做實際不是它,後面篇幅會有講到)。this

 

HttpRoutingDispatcher消息處理程序(實現類-管道尾)spa

    public class HttpRoutingDispatcher : HttpMessageHandler
    {
        // Fields
        private readonly HttpConfiguration _configuration;
        private readonly HttpMessageInvoker _defaultInvoker;

        // Methods
        public HttpRoutingDispatcher(HttpConfiguration configuration);
        public HttpRoutingDispatcher(HttpConfiguration configuration, HttpMessageHandler defaultHandler);
        private static void RemoveOptionalRoutingParameters(IDictionary<string, object> routeValueDictionary);
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
    }

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

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

圖1

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

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

首先咱們定義一個消息處理器類型命令爲CustomDelegatingHandler,而且繼承自DelegatingHandler類型。示例代碼以下

代碼1-1

    public class CustomDelegatingHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            Console.WriteLine(request.RequestUri.OriginalString + "____" + request.Method.Method);

            Task<HttpResponseMessage> responseMessage = base.SendAsync(request, cancellationToken);

            Console.WriteLine(responseMessage.Result.RequestMessage.Method.Method);

            return responseMessage;
        }
   }

隨之咱們在SelfHost環境下的服務端在註冊路由以後註冊剛纔咱們新建的消息處理程序對象,示例代碼以下:

代碼1-2

        static void Main(string[] args)
        {
            HttpSelfHostConfiguration selfHostConfiguration =
                new HttpSelfHostConfiguration("http://localhost/selfhost");
            using (HttpSelfHostServer selfHostServer = new HttpSelfHostServer(selfHostConfiguration))
            {
                selfHostServer.Configuration.Routes.MapHttpRoute(
                    "DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
                RegistrationMessageHandler(selfHostServer.Configuration);

                selfHostServer.OpenAsync();

                Console.WriteLine("服務器端服務監聽已開啓");
                Console.Read();
            }

        }
        static void RegistrationMessageHandler(HttpConfiguration httpconfiguration)
        {
            httpconfiguration.MessageHandlers.Add(new HttpMessageHandlers.CustomDelegatingHandler());
        }

 

 

在註冊完畢,而且服務器已經啓動開啓請求監聽,客戶端也隨之發出請求以後,咱們再來看一下客戶端發出的請求以及類型,以下圖。

圖2

這個時候咱們再來看一下服務端管道處理狀況,以下圖。

圖3

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

若是說這樣的示例並不不明顯,不能讓人很清楚明白的瞭解管道的執行過程以及順序,那咱們定義兩個處理程序,而且修改代碼1-1,示例代碼以下:

代碼1-3

    public class CustomDelegatingHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            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);

            return responseMessage;
        }
    }

    public class CustomDelegatingHandler_1 : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            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);

            return responseMessage;
        }
}

隨之咱們註冊管理處理程序的地方也要新增一個消息處理程序,示例代碼以下:

代碼1-4

        static void RegistrationMessageHandler(HttpConfiguration httpconfiguration)
        {
            httpconfiguration.MessageHandlers.Add(new HttpMessageHandlers.CustomDelegatingHandler());
            httpconfiguration.MessageHandlers.Add(new HttpMessageHandlers.CustomDelegatingHandler_1());
        }

這個時候按照圖2以前的那段說明操做,再看一下服務端的管道處理狀況,請求仍是那些個請求,看下示意圖以下:

圖4

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

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

圖5

 

 

做者:金源

出處:http://www.cnblogs.com/jin-yuan/

本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面

相關文章
相關標籤/搜索