新聞中心
ASP.NET Web API WebHost宿主環(huán)境中管道、路由
前言
上篇中說(shuō)到ASP.NET Web API框架在SelfHost環(huán)境中管道、路由的一個(gè)形態(tài),本篇就來(lái)說(shuō)明一下在WebHost環(huán)境中ASP.NET Web API框架中的管道、路由又是哪一種形態(tài)。
成都創(chuàng)新互聯(lián)主要從事網(wǎng)站制作、成都網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)同心,十多年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專(zhuān)業(yè),歡迎來(lái)電咨詢(xún)建站服務(wù):18980820575
ASP.NET Web API路由、管道
ASP.NET Web API開(kāi)篇介紹示例
ASP.NET Web API路由對(duì)象介紹
ASP.NET Web API管道模型
ASP.NET Web API selfhost宿主環(huán)境中管道、路由
ASP.NET Web API webhost宿主環(huán)境中管道、路由
ASP.NET Web API webhost宿主環(huán)境中管道、路由
下面將會(huì)主要講解路由的注冊(cè)執(zhí)行過(guò)程(WebHost環(huán)境),對(duì)于管道不會(huì)去刻意的說(shuō)明,都會(huì)包含在路由的講解中,拆開(kāi)來(lái)說(shuō)明效果不太好。
HttpRoute->HostedHttpRoute->HttpWebRoute->Route
想要清楚的了解路由的執(zhí)行過(guò)程以及管道的形態(tài),就必須對(duì)路由對(duì)象熟知,然而在前面的《ASP.NET Web API 路由對(duì)象介紹》篇幅中只是分別的對(duì)各個(gè)環(huán)境下的路由對(duì)象類(lèi)型進(jìn)行了說(shuō)明,并沒(méi)有說(shuō)明轉(zhuǎn)變的過(guò)程。
現(xiàn)在就來(lái)講解路由對(duì)象的“轉(zhuǎn)變”過(guò)程。
示例代碼1-1
protected void Application_Start(object sender, EventArgs e) { GlobalConfiguration.Configuration.Routes.MapHttpRoute( "DefaultAPI", "api/{controller}/{id}", new { controller="product",id = RouteParameter.Optional }); }
示例代碼1-1中是在WebHost環(huán)境下進(jìn)行的路由注冊(cè),根據(jù)MapHttpRoute()方法我們轉(zhuǎn)定義過(guò)去應(yīng)該是一個(gè)HttpRouteCollection類(lèi)型的擴(kuò)展方法類(lèi)型HttpRouteCollectionExtensions,既然是HttpRouteCollectionExtensions類(lèi)型里的實(shí)現(xiàn)那我們就過(guò)去看看到底啥情況。
示例代碼1-2
public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints, HttpMessageHandler handler) { if (routes == null) { throw System.Web.Http.Error.ArgumentNull("routes"); } HttpRouteValueDictionary dictionary = new HttpRouteValueDictionary(defaults); HttpRouteValueDictionary dictionary2 = new HttpRouteValueDictionary(constraints); IDictionarydataTokens = null; HttpMessageHandler handler2 = handler; IHttpRoute route = routes.CreateRoute(routeTemplate, dictionary, dictionary2, dataTokens, handler2); routes.Add(name, route); return route; }
我們可以看到返回類(lèi)型是IHttpRoute,生成則是由HttpRouteCollection類(lèi)型的實(shí)例調(diào)用其中的CreateRoute()方法來(lái)實(shí)現(xiàn),這里有的朋友要問(wèn)了,這不是SelfHost中的路由注冊(cè)實(shí)現(xiàn)方式嗎?回答是對(duì)的,只不過(guò)在WebHost中利用多態(tài)來(lái)實(shí)現(xiàn)返回成其他的類(lèi)型,接著往下看。
既然都看到了在這里發(fā)生的變化,那說(shuō)明是有繼承了HttpRouteCollection類(lèi)型的這么一個(gè)類(lèi)型然后創(chuàng)建的路由對(duì)象。這樣一理就清晰多了,在SelfHost環(huán)境中HttpRouteCollection類(lèi)型是存在于HttpConfiguration類(lèi)型的對(duì)象中,并不單獨(dú)使用。而在WebHost中也是。
這個(gè)時(shí)候我們?cè)倩剡^(guò)頭來(lái)看一下代碼1-1中的GlobalConfiguration類(lèi)型中的定義。
示例代碼1-3
private static Lazy_configuration = new Lazy (delegate { HttpConfiguration configuration = new HttpConfiguration(new HostedHttpRouteCollection(RouteTable.Routes)); configuration.Services.Replace(typeof(IAssembliesResolver), new WebHostAssembliesResolver()); configuration.Services.Replace(typeof(IHttpControllerTypeResolver), new WebHostHttpControllerTypeResolver()); configuration.Services.Replace(typeof(IHostBufferPolicySelector), new WebHostBufferPolicySelector()); return configuration; }); public static HttpConfiguration Configuration { get { return _configuration.Value; } }
從代碼1-3中我們可以看到_configuration靜態(tài)變量使用了延遲加載,啥意思呢就是下面的那個(gè)HttpConfiguration類(lèi)型的Configuration屬性如果使用了才會(huì)去實(shí)例化,跑偏了這不是重點(diǎn)。
重點(diǎn)是在實(shí)例化靜態(tài)變量_configuration中可以清楚的看到使用了HostedHttpRouteCollection類(lèi)型的路由集合類(lèi)型對(duì)象作為構(gòu)造函數(shù)參數(shù)??梢宰孕械娜タ匆幌翲ostedHttpRouteCollection的內(nèi)部結(jié)構(gòu)。
現(xiàn)在再回到創(chuàng)建路由的那會(huì),也就是代碼1-1和代碼1-2中所示的那樣,實(shí)際也就是HostedHttpRouteCollection類(lèi)型在創(chuàng)建路由對(duì)象,按照老規(guī)矩直接看實(shí)現(xiàn)代碼。
示例代碼1-4
public override IHttpRoute CreateRoute(string uriTemplate, IDictionarydefaults, IDictionary constraints, IDictionary dataTokens, HttpMessageHandler handler) { return new HostedHttpRoute(uriTemplate, defaults, constraints, dataTokens, handler); }
從代碼1-4中可以清楚的看到是返回的是HostedHttpRoute路由對(duì)象,我們可以看一下構(gòu)造函數(shù),只有這樣才能知道“轉(zhuǎn)變”的過(guò)程。
public HostedHttpRoute(string uriTemplate, IDictionarydefaults, IDictionary constraints, IDictionary dataTokens, HttpMessageHandler handler) { RouteValueDictionary dictionary = (defaults != null) ? new RouteValueDictionary(defaults) : null; RouteValueDictionary dictionary2 = (constraints != null) ? new RouteValueDictionary(constraints) : null; RouteValueDictionary dictionary3 = (dataTokens != null) ? new RouteValueDictionary(dataTokens) : null; this.OriginalRoute = new HttpWebRoute(uriTemplate, dictionary, dictionary2, dictionary3, HttpControllerRouteHandler.Instance, this); this.Handler = handler; }
在代碼1-4中我們只需要關(guān)注OriginalRoute屬性的賦值,OriginalRoute屬性是HostedHttpRoute類(lèi)型里的一個(gè)屬性,是用來(lái)設(shè)置對(duì)Route對(duì)象的引用,示例代碼1-4中也就是HttpWebRoute類(lèi)型的對(duì)象,對(duì)于HttpWebRoute對(duì)象的構(gòu)造函數(shù)這里就不例舉了。這個(gè)時(shí)候可以看到是將HttpControllerRouteHandler類(lèi)型的對(duì)象作為Route(HttpWebRoute)對(duì)象的RouteHandler(路由處理程序)。
大家都知道ASP.NET Web API框架在WebHost環(huán)境中是依賴(lài)于ASP.NET的,實(shí)則也是通過(guò)IHttpModule來(lái)進(jìn)行前期的消息攔截,下面我們看一下在HttpModule中的代碼(我想應(yīng)該是這樣的,如果有誤請(qǐng)指點(diǎn)。)
示例代碼1-5
public class WebAPIHttpModule:IHttpModule { public void Dispose() { throw new NotImplementedException(); } public void Init(HttpApplication context) { context.PostResolveRequestCache += context_PostResolveRequestCache; } void context_PostResolveRequestCache(object sender, EventArgs e) { HttpApplication context = sender as HttpApplication; HttpContextWrapper contextWrapper = new HttpContextWrapper(context.Context); RouteData routeData = RouteTable.Routes.GetRouteData(contextWrapper); RequestContext requestContext=new RequestContext(contextWrapper,routeData); IHttpHandler httpHandler = routeData.RouteHandler.GetHttpHandler(requestContext); IHttpAsyncHandler httpAsyncHandler = httpHandler as IHttpAsyncHandler; httpAsyncHandler.BeginProce***equest(context.Context, null, null); } }
在代碼1-5中我們可以看到首先是獲取了RouteData對(duì)象實(shí)例,以此獲取RouteHandler,然后根據(jù)RequestContext獲取IHttpHandler,再轉(zhuǎn)換為IHttpAsyncHandler類(lèi)型的實(shí)例,然后調(diào)用其BeginProce***equest()方法來(lái)執(zhí)行操作。
上面這段話(huà)描述的是上述代碼的執(zhí)行過(guò)程,有的朋友可能會(huì)疑問(wèn)了,怎么就獲取RouteData了?
這里我給大家解釋一下,在我們的代碼1-2中,有這樣的代碼:
IHttpRoute route = routes.CreateRoute(routeTemplate, dictionary, dictionary2, dataTokens, handler2); routes.Add(name, route);
首先我們看第一句,這里的route上面說(shuō)過(guò)了是HostedHttpRoute對(duì)象,這里毫無(wú)疑問(wèn)直接過(guò),然后我們?cè)倏吹诙?,這里的routes是HostedHttpRouteCollection對(duì)象不假,但是這個(gè)Add()方法添加的方向不是HostedHttpRouteCollection,而是由我們一開(kāi)始在GlobalConfiguration類(lèi)型中說(shuō)過(guò)的RouteTable.Routes,當(dāng)前環(huán)境是什么?ASP.NET框架環(huán)境對(duì)吧!毫無(wú)疑問(wèn)這個(gè)Add()方法把上面所說(shuō)的route(HostedHttpRoute對(duì)象)添加到了當(dāng)前環(huán)境的RouteTable.Routes中,有的朋友會(huì)問(wèn)了類(lèi)型不對(duì)。確實(shí)是不對(duì)的在添加的時(shí)候route(HostedHttpRoute對(duì)象)會(huì)轉(zhuǎn)換成HttpWebRoute對(duì)象,HttpWebRoute對(duì)象繼承自Route,可以看前面的篇幅,想必說(shuō)到這里大家應(yīng)該明白了。這里我就不多說(shuō)了。
我們接著回到代碼1-5中,在獲取了RouteData之后通過(guò)RouteHandler的GetHttphandler()方法獲取IHttpHandler實(shí)例,在RouteData中的這個(gè)RouteHandler毫無(wú)疑問(wèn)就是HttpControllerRouteHandler類(lèi)型。
我們來(lái)看下HttpControllerRouteHandler類(lèi)型中的GetHttphandler()方法:
protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) { return new HttpControllerHandler(requestContext.RouteData); }
可以看到是由HttpControllerHandler這個(gè)對(duì)象類(lèi)型來(lái)執(zhí)行最后的操作,那我們就來(lái)看一下這個(gè)類(lèi)型的定義:
public class HttpControllerHandler : IHttpAsyncHandler, IHttpHandler
現(xiàn)在大家明白為什么要轉(zhuǎn)成IHttpAsyncHandler了吧,因?yàn)槿绻{(diào)用了實(shí)現(xiàn)了IHttpHandler接口的函數(shù)是會(huì)報(bào)出異常的,因?yàn)樵贖ttpControllerHandler類(lèi)型中并沒(méi)有實(shí)現(xiàn)IHttpHandler接口只是一個(gè)空殼,然后我們?cè)倏匆幌翲ttpControllerHandler類(lèi)型的靜態(tài)構(gòu)造函數(shù):
圖1
這個(gè)_server是Lazy
下面我們看一下整體的一個(gè)示意圖,
圖2
最后對(duì)于HttpControllerDispatcher類(lèi)型在控制器部分講解。
當(dāng)前標(biāo)題:ASP.NETWebAPIWebHost宿主環(huán)境中管道、路由
網(wǎng)頁(yè)鏈接:http://www.dlmjj.cn/article/ghipge.html