从源码浅析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler
熟悉WebForm開(kāi)發(fā)的朋友一定都知道,Page類必須實(shí)現(xiàn)一個(gè)接口,就是IHttpHandler。HttpHandler是一個(gè)HTTP請(qǐng)求的真正處理中心,在HttpHandler容器中,ASP.NET Framework調(diào)用HttpHandler的ProcessRequest成員方法來(lái)對(duì)這個(gè)HTTP請(qǐng)求進(jìn)行真正的處理,真正地對(duì)客戶端請(qǐng)求的服務(wù)器頁(yè)面做出編譯和執(zhí)行。歸根結(jié)底,Asp.Net所有的HTTP請(qǐng)求最后都是由IHttpHandler的實(shí)現(xiàn)來(lái)處理的,Asp.Net MVC框架當(dāng)然也不例外。下面就從MvcRouteHandler、MvcHandler和MvcHttpHandler三個(gè)常見(jiàn)的Handler類來(lái)淺析一下MVC是怎么和IHttpHandler聯(lián)系起來(lái)進(jìn)行HTTP請(qǐng)求處理的。
1、MvcRouteHandler
在MVC中MvcApplication通常在Application_Start事件里實(shí)現(xiàn)RegisterRoutes方法:
protected void Application_Start(){AreaRegistration.RegisterAllAreas();RegisterGlobalFilters(GlobalFilters.Filters);RegisterRoutes(RouteTable.Routes);}其中RegisterRoutes方法通常類似如下:
public static void RegisterRoutes(RouteCollection routes){routes.IgnoreRoute("{resource}.axd/{*pathInfo}");routes.MapRoute("Default", // Route name"{controller}/{action}/{id}", // URL with parametersnew { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults);}這個(gè)方法非常重要,因?yàn)檎菑倪@里開(kāi)始,Asp.Net應(yīng)用程序可以和Asp.Net URL Routing組件完美結(jié)合起來(lái)實(shí)現(xiàn)Url優(yōu)化(MVC和WebForm都可以,可以參考dudu的這一篇)。
從MVC源碼入手,我們發(fā)現(xiàn)RouteCollection的MapRoute擴(kuò)展方法最終都是通過(guò)RouteCollectionExtensions的一個(gè)靜態(tài)方法實(shí)現(xiàn)的:
[SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")]public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces){if (routes == null){throw new ArgumentNullException("routes");}if (url == null){throw new ArgumentNullException("url");}Route route = new Route(url, new MvcRouteHandler()){Defaults = new RouteValueDictionary(defaults),Constraints = new RouteValueDictionary(constraints),DataTokens = new RouteValueDictionary()};if ((namespaces != null) && (namespaces.Length > 0)){route.DataTokens["Namespaces"] = namespaces;}routes.Add(name, route);return route;}?
大家注意這一行:?? Route route = new Route(url, new MvcRouteHandler()),正是通過(guò)MvcRouteHandler(其實(shí)從命名就可以猜到),Asp.Net的URL Routing組件就和IHttpHandler有了關(guān)聯(lián)。到這里我們猜測(cè),MvcRouteHandler一定和IHttpHandler有關(guān)系(甚至它可能就是IHttpHandler的一個(gè)具體實(shí)現(xiàn)),而且URL Routing組件最后一定映射到一個(gè)IHttpHandler處理程序來(lái)處理相應(yīng)的HTTP請(qǐng)求。我們來(lái)查看MvcRouteHandler具體源碼實(shí)現(xiàn)印證一下自己的看法:
/* ****************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved.** This software is subject to the Microsoft Public License (Ms-PL). * A copy of the license can be found in the license.htm file included * in this distribution.** You must not remove this notice, or any other, from this software.** ***************************************************************************/namespace System.Web.Mvc {using System.Web.Routing;using System.Web.SessionState;public class MvcRouteHandler : IRouteHandler{private IControllerFactory _controllerFactory;public MvcRouteHandler(){}public MvcRouteHandler(IControllerFactory controllerFactory){_controllerFactory = controllerFactory;}protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext){requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));return new MvcHandler(requestContext);}protected virtual SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext){string controllerName = (string)requestContext.RouteData.Values["controller"];IControllerFactory controllerFactory = _controllerFactory ?? ControllerBuilder.Current.GetControllerFactory();return controllerFactory.GetControllerSessionBehavior(requestContext, controllerName);}#region IRouteHandler MembersIHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext){return GetHttpHandler(requestContext);}#endregion} }可惜,MvcRouteHandler沒(méi)有繼承實(shí)現(xiàn)IHttpHandler接口,而是繼承了IRouteHandler接口,但是我們欣喜發(fā)現(xiàn)IRouteHandler接口的唯一方法GetHttpHandler返回了一個(gè)IHttpHandler,這實(shí)在是太讓人感到意料之中的一陣激動(dòng)了。
?
2、MvcHandler
繼續(xù)上面MvcRouteHandler的源碼,我們發(fā)現(xiàn)MvcRouteHandler具體實(shí)現(xiàn)GetHttpHandler的時(shí)候最后new了一個(gè)MvcHandler對(duì)象返回:
protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext){requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));return new MvcHandler(requestContext);}?
也就是說(shuō)MvcHandler是IHttpHandler子類確定無(wú)疑了。然后查看MvcHandler源碼,發(fā)現(xiàn)MvcHandler繼承實(shí)現(xiàn)了IHttpAsyncHandler, IHttpHandler, IRequiresSessionState三個(gè)無(wú)比熟悉的接口。而這三個(gè)接口如果都實(shí)現(xiàn)了,在MVC框架下是不是任何http請(qǐng)求就可以通吃了呢?從MSDN我們得知,事實(shí)不是這樣的:
注意,即使 MvcHandler 實(shí)現(xiàn) IHttpHandler,也不能將其映射為處理程序(例如.mvc 文件擴(kuò)展名),因?yàn)樵擃惒恢С譄o(wú)參數(shù)構(gòu)造函數(shù)。 (它唯一的構(gòu)造函數(shù)需要一個(gè) RequestContext 對(duì)象)
但是,還好,我們還有MvcHttpHandler。
?
3、MvcHttpHandler
如你所知,MvcHttpHandler可以“彌補(bǔ)”MvcHandler的不足,為什么這樣說(shuō)呢?其實(shí)2中也提到過(guò)了,MvcHandler沒(méi)有無(wú)參的構(gòu)造函數(shù),因此即使MvcHandler實(shí)現(xiàn)了 IHttpHandler接口,在IIS中也不能將其映射為某類文件擴(kuò)展名的處理程序,需要結(jié)合路由模塊使用。
而MvcHttpHandler就提供了不通過(guò)路由模塊的情況下直接處理映射的處理程序。通過(guò)查看MvcHttpHandler源碼我們發(fā)現(xiàn),MvcHttpHandler繼承實(shí)現(xiàn)了UrlRoutingHandler, IHttpAsyncHandler, IRequiresSessionState接口,而UrlRoutingHandler繼承自IHttpHandler。MvcHttpHandler帶無(wú)參的構(gòu)造函數(shù)(也就是說(shuō)我們可以直接new一個(gè)MvcHttpHandler無(wú)參數(shù)對(duì)象?不用擔(dān)心上下文?希望這里的解釋不是令人感到費(fèi)解),而且繼承自UrlRoutingHandler類實(shí)現(xiàn)了IHttpHandler接口,因此可以在ASP.NET程序中讓你更加靈活使用用來(lái)解決一些問(wèn)題。
?
參考:
http://msdn.microsoft.com/zh-cn/library/system.web.mvc.mvcroutehandler.aspx
http://msdn.microsoft.com/zh-cn/library/system.web.mvc.mvchandler.aspx
http://msdn.microsoft.com/zh-cn/library/system.web.mvc.mvchttphandler.aspx
轉(zhuǎn)載于:https://www.cnblogs.com/lookbs/p/MVC-Handler.html
總結(jié)
以上是生活随笔為你收集整理的从源码浅析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C语言中声明和定义的区别
- 下一篇: Collections.unmodifi