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

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

ASP.NET Web API 控制器創(chuàng)建過(guò)程(一)

2019-11-17 01:40:53
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

asp.net Web API 控制器創(chuàng)建過(guò)程(一)

ASP.NET Web API 控制器創(chuàng)建過(guò)程(一)

前言

在前面對(duì)管道、路由有了基礎(chǔ)的了解過(guò)后,本篇將帶大家一起學(xué)習(xí)一下在ASP.NET Web API中控制器的創(chuàng)建過(guò)程,這過(guò)程分為幾個(gè)部分下面的內(nèi)容會(huì)為大家講解第一個(gè)部分,也是ASP.NET Web API框架跟ASP.NET MVC框架實(shí)現(xiàn)上存在不同的一部分。

ASP.NET Web API 控制器創(chuàng)建、激活過(guò)程

  • ASP.NET Web API 控制器創(chuàng)建過(guò)程(一)
  • ASP.NET Web API 控制器創(chuàng)建過(guò)程(二)
  • 未完待續(xù)

環(huán)境描述、問(wèn)題的發(fā)現(xiàn)

在項(xiàng)目運(yùn)用中,我們大多數(shù)會(huì)把控制器部分從主程序抽離出來(lái)放置單獨(dú)的項(xiàng)目中,這種情況下在使用ASP.NET MVC框架的項(xiàng)目環(huán)境中是不會(huì)有什么問(wèn)題的,因?yàn)镸VC框架在創(chuàng)建控制器的時(shí)候會(huì)加載當(dāng)前主程序引用的所有程序集并且按照?qǐng)?zhí)行的搜索規(guī)則(公共類型、實(shí)現(xiàn)IController的)搜索出控制器類型并且緩存到xml文件中。而這種方式如果在使用了默認(rèn)的ASP.NET Web API框架環(huán)境下就會(huì)有一點(diǎn)點(diǎn)的問(wèn)題,這里就涉及到了Web API框架的控制器創(chuàng)建過(guò)程中的知識(shí)。來(lái)看一下簡(jiǎn)單的示例。

(示例還是《ASP.NET Web API 開(kāi)篇介紹示例》中的示例,不過(guò)做了略微的修改,符合上述的情況。)

我們還是在SelfHost環(huán)境下做示例,來(lái)看SelfHost環(huán)境下服務(wù)端配置:

示例代碼1-1

    class PRogram    {        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 });                selfHostServer.OpenAsync();                Console.WriteLine("服務(wù)器端服務(wù)監(jiān)聽(tīng)已開(kāi)啟");                Console.Read();            }        }    }

代碼1-1就是引用《ASP.NET Web API 開(kāi)篇介紹示例》中的示例,在示例SelfHost項(xiàng)目中定義了API控制器,在這里我們需要把它注釋掉,并且創(chuàng)建新的類庫(kù)項(xiàng)目命名為WebAPIController,并且引用System.Web.Http.dll程序集和Common程序集,然后再定義個(gè)API控制器,也就是把原先在SelfHost項(xiàng)目中的控制器移動(dòng)到新建的類庫(kù)項(xiàng)目中。

示例代碼1-2

using System.Web.Http;using Common;namespace WebAPIController{    public class ProductController : ApiController    {        private static List<Product> products;        static ProductController()        {            products = new List<Product>();            products.AddRange(                new Product[]                 {                    new Product(){ ProductID="001", ProductName="牙刷",ProductCategory="洗漱用品"},                    new Product(){ ProductID="002", ProductName="《.NET框架設(shè)計(jì)—大型企業(yè)級(jí)應(yīng)用框架設(shè)計(jì)藝術(shù)》", ProductCategory="書(shū)籍"}                });        }        public IEnumerable<Product> Get(string id = null)        {            return from product in products where product.ProductID == id || string.IsNullOrEmpty(id) select product;        }        public void Delete(string id)        {            products.Remove(products.First(product => product.ProductID == id));        }        public void Post(Product product)        {            products.Add(product);        }        public void Put(Product product)        {            Delete(product.ProductID);            Post(product);        }    }}

這個(gè)時(shí)候還要記得把SelfHost項(xiàng)目添加WebAPIController項(xiàng)目的引用,要保持跟MVC項(xiàng)目的環(huán)境一樣,然后我們?cè)谶\(yùn)行SelfHost項(xiàng)目,等待監(jiān)聽(tīng)開(kāi)啟過(guò)后再使用瀏覽器請(qǐng)求服務(wù)會(huì)發(fā)現(xiàn)如下圖所示的結(jié)果。

圖1

看到圖1中的顯示問(wèn)題了吧,未找到匹配的控制器類型。如果是MVC項(xiàng)目則不會(huì)有這樣的問(wèn)題,那么問(wèn)題出在哪呢?實(shí)現(xiàn)方式的差異,下面就為大家來(lái)解釋一下。

解決問(wèn)題

在上一篇中我們最后的示意圖里可以清晰的看到ASP.NET Web API框架中的管道模型最后是通過(guò)HttpControllerDispatcher類型的對(duì)象來(lái)“生成”的APIController。我們現(xiàn)在就來(lái)看一下HttpControllerDispatcher類型的定義。

示例代碼1-3

    public class HttpControllerDispatcher : HttpMessageHandler    {        // Fields        private readonly HttpConfiguration _configuration;        private IHttpControllerSelector _controllerSelector;        // Methods        public HttpControllerDispatcher(HttpConfiguration configuration);        private static HttpResponseMessage HandleException(HttpRequestMessage request, Exception exception);        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);        private Task<HttpResponseMessage> SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken);        // Properties        public HttpConfiguration Configuration { get; }        private IHttpControllerSelector ControllerSelector { get; }}

從示例代碼1-3中可以看到HttpControllerDispatcher類型繼承自HttpMessageHandler類型,由此可見(jiàn),通過(guò)前面《ASP.NET Web API 管道模型》篇幅的知識(shí)我們了解到在ASP.NET Web API管道的最后一個(gè)消息處理程序?qū)嶋H是HttpControllerDispatcher類型,在Web API框架調(diào)用HttpControllerDispatcher類型的SendAsync()方法時(shí)實(shí)際是調(diào)用了HttpControllerDispatcher類型的一個(gè)私有方法SendAsyncInternal(),而APIController就是在這個(gè)私有方法中生成的,當(dāng)然不是由這個(gè)私有方法來(lái)生成它的。下面我們就來(lái)看一下SendAsyncInternal()的基礎(chǔ)實(shí)現(xiàn)。

示例代碼1-4

    private Task<HttpResponseMessage> SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken)    {        IHttpRouteData routeData = request.GetRouteData();        HttpControllerDescriptor descriptor = this.ControllerSelector.SelectController(request);        IHttpController controller = descriptor.CreateController(request);    }

代碼1-4很清晰的說(shuō)明了APIController的生成過(guò)程,這只是片面的,這里的代碼并不是全部,我們現(xiàn)在只需關(guān)注APIController的生成過(guò)程,暫時(shí)不去關(guān)心它的執(zhí)行過(guò)程。

首先由HttpControllerDispatcher類型中的一個(gè)類型為IHttpControllerSelector的屬性ControllerSelector(實(shí)則是DefaultHttpControllerSelector類型)根據(jù)HttpRequestMessage參數(shù)類型來(lái)調(diào)用IHttpControllerSelector類型里的SelectController()方法,由此獲取到HttpControllerDescriptor類型的變量descriptor,然后由變量descriptor調(diào)用它的CreateController()方法來(lái)創(chuàng)建的控制器。

說(shuō)到這里看似一個(gè)簡(jiǎn)單的過(guò)程里面蘊(yùn)含的知識(shí)還是有一點(diǎn)的,我們首先來(lái)看ControllerSelector屬性

示例代碼1-5

    private IHttpControllerSelector ControllerSelector    {        get        {            if (this._controllerSelector == null)            {                this._controllerSelector = this._configuration.Services.GetHttpControllerSelector();            }            return this._controllerSelector;        }    }

這里我們可以看到是由HttpConfiguration類型的變量_configuration中的Servieces(服務(wù)容器)來(lái)獲取的IHttpControllerSelector類型的對(duì)象。那我們獲取到的究竟實(shí)例是什么類型的?

到這里先暫停,大家先不用記住上面的一堆廢話中的內(nèi)容,現(xiàn)在我們來(lái)看一下HttpConfiguration這個(gè)類型,我們現(xiàn)在只看HttpConfiguration類型,忘掉上面的一切。

示例代碼1-6

    public class HttpConfiguration : IDisposable    {        // Fields        private IDependencyResolver _dependencyResolver;        // Methods        public HttpConfiguration();        public HttpConfiguration(HttpRouteCollection routes);        private HttpConfiguration(HttpConfiguration configuration, HttpControllerSettings settings);        public IDependencyResolver DependencyResolver { get; set; }        public ServicesContainer Services { get; internal set; }    }

在這里我們看到有字段、構(gòu)造函數(shù)和屬性,對(duì)于_dependencyResolver字段和對(duì)應(yīng)的屬性我們下面會(huì)有講到這里就不說(shuō)了。這里主要就是說(shuō)明一下ServicesContainer 類型的Services屬性。對(duì)于ServicesContainer類型沒(méi)用的朋友可能不太清楚,實(shí)際上可以把ServicesContainer類型想象成一個(gè)IoC容器,就和IDependencyResolver類型的作用是一樣的,在前面的《C#編程模式之?dāng)U展命令》一文中有涉及到ServicesContainer類型的使用,感興趣的朋友可以去看看。

回到主題,在構(gòu)造函數(shù)執(zhí)行時(shí)ServicesContainer類型實(shí)例實(shí)際是由它的子類DefaultServices類型實(shí)例化而來(lái)的。而在DefaultServices類型實(shí)例化的時(shí)候它的構(gòu)造函數(shù)中會(huì)將一些服務(wù)和具體實(shí)現(xiàn)的類型添加到緩存里。

圖2

在圖2中我們現(xiàn)在只需關(guān)注第二個(gè)紅框中的IHttpControllerSelector對(duì)應(yīng)的具體服務(wù)類型是DefaultHttpControllerSelector類型。

現(xiàn)在我們?cè)賮?lái)看代碼1-5中的GetHttpControllerSelector()方法,它是有ServicesExtensions擴(kuò)展方法類型來(lái)實(shí)現(xiàn)的。

好了現(xiàn)在大家的思緒可以回到代碼1-4現(xiàn)在我們知道是由DefaultHttpControllerSelector類型的SelectController()方法來(lái)生成HttpControllerDescriptor類型的。暫時(shí)不用管HttpControllerDescriptor類型,我們先來(lái)看SelectController()方法中的實(shí)現(xiàn)細(xì)節(jié)。

示例代碼1-7

public virtual HttpControllerDescriptor SelectController(HttpRequestMessage request)    {        HttpControllerDescriptor descriptor;        string controllerName = this.GetControllerName(request);        if (this._controllerInfoCache.Value.TryGetValue(controllerName, out descriptor))        {            return descriptor;        }    }

這里可以看到controllerName是由路由數(shù)據(jù)對(duì)象RouteData來(lái)獲取的,然后由_controllerInfoCache變量根據(jù)控制器名稱獲取到HttpControllerDescriptor實(shí)例,這里HttpControllerDescriptor實(shí)例我們暫且不管,后面的篇幅會(huì)有講到。

重點(diǎn)是我們看一下_controllerInfoCache變量中的值是怎么來(lái)的?是從HttpControllerTypeCache類型的Cache屬性值而來(lái)。而Cache的值則是根據(jù)HttpControllerTypeCache類型的中的InitializeCache()方法得來(lái)的,我們看下實(shí)現(xiàn)。

實(shí)例代碼1-8

    private Dictionary<string,
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 平遥县| 双桥区| 兰溪市| 关岭| 青铜峡市| 紫阳县| 平远县| 长宁区| 峨眉山市| 克东县| 滁州市| 黎川县| 杨浦区| 靖远县| 新余市| 桂平市| 昌乐县| 丹凤县| 东至县| 黔江区| 香港| 句容市| 桓台县| 泌阳县| 环江| 海兴县| 永春县| 临夏市| 时尚| 抚顺市| 青田县| 绥化市| 阜阳市| 阿坝| 延津县| 娄烦县| 德化县| 德化县| 松江区| 江华| 荔波县|