当IIS收到一个http请求,把请求信息发给对应的HttpModel(实际是实现类UrlRoutingModule),在HttpModel中会注册HttpApplication 类中的PostResolveRequestCache事件,通过此事件来动态选择映射HttpHandler处理程序。通过匹配到的RouteData类的RouteHandler属性得到IRouteHandler对象(MVC4是MvcRouteHandler、asp.net原生的是PageRouteHandler),通过这个对象的GetHttpHandler方法就可以得到HttpHandler处理程序。具体代码如下:
public virtual void PostResolveRequestCache(object sender, EventArgs e) { HttpApplication app = (HttpApplication)sender; HttpContextBase context = new HttpContextWrapper(app.Context); //详细见附1 RouteData routeData = RouteCollection.GetRouteData(context); if (routeData == null) { return; } //详细见附1 IRouteHandler routeHandler = routeData.RouteHandler; if (routeHandler is StopRoutingHandler) { return; } RequestContext requestContext = new RequestContext(context, routeData); context.Request.RequestContext = requestContext; IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); if (httpHandler is UrlAuthFailureHandler) { if (FormsAuthenticationModule.FormsAuthRequired) { UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this); return; } else { throw new HttpException(401, SR.GetString(SR.Assess_Denied_Description3)); } } context.RemapHandler(httpHandler);//动态指定HttpHandler }
附1:
RouteCollection.GetHttpHandler方法获取匹配当前路由信息的RouteData,此方法是循环遍历RouteCollection集合并调用集合中RouteBase(实现类为Route)的GetRouteData方法,并返回第一个不为Null的Roudata。Roudata实在RoudataBase的GetRouteData方法中被创建的,详见如下代码:
public override RouteData GetRouteData(HttpContextBase httpContext) { string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo; RouteValueDictionary values = _parsedRoute.Match(requestPath, Defaults); if (values == null) { return null; } //为Roudata指定IRouteHandler对象 RouteData routeData = new RouteData(this, RouteHandler); if (!ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest)) { return null; } foreach (var value in values) { routeData.Values.Add(value.Key, value.Value); } if (DataTokens != null) { foreach (var prop in DataTokens) { routeData.DataTokens[prop.Key] = prop.Value; } } return routeData; } public class RouteData { private IRouteHandler _routeHandler; public RouteData() { } public RouteData(RouteBase route, IRouteHandler routeHandler) { Route = route; RouteHandler = routeHandler; } //更多代码 }
MVC4:动态指定到HttpHandler后,就是处理Controller的创建和Action的执行了
HttpHandler根据Routedata获取到Controller的名称,然后通过ControllerBuilder的静态方法GetControllerFactory获取IControllerFactory的实现类(默认是DefaultControllerFactory )来创建请求的IController的实现类的实例。最后执行IController的Execute方法并传入请求上下文,方法Execute实现在System.Web.Mvc.ControllerBase这个抽象类中,Execute最终调用的是System.Web.Mvc.Controller中的ExecuteCore方法,ExecuteCore方法主要是保存TempData然后根据路由数据调用执行Action。代码如下:
protected override void ExecuteCore() { PossiblyLoadTempData(); try { string actionName = GetActionName(RouteData);
//ActionInvoker是System.Web.Mvc.Controller的属性,该属性是一个返回类型为IActionInvoker的action执行器 if (!ActionInvoker.InvokeAction(ControllerContext, actionName)) { HandleUnknownAction(actionName); } } finally { PossiblySaveTempData(); } }