程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> MVC系列(9) MVC如何在Pipeline中接管請求的

MVC系列(9) MVC如何在Pipeline中接管請求的

編輯:關於ASP.NET

上個章節我們講到了,可以在HttpModules初始化之前動態添加Route的方式來自定義自己的HttpHandler,最終接管請求的,那MVC是這麼實現的麼?本章節我們就來分析一下相關的MVC源碼來驗證一下我們的這個問題。

先創建一個MVC3的Web Application,選擇默認的模板以便創建以後就默認包含HomeController和AccountController。我們知道MVC要先接管請求才能通過這些Controller來處理,那我們先去Global.asax.cs文件裡看代碼(定義接管請求要在初始化HttpModule之前,所以只能到這裡來找代碼(或者是利用WebActivator之類的特性來動態添加),Global.asax.cs文件裡代碼很少,但是有我們需要的東西,首先在Application_Start的方法裡發現一行代碼:

RegisterRoutes(RouteTable.Routes);

這行代碼,看調用的方法名稱RegisterRoutes是注冊Route的意思,但是為什麼參數卻是全局的RouteTable.Routes集合呢?找到RegisterRoutes方法來看看具體的內容:

public static void RegisterRoutes(RouteCollection routes)  
{  
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
      
    routes.MapRoute(  
        "Default", // Route name  
        "{controller}/{action}/{id}", // URL with parameters  
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults  
    );  
}

該方法有2行代碼,第一行是忽略一個Route(我們先不看這個),第二行是使用MapRoute方法注冊一個新的Route,默認是映射到Home Controller的Index Action上,我們可能想到了,RouteCollection(也就是剛才傳入的RouteTable.Routes)的MapRoute方法就是提供我們所說的接管請求的入口,但是如何把MVC自己的HttpHandler傳進去的呢?我們Go to一下這個MapRoute方法(需要安裝ReShaper來查找MVC的源碼),調整到了MVC的 RouteCollectionExtensions類,發現MapRoute並不是RouteCollection自帶的方法,而是在MVC源碼裡提供的一個擴展方法,代碼如下:

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;  
}

該代碼的主要作用是new一個新的Route,然後將該Route添加到我們剛才提到的靜態集合RouteTable.Routes裡,以便後期查找Handler的時候使用,OK,這一步符合我們前面章節的分析。

接下來看,Route是如何new出來的,代碼裡的參數傳入的分別是我們知道的url,以及一個MVCRouteHandler的實例,這一步也符合我們前面的分析,那我們來看一下MVCRouteHandler的GetHttpHandler方法是如何實現的獲取MVCHandler的:

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 Members   
    IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) {  
        return GetHttpHandler(requestContext);   
    }  
    #endregion  
}

看以上的粗體代碼,MvcRouteHandler在實現了IRouteHandler的GetHttpHandler,該方法調用了 MvcRouteHandler自身定義的GetHttpHandler虛方法,而在這個虛方法裡我們看到了一個非常重要而又期待已久的代碼——返回 MvcHandler的實例,大概看一下MvcHandler這個類,得到它就是我們所猜想的:繼承於IHttpHandler接口的一個類,並且也繼承了 IHttpAsyncHandler接口,我們先不管MvcHandler內部是如何實現的,但我們前面幾章節的全部分析終於得到了驗證,也就說在這裡得到了Mvc的專用處理Handler,然後調用它的BeginProcessRequest方法進入Mvc自身的Pipeline進行處理了。

至此,我們終於弄明白了Mvc在整個ASP.NET Runtime是如何接管請求的了,也應該大概清楚整個ASP.NET Runtime的運行機制了,至於MvcHandler的實現方式,我們會在後面的很多章節逐一給大家分析每行代碼,今天我們還有一個小任務,那就是:看完了Mvc的實現機制,我們能否自己來寫一個自定義的HttpHandler通過Route動態注冊進去,來實現我們自己的自定義擴展,我們來嘗試著做一下吧。

本欄目

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved