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

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

ASP.NET Web API中的Controller

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

asp.net Web API中的Controller

雖然通過Visual Studio向導在ASP.NET Web API項目中創建的 Controller類型默認派生與抽象類型ApiController,但是ASP.NET Web API框架本身只要求它實現IHttpController接口即可,所以我們將其統稱為HttpController。既然HttpController指的是所有實現了IHttpController接口的類型,我們自然得先來了解一下這個接口的定義。如下面的代碼片斷所示,在IHttpController接口中僅僅定義了唯一的方法ExecuteAsync方法,它以異步的方式執行HttpController,并返回一個Task<HttPResponseMessage>對象。[本文已經同步到《How ASP.NET Web API Works?》]

   1: public interface IHttpController
   2: {
   3:     Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken);
   4: }

HttpController可以視為對ASP.NET Web API的消息處理管道的延續。通過“ASP.NET Web API標準的“管道式”設計”的介紹我們知道位于管道末端的是一個HttpRoutingDispatcher對象。當SendAsync方法被執行的時候,HttpRoutingDispatcher會利用隸屬于它的HttpControllerDispatcher來激活目標HttpController對象,隨后調用該對象的ExecuteAsync方法并將返回的Task<HttpResponseMessage>對象作為返回值。右圖揭示了包含激活的HttpController在內的消息處理管道的結構。

一、HttpControllerContext

與HttpMessageHandler的SendAsync方法有所不同,HttpController的ExecuteAsync方法并沒有一個表示請求的類型為HttpRequestMessage的參數,取而代之的是一個HttpControllerContext類型的參數。HttpControllerContext定義在命名空間“System.Web.Http.Controllers”下,表示執行HttpController的上下文。

如下面的代碼片斷所示,通過定義在HttpControllerContext中的屬性我們可以得到用于配置消息處理管道的HttpConfiguration對象和封裝路由數據的HttpRouteData對象,以及表示當前請求的HttpRequestMessage對象。這三個屬性可以在構建HttpControllerContext的時候直接通過構造函數的參數指定,我們也可以先創建一個空的HttpControllerContext對象之后直接對這些屬性賦值。

   1: public class HttpControllerContext
   2: {
   3:     public HttpControllerContext();
   4:     public HttpControllerContext(HttpConfiguration configuration, IHttpRouteData routeData, HttpRequestMessage request);   
   5:     
   6:     public HttpConfiguration         Configuration { get; set; }
   7:     public IHttpRouteData            RouteData { get; set; }
   8:     public HttpRequestMessage        Request { get; set; }
   9:  
  10:     public IHttpController              Controller { get; set; }
  11:     public HttpControllerDescriptor     ControllerDescriptor { get; set; }
  12: }

一個HttpControllerContext對象表示執行HttpController的上下文,我們可以通過Controller屬性來獲取或者設置這個HttpController對象。除此之外,我們還可以利用另一個屬性ControllerDescriptor獲取或者設置用于描述HttpController的HttpControllerDescriptor對象(類型HttpControllerDescriptor定義在命名空間“System.Web.Http.Controllers”下)。

二、HttpControllerDescriptor

HttpControllerDescriptor封裝了某個HttpController類型的元數據,我們可以將它視為某個HttpController類型的描述對象。HttpControllerDescriptor具有根據元數據創建對應HttpController的能力,實際上ASP.NET Web API的HttpController激活系統就是根據HttpControllerDescriptor來創建目標HttpController的。

如下面的代碼片斷所示,我們可以通過HttpControllerDescriptor的屬性Configuration、ControllerName和ControllerType獲取當前的HttpConfiguration對象和被描述HttpController的名稱和類型。這三個屬性可以在構建HttpControllerDescriptor時通過構造函數的參數顯式指定,也可以先構建一個空的HttpControllerDescriptor對象,然后手工設置這些屬性。

   1: public class HttpControllerDescriptor
   2: {   
   3:     public HttpControllerDescriptor();
   4:     public HttpControllerDescriptor(HttpConfiguration configuration, string controllerName, Type controllerType);
   5:  
   6:     public virtual IHttpController CreateController(HttpRequestMessage request);
   7:  
   8:     public virtual Collection<T> GetCustomAttributes<T>() where T: class;
   9:     public virtual Collection<T> GetCustomAttributes<T>(bool inherit) where T: class;
  10:     public virtual Collection<IFilter> GetFilters();
  11:    
  12:     public HttpConfiguration     Configuration { get; set; }
  13:     public string                ControllerName { get; set; }
  14:     public Type                  ControllerType { get; set; }
  15:  
  16:     public virtual ConcurrentDictionary<object, object> Properties { get; }
  17: }

HttpControllerDescriptor具有創建HttpController的能力主要體現在其CreateController方法上,該方法完成了目標方法的激活。換句話說,目標HttpController的激活是通過調用描述它的HttpControllerDescriptor對象的CreateController方法完成的。本章的核心就在于剖析此方法的實現邏輯。

我們可以通過HttpControllerDescriptor的GetCustomAttributes<T>方法得到應用在被描述HttpController類型上指定類型的特性列表。調用另一個方法GetFilters可以獲取應用到目標HttpController類型上的所有Filter,Filter在ASP.NET Web API中是一個非常重要的概念,同時也是一種常見的擴展方式,我們會在本書第12章“過濾器”中對Filter進行單獨介紹。

HttpControllerDescriptor還具有一個字典類型的只讀屬性Properties,它使我們可以將任何一個對象附加到某個HttpControllerDescriptor上。我們在HttpRequestMessage和HttpConfiguration類型中已經看到過了類似的設計。

三、ApiController

我們現在來介紹一下我們創建HttpController類型默認繼承的基類ApiController。如下面的代碼片斷所示,除了實現接口IHttpController外,HttpController還采用標準的方式實現了另一個接口IDisposable。如果自定義HttpController需要實現一些資源回收的工作,可以將它們定義在重寫的(受保護的)虛方法Dispose中。

   1: public abstract class ApiController : IHttpController, IDisposable
   2: {
   3:     public virtual Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken);
   4:     protected virtual void Initialize(HttpControllerContext controllerContext);
   5:     
   6:     public void Dispose();
   7:     protected virtual void Dispose(bool disposing);
   8:   
   9:     public HttpControllerContext     ControllerContext { get; set; }
  10:     public HttpConfiguration         Configuration { get; set; }
  11:     public HttpRequestMessage        Request { get; set; }
  12:     public IHttpRouteData            RouteData { get; set; }
  13:  
  14:     public ModelStateDictionary     ModelState { get; }
  15:     public UrlHelper                Url { get; set; }
  16:     public IPrincipal               User { get; }
  17: }

ApiController的三個屬性Configuration、Request和RouteData與此HttpControllerContext對象的同名屬性具有相同的引用。表示執行當前ApiController上下文的HttpControllerContext對象可以通過ControllerContext屬性獲取,這是一個可讀寫的屬性,意味著我們也可以通過設置該屬性為其指定相應的上下文。如果我們沒有對ControllerContext屬性進行顯式設置,該屬性會在第一次被獲取時被自動賦值。

ApiController的只讀屬性ModelState返回一個具有字典數據結構的ModelStateDictionary對象,包含其中的數據會被以“Model綁定”的形式綁定到目標Action方法的對應的參數。除此之外,此ModelStateDictionary還用于保存參數驗證失敗后的錯誤消息。另一個參數Url返回一個類型為UrlHelper的對象(UrlHelper定義在命名空間“System.Web.Http.Routing”下),我們利用它可以根據注冊的HttpRoute和提供的路由變量生成一個完整的URL。

ApiController的User屬性返回當前線程的Principal。相信讀者還會記得在本書第3章“消息處理管道”中介紹HttpServer時我們談到:如果當前線程的Principal為Null,作為消息處理管道“龍頭”的HttpServer會在SendAsync方法執行過程中創建一個空的GenericPrincipal對象作為當前線程的“匿名”Principal。所以對于匿名請求來說,這個User屬性會返回這個通過HttpServer設置的空GenericPrincipal對象。

從上面給出的代碼片斷我們還會看到ApiController包含一個受保護的Initialize方法,它會根據由指定HttpControllerContext提供的上下文信息對自身作相應的初始化。一旦Initialize方法被成功執行,當前ApiController對象將處于初始化狀態。此Initialize在默認情況下會在實現的ExecuteAsync方法中被自動調用。在默認情況下,ASP.NET Web API的HttpController激活系統總是創建一個新的HttpController來處理每一個請求。對于其類型繼承自ApiController的HttpController來說,如果在執行ExecuteAsync方法的時候發現當前的ApiController已經處于“初始化”的狀態,系統會直接拋出一個InvalidOperationException異常。

舉個簡單的例子,假設我們定義了如下一個繼承自ApiController的DemoController類型,并通如下的方式將原本為受保護的Initialize方法轉換成一個公有方法,以方便我們后續的調用。

   1: public class DemoController : ApiController
   2: {
   3:     public new void Initialize(HttpControllerContext controllerContext)
   4:     {
   5:         base.Initialize(controllerContext);
   6:     }
   7: }

然后我們執行如下一段代碼,它的特別之處在于在調用DemoController對象的ExecuteAsync方法之前調用了Initialize方法對其作了初始化處理。

   1: DemoController controller = new DemoController ();
   2: HttpControllerContext controllerContext = new HttpControllerContext(new HttpConfiguration(), new HttpRouteData(new HttpRoute()), new HttpRequestMessage());
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 草草在线观看 | va毛片| 91精品国产刺激国语对白 | 在线免费观看毛片视频 | 污在线观看网站 | 成人一区二区在线观看视频 | 91成人免费看片 | 草草视频免费观看 | 久久精品一区二区三区国产主播 | 成人做爰s片免费看网站 | 久久97超碰 | 哪里可以看免费的av | 国产盼盼私拍福利视频99 | 久草在线视频看看 | 斗罗破苍穹在线观看免费完整观看 | 黄污在线观看 | 中文字幕涩涩久久乱小说 | 国产午夜精品一区二区三区视频 | 91麻豆蜜桃一区二区三区 | 精品一区二区三区不卡 | 欧美1区2区在线观看 | 超级av在线 | 日本在线视 | 九九热色| 国产一级二级毛片 | 国产噜噜噜噜久久久久久久久 | 国产精品一区在线看 | 国产免费美女 | 亚洲精品一区二区三区在线看 | 欧美在线a| 久久国产精品久久久久久电车 | 性插视频 | 99亚洲伊人久久精品影院红桃 | 亚洲成人第一区 | 久久久在线 | 日本一区二区高清不卡 | 成人国产综合 | 欧美成人一级 | 一区二区三区视频在线观看 | 毛片大全在线观看 | 超久久 |