首先咱們經過在Global.asax中的Application_Start將路由信息註冊到RouteTable的Routes靜態屬性中。以下代碼所示: app
public class RouteTable { //省略 public static RouteCollection Routes { get; } } protected void Application_Start() { RouteConfig.RegisterRoutes(RouteTable.Routes); } public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } //MapRoute有多個重載,最終實例以下 public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) { //省略 Route route = new Route(url, new MvcRouteHandler()) { Defaults = CreateRouteValueDictionaryUncached(defaults), Constraints = CreateRouteValueDictionaryUncached(constraints), DataTokens = new RouteValueDictionary() }; ConstraintValidation.Validate(route); if ((namespaces != null) && (namespaces.Length > 0)) { route.DataTokens[RouteDataTokenKeys.Namespaces] = namespaces; } routes.Add(name, route); return route; }
在new Route對象的同時,咱們同時new了一個MvcRouteHandler對象實例傳進去。而後將route添加到RouteTable的靜態屬性RouteCollection中,同時返回該route實例。路由註冊完畢。ide
MVC經過在IHttpModule的實現類UrlRoutingModule的Init方法中攔截HttpApplication的PostResolveRequestCache事件來處理請求。代碼以下:函數
public class UrlRoutingModule : IHttpModule { public RouteCollection RouteCollection { get { if (this._routeCollection == null) { this._routeCollection = RouteTable.Routes; } return this._routeCollection; } set { this._routeCollection = value; } } protected virtual void Init(HttpApplication application) { //省略 application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache); } private void OnApplicationPostResolveRequestCache(object sender, EventArgs e) { HttpApplication httpApplication = (HttpApplication)sender; HttpContextBase context = new HttpContextWrapper(httpApplication.Context); this.PostResolveRequestCache(context); } public virtual void PostResolveRequestCache(HttpContextBase context) { RouteData routeData = this.RouteCollection.GetRouteData(context); //省略 IRouteHandler routeHandler = routeData.RouteHandler; //省略 RequestContext requestContext = new RequestContext(context, routeData); context.Request.RequestContext = requestContext; IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); //省略 if (!(httpHandler is UrlAuthFailureHandler)) { context.RemapHandler(httpHandler); return; } //省略 } }
插一句,UrlRoutingModule中的RouteCollection默認來自對RouteTable的靜態屬性Routes的引用。this
攔截以後,經過RouteCollection的GetRouteData得到相應的路由數據RouteData的實例routeData。routeData有一個屬性RouteHandler,在註冊路由時,實例化Route時,咱們實例化了一個MvcRouteHandler給構造函數,這裏RouteHandler屬性其實MvcRouteHandler的實例引用(以下代碼片斷中的Route)。url
而後咱們routeHandler是的GetHttpHandler方法,獲取到IHttpHandler(以下代碼片斷中的MvcRouteHandler 類)。spa
//代碼片斷三 public class Route : RouteBase { //省略 public IRouteHandler RouteHandler { get; set; } public string Url { get { return this._url ?? string.Empty; } set { this._parsedRoute = RouteParser.Parse(value); this._url = value; } } public Route(string url, IRouteHandler routeHandler) { this.Url = url; this.RouteHandler = routeHandler; } public override RouteData GetRouteData(HttpContextBase httpContext) { string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo; RouteValueDictionary routeValueDictionary = this._parsedRoute.Match(virtualPath, this.Defaults); if (routeValueDictionary == null) { return null; } RouteData routeData = new RouteData(this, this.RouteHandler); if (!this.ProcessConstraints(httpContext, routeValueDictionary, RouteDirection.IncomingRequest)) { return null; } foreach (KeyValuePair<string, object> current in routeValueDictionary) { routeData.Values.Add(current.Key, current.Value); } if (this.DataTokens != null) { foreach (KeyValuePair<string, object> current2 in this.DataTokens) { routeData.DataTokens[current2.Key] = current2.Value; } } return routeData; } //省略 } public class MvcRouteHandler : IRouteHandler { //省略 protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) { requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext)); return new MvcHandler(requestContext); } //省略 }