国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

ASP.NET Web API中的Controller

2019-11-17 01:26:36
字體:
供稿:網(wǎng)友

asp.net Web API中的Controller

雖然通過Visual Studio向?qū)г贏SP.NET Web API項目中創(chuàng)建的 Controller類型默認(rèn)派生與抽象類型ApiController,但是ASP.NET Web API框架本身只要求它實現(xiàn)IHttpController接口即可,所以我們將其統(tǒng)稱為HttpController。既然HttpController指的是所有實現(xiàn)了IHttpController接口的類型,我們自然得先來了解一下這個接口的定義。如下面的代碼片斷所示,在IHttpController接口中僅僅定義了唯一的方法ExecuteAsync方法,它以異步的方式執(zhí)行HttpController,并返回一個Task<HttPResponseMessage>對象。[本文已經(jīng)同步到《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的消息處理管道的延續(xù)。通過“ASP.NET Web API標(biāo)準(zhǔn)的“管道式”設(shè)計”的介紹我們知道位于管道末端的是一個HttpRoutingDispatcher對象。當(dāng)SendAsync方法被執(zhí)行的時候,HttpRoutingDispatcher會利用隸屬于它的HttpControllerDispatcher來激活目標(biāo)HttpController對象,隨后調(diào)用該對象的ExecuteAsync方法并將返回的Task<HttpResponseMessage>對象作為返回值。右圖揭示了包含激活的HttpController在內(nèi)的消息處理管道的結(jié)構(gòu)。

一、HttpControllerContext

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

如下面的代碼片斷所示,通過定義在HttpControllerContext中的屬性我們可以得到用于配置消息處理管道的HttpConfiguration對象和封裝路由數(shù)據(jù)的HttpRouteData對象,以及表示當(dāng)前請求的HttpRequestMessage對象。這三個屬性可以在構(gòu)建HttpControllerContext的時候直接通過構(gòu)造函數(shù)的參數(shù)指定,我們也可以先創(chuàng)建一個空的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對象表示執(zhí)行HttpController的上下文,我們可以通過Controller屬性來獲取或者設(shè)置這個HttpController對象。除此之外,我們還可以利用另一個屬性ControllerDescriptor獲取或者設(shè)置用于描述HttpController的HttpControllerDescriptor對象(類型HttpControllerDescriptor定義在命名空間“System.Web.Http.Controllers”下)。

二、HttpControllerDescriptor

HttpControllerDescriptor封裝了某個HttpController類型的元數(shù)據(jù),我們可以將它視為某個HttpController類型的描述對象。HttpControllerDescriptor具有根據(jù)元數(shù)據(jù)創(chuàng)建對應(yīng)HttpController的能力,實際上ASP.NET Web API的HttpController激活系統(tǒng)就是根據(jù)HttpControllerDescriptor來創(chuàng)建目標(biāo)HttpController的。

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

   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具有創(chuàng)建HttpController的能力主要體現(xiàn)在其CreateController方法上,該方法完成了目標(biāo)方法的激活。換句話說,目標(biāo)HttpController的激活是通過調(diào)用描述它的HttpControllerDescriptor對象的CreateController方法完成的。本章的核心就在于剖析此方法的實現(xiàn)邏輯。

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

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

三、ApiController

我們現(xiàn)在來介紹一下我們創(chuàng)建HttpController類型默認(rèn)繼承的基類ApiController。如下面的代碼片斷所示,除了實現(xiàn)接口IHttpController外,HttpController還采用標(biāo)準(zhǔn)的方式實現(xiàn)了另一個接口IDisposable。如果自定義HttpController需要實現(xiàn)一些資源回收的工作,可以將它們定義在重寫的(受保護(hù)的)虛方法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對象的同名屬性具有相同的引用。表示執(zhí)行當(dāng)前ApiController上下文的HttpControllerContext對象可以通過ControllerContext屬性獲取,這是一個可讀寫的屬性,意味著我們也可以通過設(shè)置該屬性為其指定相應(yīng)的上下文。如果我們沒有對ControllerContext屬性進(jìn)行顯式設(shè)置,該屬性會在第一次被獲取時被自動賦值。

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

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

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

舉個簡單的例子,假設(shè)我們定義了如下一個繼承自ApiController的DemoController類型,并通如下的方式將原本為受保護(hù)的Initialize方法轉(zhuǎn)換成一個公有方法,以方便我們后續(xù)的調(diào)用。

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

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

   1: DemoController controller = new DemoController ();
   2: HttpControllerContext controllerContext = new HttpControllerContext(new HttpConfiguration(), new HttpRouteData(new HttpRoute()), new HttpRequestMessage());
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 湘西| 绵阳市| 扎鲁特旗| 莱芜市| 荣昌县| 石河子市| 宣恩县| 宣武区| 德安县| 女性| 嘉鱼县| 门头沟区| 唐海县| 边坝县| 达日县| 德化县| 高平市| 蕉岭县| 马山县| 镇沅| 百色市| 霸州市| 武汉市| 天峻县| 和静县| 锦州市| 金门县| 阜平县| 康乐县| 和田市| 刚察县| 怀集县| 鸡西市| 迁安市| 惠东县| 盐边县| 宜都市| 厦门市| 宝兴县| 渭南市| 张家口市|