此篇博文緊接上篇博文進行闡述,本篇博文闡述的主題是Controller激活和url路由web
ASP.NET路由系統是HTTP請求抵達服務端的第一道屏障,它根據註冊的路由規則對攔截的請求進行匹配並解析包含目標的Controller和Action名稱的路由信息。當前ControllerBuilder具備用於激活Controller對象的ControllerFactory。app
ASP.NET路由系統的核心是一個叫作UrlRoutingModule的自定義HttpModule,路由的實現是它經過註冊表明當前web應用的HttpApplication的PostResolverRequestCache事件對HttpHandler的動態映射來實現的。具體來講,它經過以RouteTable的靜態屬性Routes表明的全局路由表對請求進行匹配並獲得一個RouteData對象。RouteData具備一個實現了接口IRouteHandler屬性RouteHandler,經過該屬性的GetHttpHandler獲得最終被映射到當前請求的HttpHandler。函數
對於MVC應用來講,RouteData的RouteHandler屬性類型爲MvcRouteHandler,體如今MvcRouteHandler類型上關於HttpHandler的提供機制基本上(不是徹底等同)能夠經過以下的代碼來表示。MvcRouteHandler維護着一個ControllerFactory對象,該對象能夠在構造函數中指定,若是沒有顯示指定則直接經過調用當前ControllerBuilder的GetControllerFactory來獲取。ui
1 public class MvcRouteHandler:IRouteHandler 2 { 3 private IControllerFactory _controllerFactory; 4 6 public MvcRouteHandler() { } 7 public MvcRouteHandler(IControllerFactory controllerFactory) 8 { 9 _controllerFactory = controllerFactory; 10 } 11 12 protected virtual SessionStateBehavior GetSessionStateBehavior(RequestContext context) 13 { 14 string str = (string)context.RouteData.Values["controller"]; //RouteData.Values獲取路由的url參數值和默認值的集合 15 if(string.IsNullOrWhiteSpace(str)) 16 { 17 throw new InvalidOperationException("MvcRouteHandler_RouteValuesHasNoController"); 18 } 19 IControllerFactory factory = _controllerFactory ?? ControllerBuilder.Current.GetControllerFactory(); 20 return factory.GetControllerSessionBehavior(context, str); 21 } 22 public virtual IHttpHandler GetHttpHandler(RequestContext context) 23 { 24 context.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(context)); 25 return new MvcHandler(context); 26 } 27 }
用於提供HttpHandler的GetHttpHandler方法中,除了返回一個實現了IHttpHandler接口的MvcHandler對象以外,還須要對當前Http上下文的會話狀態行爲模式進行設置。具體來講,首先經過包含在傳入RequestContext的RouteData對象獲得Controller的名稱,該名稱連同RequestContext對象一塊兒傳入ControllerFactory的GetControllerSessionBehavior方法獲得一個類型爲SessionStateBehavior的枚舉。最後經過RequestContext獲得表示當前HTTP上下文的HttpContextBase對象(其實是一個HttpContextWrapper對象)並調用其SetSessionStateBehavior方法。url
咱們知道RouteData中的RouteHandler屬性最初來源於對應的Route對象的同名屬性,而當咱們調用RouteCollection的擴展方法MapRoute方法時,其內部會直接建立並添加一個Route對象。因爲在建立Route對象是並無顯式指定ControllerFactory,因此經過當前ControllerBuilder的GetControllerFactory方法獲得的ControllerFactory默認被使用。spa
經過當前ControllerBuilder的GetControllerFactory方法獲得的ControllerFactory僅僅用於獲取會話狀態行爲模式,而MvcHandler真正將它用於建立Controller。MvcHandler中關於對請求處理的邏輯基本上能夠經過以下的代碼片段來體現。以下面的代碼片段所示,MvcHandler具備一個表示當前請求上下文的RequestContext屬性,該屬性在構造函數中被初始化。code