Controller的啟用與URL路由

broadviewbj發表於2013-02-26

Controller的啟用與URL路由

ASP.NET路由系統是HTTP請求抵達服務端的第一道屏障,它根據註冊的路由規則對攔截的請求進行匹配並解析包含目標Controller和Action名稱的路由資訊。而當前ControllerBuilder具有用於啟用Controller物件的ControllerFactory,現在看看兩者是如何結合起來的。

透過第2章“URL路由”的介紹我們知道,ASP.NET路由系統的核心是一個叫做UrlRoutingModule的HttpModule,路由的實現是它透過註冊代表HttpApplication的PostResolveRequestCache事件對HttpHandler的動態對映來實現的。具體來說,它透過以RouteTable的靜態屬性Routes代表的全域性路由表對請求進行匹配並得到一個RouteData物件。RouteData具有一個實現了介面IRouteHandler的屬性RouteHandler,透過該屬性的GetHttpHandler方法可以得到最終被對映到當前請求的HttpHandler物件。

對於ASP.NET MVC應用來說,RouteData的RouteHandler屬性型別為MvcRouteHandler,實現在MvcRouteHandler中的HttpHandler提供機制基本上(不是完全等同)可以透過如下的程式碼來體現。MvcRouteHandler維護著一個ControllerFactory物件,該物件可以在建構函式中指定,如果沒有顯示指定則直接透過呼叫當前ControllerBuilder的GetControllerFactory方法獲取。

public class MvcRouteHandler : IRouteHandler

{

    private IControllerFactory _controllerFactory;

    public MvcRouteHandler(): this(ControllerBuilder.Current

        .GetControllerFactory())

    { }

    public MvcRouteHandler(IControllerFactory controllerFactory)

    {

        _controllerFactory = controllerFactory;

    }

    IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)

    {

        string controllerName = (string)requestContext.RouteData

            .GetRequiredString("controller");

        SessionStateBehavior. sessionStateBehavior. = _controllerFactory

            .GetControllerSessionBehavior(requestContext, controllerName);

        requestContext.HttpContext.SetSessionStateBehavior(sessionStateBehavior);

 

        return new MvcHandler(requestContext);

    }

}

在用於提供HttpHandler的GetHttpHandler方法中,除了返回一個實現了IHttpHandler介面的MvcHandler物件之外,還需要對當前HTTP上下文的會話狀態行為模式進行設定。具體的實現是:先透過包含在RequestContext的RouteData物件得到Controller的名稱,該名稱連同RequestContext物件一起傳入ControllerFactory的GetControllerSessionBehavior方法得到一個型別為SessionStateBehavior的列舉。最後透過RequestContext得到當前HTTP上下文(實際上是一個HttpContextWrapper物件),並呼叫其SetSessionStateBehavior方法對會話狀態行為進行設定。

透過第2章“URL路由”的介紹我們知道,RouteData中的RouteHandler屬性最初來源於對應的路由物件,而當我們呼叫RouteCollection的擴充套件方法MapRoute方法時註冊的Route物件對應的RouteHandler是一個MvcRouteHandler物件。由於在建立MvcRouteHandler物件時並沒有顯式指定ControllerFactory,所以透過當前ControllerBuilder的GetControllerFactory方法得到的ControllerFactory預設被使用。

透過當前ControllerBuilder的GetControllerFactory方法得到的ControllerFactory僅僅用於獲取會話狀態行為模式,而MvcHandler真正將它用於建立Controller。如下的程式碼片段基本上體現了MvcHandler的定義,它對請求處理的邏輯定義在BeginProcessRequest方法中。

public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState

{

    //其他成員

    public RequestContext RequestContext { get; private set; }

 

    public bool IsReusable

    {

        get { return false; }

    }

 

    public MvcHandler(RequestContext requestContext)

    {

        this.RequestContext = requestContext;

    }

 

    IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb,

        object extraData)

    {

        IControllerFactory controllerFactory =

            ControllerBuilder.Current.GetControllerFactory();

        string controllerName =

            this.RequestContext.RouteData.GetRequiredString("controller");

        IController controller = controllerFactory

            .CreateController(this.RequestContext, controllerName);

        if (controller is IAsyncController)

        {

            try

            {

                //呼叫BeginExecute/EndExecute方法以非同步的方式執行Controller

            }

            finally

            {

                controllerFactory.ReleaseController(controller);

            }

        }

        else

        {

            try

            {

                //呼叫Execute方法以非同步的方式執行Controller

            }

            finally

            {

                controllerFactory.ReleaseController(controller);

            }

        }

    }

}

由於MvcHandler同時實現了IHttpHandler和IHttpAsyncHandler介面,所以它總是以非同步的方式被執行(呼叫BeginProcessRequest/EndProcessRequest方法)。BeginProcessRequest方法透過RequestContext物件得到目標Controller的名稱,然後利用當前ControllerBuilder建立的ControllerFactory啟用Controller物件。如果Controller型別實現了IAsyncController介面,則以非同步的方式執行Controller,否則採用同步執行方式。在被啟用Controller物件被執行之後,MvcHandler會呼叫ControllerFactory的ReleaseController對其進行釋放清理工作。

 

 

 

 

 

本文節選自《ASP.NET MVC 4 框架揭秘》

蔣金楠

電子工業出版社出版

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/13164110/viewspace-754780/,如需轉載,請註明出處,否則將追究法律責任。

相關文章