iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 10
1

前言

前一篇介紹路由封裝了Http請求路徑資訊可以讓我們找到相對應的ActionController並呼叫執行外,也可透過MapPageRoute來將請求教給.aspx實體檔案來處理請求.

Route甚至可以讓我們自己客製化處理HttpHandler 在Route中建立處理客製化HttpHandler可謂很有彈性

本篇介紹Route物件建立MvcRouteHandler物件且如何取到IHttpHandler.

我有做一個可以針對於Asp.net MVC Debugger的專案,只要下中斷點就可輕易進入Asp.net MVC原始碼

此篇同步發布在筆者Blog [Day10] 透過MvcRouteHandler取得呼叫IHttphandler

MVC取得使用HttpHandler (IHttpHandler)

之前說到我們透過MapRoute擴展方法加入一個Route物件給RouteCollection全域路由集合.

Route使用的IRouteHandler介面是由MvcRouteHandler來實現

Route route = new Route(url, new MvcRouteHandler())
{
    Defaults = CreateRouteValueDictionaryUncached(defaults),
    Constraints = CreateRouteValueDictionaryUncached(constraints),
    DataTokens = new RouteValueDictionary()
};

IRouteHandler最重要的是IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)會取得一個IHttpHandler物件.

public class MvcRouteHandler : IRouteHandler
{
    private IControllerFactory _controllerFactory;

    public MvcRouteHandler()
    {
    }

    public MvcRouteHandler(IControllerFactory controllerFactory)
    {
        _controllerFactory = controllerFactory;
    }

    protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        //設置Session使用
        requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
        return new MvcHandler(requestContext);
    }

    protected virtual SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext)
    {
        string controllerName = (string)requestContext.RouteData.Values["controller"];
        if (String.IsNullOrWhiteSpace(controllerName))
        {
            throw new InvalidOperationException(MvcResources.MvcRouteHandler_RouteValuesHasNoController);
        }

        IControllerFactory controllerFactory = _controllerFactory ?? ControllerBuilder.Current.GetControllerFactory();
        return controllerFactory.GetControllerSessionBehavior(requestContext, controllerName);
    }

    #region IRouteHandler Members

    IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
    {
        return GetHttpHandler(requestContext);
    }

    #endregion
}

上面程式碼可以看到Mvc使用IHttpHandlerMvcHandler

MVC呼叫的HttpHandler (MvcHandler)

MvcHandler類別中主要核心的程式碼做了幾件事情.

  1. 使用一個Adapter對於HttpContext物件把他轉成可以繼承於HttpContextBaseHttpContextWrapper類別.
  2. 透過ProcessRequestInit取得執行controller物件並且呼叫執行方法.
  3. 最後透過ReleaseController釋放之前使用過資源
protected virtual void ProcessRequest(HttpContext httpContext)
{
    HttpContextBase httpContextBase = new HttpContextWrapper(httpContext);
    ProcessRequest(httpContextBase);
}

protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
    IController controller;
    IControllerFactory factory;
    //取得 控制器工廠(預設DefaultControllerFactory) 和 要執行的Controller
    ProcessRequestInit(httpContext, out controller, out factory);

    try
    {
        controller.Execute(RequestContext);
    }
    finally
    {
        factory.ReleaseController(controller);
    }
}

小結

今天我們知道MVC使用HttpHandlerMvcHandler透過並MvcRouteHandler物件來返回.

下圖簡單展現MVC使用的HttpModuleHttpHandler關係

relationship_pic.PNG

  1. UrlRoutingMoudule註冊事件.
  2. 取得符合Http請求Route物件
  3. 呼叫MvcRouteHandler取得MvcHandler物件
  4. 執行MvcHandlerProcessReqeust方法

下面會陸續介紹MVC是如何取得Controller物件


上一篇
[Day09] 進入MVC原始碼世界 Route & RouteTable 原始碼解析
下一篇
[Day11] Asp.net MVC Controller是怎麼被建立
系列文
從Asp.net框架角度進入Asp.net MVC原始碼30

尚未有邦友留言

立即登入留言