亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

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

ASP.NET Web API 控制器創建過程(一)

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

asp.net Web API 控制器創建過程(一)

ASP.NET Web API 控制器創建過程(一)

前言

在前面對管道、路由有了基礎的了解過后,本篇將帶大家一起學習一下在ASP.NET Web API中控制器的創建過程,這過程分為幾個部分下面的內容會為大家講解第一個部分,也是ASP.NET Web API框架跟ASP.NET MVC框架實現上存在不同的一部分。

ASP.NET Web API 控制器創建、激活過程

  • ASP.NET Web API 控制器創建過程(一)
  • ASP.NET Web API 控制器創建過程(二)
  • 未完待續

環境描述、問題的發現

在項目運用中,我們大多數會把控制器部分從主程序抽離出來放置單獨的項目中,這種情況下在使用ASP.NET MVC框架的項目環境中是不會有什么問題的,因為MVC框架在創建控制器的時候會加載當前主程序引用的所有程序集并且按照執行的搜索規則(公共類型、實現IController的)搜索出控制器類型并且緩存到xml文件中。而這種方式如果在使用了默認的ASP.NET Web API框架環境下就會有一點點的問題,這里就涉及到了Web API框架的控制器創建過程中的知識。來看一下簡單的示例。

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

我們還是在SelfHost環境下做示例,來看SelfHost環境下服務端配置:

示例代碼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("服務器端服務監聽已開啟");                Console.Read();            }        }    }

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

示例代碼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框架設計—大型企業級應用框架設計藝術》", ProductCategory="書籍"}                });        }        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);        }    }}

這個時候還要記得把SelfHost項目添加WebAPIController項目的引用,要保持跟MVC項目的環境一樣,然后我們在運行SelfHost項目,等待監聽開啟過后再使用瀏覽器請求服務會發現如下圖所示的結果。

圖1

看到圖1中的顯示問題了吧,未找到匹配的控制器類型。如果是MVC項目則不會有這樣的問題,那么問題出在哪呢?實現方式的差異,下面就為大家來解釋一下。

解決問題

在上一篇中我們最后的示意圖里可以清晰的看到ASP.NET Web API框架中的管道模型最后是通過HttpControllerDispatcher類型的對象來“生成”的APIController。我們現在就來看一下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類型,由此可見,通過前面《ASP.NET Web API 管道模型》篇幅的知識我們了解到在ASP.NET Web API管道的最后一個消息處理程序實際是HttpControllerDispatcher類型,在Web API框架調用HttpControllerDispatcher類型的SendAsync()方法時實際是調用了HttpControllerDispatcher類型的一個私有方法SendAsyncInternal(),而APIController就是在這個私有方法中生成的,當然不是由這個私有方法來生成它的。下面我們就來看一下SendAsyncInternal()的基礎實現。

示例代碼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很清晰的說明了APIController的生成過程,這只是片面的,這里的代碼并不是全部,我們現在只需關注APIController的生成過程,暫時不去關心它的執行過程。

首先由HttpControllerDispatcher類型中的一個類型為IHttpControllerSelector的屬性ControllerSelector(實則是DefaultHttpControllerSelector類型)根據HttpRequestMessage參數類型來調用IHttpControllerSelector類型里的SelectController()方法,由此獲取到HttpControllerDescriptor類型的變量descriptor,然后由變量descriptor調用它的CreateController()方法來創建的控制器。

說到這里看似一個簡單的過程里面蘊含的知識還是有一點的,我們首先來看ControllerSelector屬性

示例代碼1-5

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

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

到這里先暫停,大家先不用記住上面的一堆廢話中的內容,現在我們來看一下HttpConfiguration這個類型,我們現在只看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; }    }

在這里我們看到有字段、構造函數和屬性,對于_dependencyResolver字段和對應的屬性我們下面會有講到這里就不說了。這里主要就是說明一下ServicesContainer 類型的Services屬性。對于ServicesContainer類型沒用的朋友可能不太清楚,實際上可以把ServicesContainer類型想象成一個IoC容器,就和IDependencyResolver類型的作用是一樣的,在前面的《C#編程模式之擴展命令》一文中有涉及到ServicesContainer類型的使用,感興趣的朋友可以去看看。

回到主題,在構造函數執行時ServicesContainer類型實例實際是由它的子類DefaultServices類型實例化而來的。而在DefaultServices類型實例化的時候它的構造函數中會將一些服務和具體實現的類型添加到緩存里。

圖2

在圖2中我們現在只需關注第二個紅框中的IHttpControllerSelector對應的具體服務類型是DefaultHttpControllerSelector類型。

現在我們再來看代碼1-5中的GetHttpControllerSelector()方法,它是有ServicesExtensions擴展方法類型來實現的。

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

示例代碼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是由路由數據對象RouteData來獲取的,然后由_controllerInfoCache變量根據控制器名稱獲取到HttpControllerDescriptor實例,這里HttpControllerDescriptor實例我們暫且不管,后面的篇幅會有講到。

重點是我們看一下_controllerInfoCache變量中的值是怎么來的?是從HttpControllerTypeCache類型的Cache屬性值而來。而Cache的值則是根據HttpControllerTypeCache類型的中的InitializeCache()方法得來的,我們看下實現。

實例代碼1-8

    private Dictionary<string,
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩人人澡狠狠躁视频| 国产亚洲a∨片在线观看| 精品国产欧美一区二区三区成人| 成人444kkkk在线观看| 久久999免费视频| 欧美精品一区在线播放| 2019最新中文字幕| 91美女片黄在线观| 欧美在线日韩在线| 亚洲精品欧美一区二区三区| 久久久欧美一区二区| 国产精品都在这里| 美女视频黄免费的亚洲男人天堂| 日韩av在线播放资源| 亚洲欧美日韩国产精品| 欧美在线播放视频| 国内精品视频一区| 亚洲一区亚洲二区亚洲三区| 亚洲精品成人久久久| 国产精品日韩一区| 91av在线影院| 亚洲男女自偷自拍图片另类| 色偷偷88888欧美精品久久久| 国产一区二区三区视频| 久久成人18免费网站| 午夜精品久久久久久久久久久久久| 亚洲激情电影中文字幕| 欧美大片第1页| 久久久精品影院| 98视频在线噜噜噜国产| 浅井舞香一区二区| 91在线无精精品一区二区| 国产91网红主播在线观看| 亚洲第一页在线| 岛国av午夜精品| 丝袜情趣国产精品| 精品视频在线播放色网色视频| 日韩不卡在线观看| 欧美激情在线观看视频| 国产精品av电影| 日韩在线观看精品| 久久国产精品视频| 亚州精品天堂中文字幕| 久久97精品久久久久久久不卡| 日韩成人xxxx| 亚洲一区二区自拍| 亚洲欧洲在线观看| 中文字幕精品av| 欧美激情亚洲另类| 黑人狂躁日本妞一区二区三区| 91在线免费观看网站| 亚洲国产精品va在线看黑人| 亚洲精品中文字幕av| 国产精品视频免费观看www| 成人免费视频网址| 欧美性猛交xxxx乱大交极品| 一本一本久久a久久精品牛牛影视| 这里只有精品久久| 中文字幕日韩精品有码视频| 久久免费精品日本久久中文字幕| 国产精品久久视频| 国产一区二区在线免费视频| 91视频国产精品| 欧美亚洲日本网站| 国产精品pans私拍| 亚洲精品一区中文字幕乱码| 亚洲欧美综合精品久久成人| 久久久久99精品久久久久| 国产精品wwwwww| 中文字幕精品av| 久久影院资源网| 91精品久久久久久久久久| 欧美性在线观看| 色综合导航网站| 国产97色在线| 亚洲欧美另类人妖| 国产欧美最新羞羞视频在线观看| 在线精品91av| 国产一区二区三区三区在线观看| 在线看日韩av| 96精品久久久久中文字幕| 亚洲国语精品自产拍在线观看| 国产精品h在线观看| 国产一区香蕉久久| 色综合天天综合网国产成人网| 久久久久久国产精品美女| 欧美激情亚洲一区| 日韩免费电影在线观看| 日本久久精品视频| 国模私拍一区二区三区| 国产精品中文字幕久久久| 国产欧美va欧美va香蕉在线| 国产成人精品综合| 久久中文精品视频| 性色av一区二区三区| 51精品在线观看| 欧美黄色片免费观看| 欧美大成色www永久网站婷| 欧美精品午夜视频| 亚洲日本成人女熟在线观看| 亚洲欧美在线磁力| 久久影院模特热| 日韩精品免费观看| 国产精品1234| 91精品国产自产在线老师啪| 欧美一级在线亚洲天堂| 亚洲欧洲在线播放| 亚洲人成电影在线播放| 国产乱肥老妇国产一区二| 久久久久久美女| 亚洲精品xxxx| 欧美极度另类性三渗透| 亚洲视频在线免费观看| 日韩中文字幕在线看| 91久久久久久久久久久| 精品国产乱码久久久久久虫虫漫画| 国产成人精品最新| 久久久噜噜噜久久久| 国产综合福利在线| 狠狠久久亚洲欧美专区| 97精品久久久| 97超碰国产精品女人人人爽| 欧美成人在线网站| 久久久久久成人精品| 色琪琪综合男人的天堂aⅴ视频| 91极品视频在线| 欧美高跟鞋交xxxxhd| 久久在线免费视频| 美女视频久久黄| 91免费人成网站在线观看18| 中文字幕综合一区| 欧美电影在线播放| 精品国产一区二区三区久久狼5月| 777午夜精品福利在线观看| 久久99久久久久久久噜噜| 亚洲男人天堂网站| 亚洲欧美日韩综合| 岛国视频午夜一区免费在线观看| 永久免费精品影视网站| 国产精品老女人视频| 久久久久久久一区二区三区| 性欧美激情精品| 欧美亚洲一级片| 亚洲第一天堂av| 久久91亚洲精品中文字幕奶水| 欧美日韩一区二区三区在线免费观看| 成人网中文字幕| 久久精品国产久精国产思思| 亚洲丝袜在线视频| 日本欧美一级片| 激情亚洲一区二区三区四区| 欧美在线亚洲一区| 欧美激情精品久久久久久久变态| 三级精品视频久久久久| 日韩精品一区二区三区第95| 久久精品99久久久久久久久| 国产在线视频一区| 欧美激情亚洲综合一区| 日韩av综合网| 亚洲国产精品系列| 欧美电影免费观看高清完整| 日韩一区二区三区国产| 青青草国产精品一区二区| 韩国福利视频一区|