麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

Self Host模式下的ASP. NET Web API是如何進行請求的監聽與處理的?

2019-11-17 01:26:33
字體:
來源:轉載
供稿:網友

Self Host模式下的asp. NET Web API是如何進行請求的監聽與處理的?

構成asp.net Web API核心框架的消息處理管道既不關心請求消息來源于何處,也不需要考慮響應消息歸于何方。當我們采用Web Host模式將一個ASP.NET應用作為目標Web API的宿主時,實際上是由ASP.NET管道解決了這兩個問題。具體來說,ASP.NET自身的URL路由系統借助于HttpControllerHandler這個自定義的HttpHandler實現了ASP.NET管道和ASP.NET Web API管道之間的“連通”,但是在Self Host寄宿模式下,請求的監聽、接收和響應又是如何實現的呢?[本文已經同步到《How ASP.NET Web API Works?》]

目錄 一、HttpBinding模型     Binding模型     HttpBinding     實例演示:直接利用HttpBinding進行請求的接收和響應 二、HttpSelfHostServer     HttpSelfHostConfiguration     HttpSelfHostServer與消息處理管道     實例演示:創建自定義HttpServer模擬HttpSelfHostServer的工作原理

一、HttpBinding模型

和WCF服務一樣,我們可以采用Self Host模式將Web API寄宿于任何一種類型的托管應用程序下,宿主可以是一個Windows Form應用、WPF應用、控制臺應用以及Windows Service。Self Host模式下的WCF和ASP.NET Web API不僅外在表現形式極為相似,其實在內部實現原理上也是一致的。

Binding模型

對于WCF具有基本了解的讀者應該都知道,它是一個基于消息的分布式通信框架,消息交換借助于客戶端和服務端對等的終結點(Endpoint)來完成,而終結點由經典的ABC(Address、Binding、Contract)三元素組成。WCF同樣具有一個處理消息的管道,這個管道是一組Channel的有序組合,WCF下的Channel相對于ASP.NET Web API下的HttpMessageHandler。

WCF的消息處理管道的締造者是作為終結點三要素之一的Binding。Binding不僅僅為服務端創建用于接收請求回復響應的管道,同時也為客戶端創建發送請求接收響應的管道。Binding模型本身也相對比較復雜,所以我們不可能對其進行詳細討論。如果讀者對此比較感興趣,可以參閱《WCF的綁定模型》。由于ASP.NET Web API只是利用HttpBinding創建服務端消息處理管道,所以我們只討論Binding的服務端模型。

從結構上講,一個Binding是若干BindingElement對象的有序組合。對于最終創建的消息處理管道來說,每個Channel都對應著一個BindingElement。BindingElement并非直接創建對應的Channel,由它直接創建的實際上是一個名為ChannelListener的對象,Channel由ChannelListener創建。右圖基本揭示了Binding的服務端模型。

顧名思義,ChannelListener用于請求的監聽。當Binding對象開啟(調用其Open方法)時,每個BindingElement會創建各自的ChannelListener。這些ChannelListener按照對應BindingElement的順序連接成串,位于底部(面向傳輸層)的ChannelListener被綁定到某個端口進行請求的監聽。一旦探測到抵達的請求,它會利用由所有ChannelListener創建的Channel組成的管道來接收并處理該請求。對于最終需要返回的響應消息,則按照從上到下的順序被這個管道進行處理并最終返回給客戶端。

對于這個由Channel組成消息處理管道來說,有兩種類型的Channel是必不可少的。一種是面向傳輸層用于發送和接收消息的TransportChannel,另一種被稱為MessageEncodingChannel則負責對接收的消息實施解碼并對發送的消息實施編碼。TransportChannel由TransportChannelListener創建,而后者由TransportBindingElement創建。與之類似,MessageEncodingBindingElement是MessageEncodingChannelListener的創建者,而后者又是MessageEncodingChannel的創建者。

如果采用Self Host寄宿模式,請求的監聽是由一個類型為HttpBinding的Binding對象創建的ChannelListener管道來完成的,由它創建的管道實現了針對請求的接收和針對響應的回復。HttpBinding類型定義在“System.Web.Http.SelfHost.Channels”命名空間下,我們接下來對它進行詳細講述。

HttpBinding

Binding存在的目的在于創建用于處理和傳輸消息的信道棧,組成信道棧的每一個Channel均對應著一個BindingElement,所以Binding本身處理消息的能力由其BindingElement的組成來決定,我們可以通過分析BindingElement的組成來了解消息最終是如何處理的。現在我們就來討論一下ASP.NET Web API在Self Host模式下使用的HttpBinding由哪些BindingElement構成。

如左圖所示,HttpBinding僅僅由兩種必需的BindingElement構成,TransportBindingElement的類型決定于最終采用的傳輸協議。如果采用單純的HTTP協議,采用的TransportBindingElement是一個HttpTransportBindingElement對象。在采用HTTPS協議的情況下,TransportBindingElement的類型是HttpsTransportBindingElement。

我們現在著重來分析與消息編碼/解碼相關的BindingElement,從圖3-11可以看出這是一個HttpMessageEncodingBindingElement對象(HttpMessageEncodingBindingElement是一個定義在程序集“System.Web.Http.SelfHost.dll”中的內部類型),它最終會創建一個MessageEncoder對象完成針對消息的編碼/解碼工作。

ASP.NET Web API分別利用 HttPRequestMessage和HttpResponseMessage對象表示消息處理管道處理的請求和響應,而WCF消息處理管道的請求和響應均是一個Message對象(Message是定義在命名空間“System.ServiceModel.Channels”下的一個抽象類型)。經過HttpMessageEncoder解碼后的Message對象會轉成一個HttpRequestMessage對象并傳入ASP.NET Web API消息處理管道進行處理,由此管道返回的HttpResponseMessage對象需要轉換成一個Message對象并由HttpMessageEncoder根據需求進行解碼。

這個具體的消息實際上是一個HttpMessage對象,HttpMessage繼承自抽象類Message,它是一個定義在程序集“System.Web.Http.SelfHost.dll”中的內部類型。如下面的代碼片斷所示,HttpMessage實際上是對一個HttpRequestMessage或者HttpResponseMessage對象的封裝,兩個方法GetHttpRequestMessage和GetHttpResponseMessage分別用于提取被封裝的HttpRequestMessage和HttpResponseMessage對象。

   1: internal sealed class HttpMessage : Message
   2: {
   3:     //其他成員   
   4:     public HttpMessage(HttpRequestMessage request);
   5:     public HttpMessage(HttpResponseMessage response);
   6:    
   7:     public HttpRequestMessage  GetHttpRequestMessage(bool extract);
   8:     public HttpResponseMessage GetHttpResponseMessage(bool extract);
   9: }

這兩個方法均具有一個布爾類型的參數extract,它表示是否“抽取”被封裝的HttpRequestMessage/HttpResponseMessage對象。如果指定的參數值為True,方法執行之后被封裝的HttpRequestMessage/HttpResponseMessage對象會從HttpMessage對象中抽取出來,所以再次調用它們會返回Null。

再次將我們的關注點拉回到由HttpBinding創建的消息處理管道上。當我們開啟HttpBinding后,它利用創建的ChannelListener管道監聽請求。一旦探測到抵達的請求后,基于HTTP/HTTPS協議的TransportChannel會負責接收請求。接收的二進制數據會由MessageEncoder解碼后生成一個HttpRequestMessage對象,該對象進而被封裝成一個HttpMessage對象,傳入消息處理管道的HttpRequestMessage是直接通過調用GetHttpRequestMessage方法從該HttpMessage對象中提取的。

當ASP.NET Web API消息處理管道完成了請求的處理并最終輸出一個HttpResponseMessage對象后,該對象同樣先被封裝成一個HttpMessage對象。在通過傳輸層將響應返回給客戶端之前,需要利用MessageEncoder對其進行編碼,而解碼的內容實際上就是調用GetHttpResponseMessage方法提取的HttpResponseMessage對象。

實例演示:直接利用HttpBinding進行請求的接收和響應

當我們采用Self Host寄宿模式將一個非Web應用程序作為目標Web API的宿主時,最終網絡監聽任務實際上是由HttpBinding創建的ChannelListener管道來完成的,而ChannelListener管道創建的消息處理管道最終實現了對請求的接收和對響應的發送。為了讓讀者對此具有深刻的認識,我們通過一個簡單的實例來演示如何直接使用HttpBinding實現對請求的監聽、接收和響應。

我們創建一個空的控制臺程序作為監聽服務器,它相當于Self Host寄宿模式下的宿主程序。如下面的代碼片斷所示,我們創建了一個HttpBinding,并指定監聽地址("http://127.0.0.1:3721")調用其BuildChannelListener<IReplyChannel>方法創建了一個ChannelListener管道(返回的是組成管道的第一個ChannelListener對象)。在調用Open方法開啟該ChannelListener管道之后,我們調用其AcceptChannel方法創建了消息處理管道,返回的是組成管道的第一個Channel對象。在Open方法將其開啟后,我們在一個While循環中調用Channel對象的ReceiveRequest方法進行請求的監聽和接收。

   1: class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         Uri listenUri = new Uri("http://127.0.0.1:3721");
   6:         Binding binding = new HttpBinding();
   7:  
   8:         //創建、開啟信道監聽器
   9:         IChannelListener<IReplyChannel> channelListener = binding.BuildChannelListener<IReplyChannel>(listenUri);
  10:         channelListener.Open();
  11:  
  12:         //創建、開啟回復信道
  13:         IReplyChannel channel = channelListener.AcceptChannel(TimeSpan.MaxValue);
  14:         channel.Open();
  15:  
  16:         //開始監聽
  17:         while (true)
  18:         {
  19:             //接收輸出請求消息
  20:             RequestContext requestContext = channel.ReceiveRequest(TimeSpan.MaxValue);
  21:             PrintRequestMessage(requestContext.RequestMessage);
  22:             //消息回復
  23:             requestContext.Reply(CreateResponseMessage());
  24:         }
  25:     }
  26: }

對于成功接收的消息,我們調用具有如下定義的PrintRequestMessage方法將相關的信息打印在控制臺上。通過上面的介紹我們知道這個接收到的消息實際上是一個HttpMessage對象,由于這是一個內部類型,所以我們只能以反射的方式調用其GetHttpRequestMessage方法獲取被封裝的HttpRequestMessage對象。在得到表示請求的HttpRequestMessage對象之后,我們將請求地址和所有報頭輸出到控制臺上。

   1: private static void PrintRequestMessage(Message message)
   2: {
   3:     MethodInfo method = message.GetType().GetMethod("GetHttpRequestMessage");
   4:     HttpRequestMessage request = (HttpRequestMessage)method.Invoke(message, new object[]{false});
   5:  
   6:     Console.WriteLine("{0, -15}:{1}", "RequestUri", request.RequestUri);
   7:     foreach (var header in request.Headers)
   8:     {
   9:         Console.WriteLine("{0, -15}:{1}", header.Key, string.Join("," ,header.Value.ToArray()));
  10:     }
  11: }

在對請求進行處理之后,我們需要創建一個Message對象對該請求予以響應,響應消息的創建是通過CreateResponseMessage方法完成的。如下面的代碼片斷所示,我們首先創建了一個響應狀態為“200, OK”的HttpResponseMessage對象,并將其表示主體內容的Content屬性設置為一個ObjectContent<Em

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 最新欧美精品一区二区三区 | 极品美女一级毛片 | 羞羞视频免费网站含羞草 | 欧美毛片| 三人弄娇妻高潮3p视频 | 香蕉久久久久 | 又黄又爽免费无遮挡在线观看 | 免费一级特黄做受大片 | 欧美一级免费高清 | 法国性hdfreexxxx人妖 | 天海翼无删减av三级在线观看 | 国内精品伊人久久久久网站 | 在线观看国产一区二区 | 综合在线视频 | 中文字幕观看 | 天堂成人国产精品一区 | 九九热在线精品视频 | 99riav视频一区二区 | 国产分类视频 | 欧美精品v国产精品v日韩精品 | 午夜小电影 | 亚洲午夜在线 | 国产一区二区精品在线观看 | 久久久久亚洲视频 | 欧美日韩高清一区二区三区 | 日韩蜜桃视频 | 一色桃子av大全在线播放 | 日韩精品一区二区三区中文 | 最新黄色av | 精品在线一区二区三区 | 亚洲资源在线播放 | 日本黄色a视频 | 免费黄色在线 | 黄在线观看在线播放720p | 久草视频在线看 | 国产精品欧美久久久久一区二区 | 中国杭州少妇xxxx做受 | aaaaaaa毛片| 国产88久久久国产精品免费二区 | 久久国产一二三 | 精品成人在线观看 |