前一篇介紹路由封裝了Http請求路徑資訊可以讓我們找到相對應的Action
和Controller
並呼叫執行外,也可透過MapPageRoute
來將請求教給.aspx
實體檔案來處理請求.
Route
甚至可以讓我們自己客製化處理HttpHandler
在Route中建立處理客製化HttpHandler可謂很有彈性
本篇介紹Route
物件建立MvcRouteHandler
物件且如何取到IHttpHandler
.
我有做一個可以針對於Asp.net MVC Debugger的專案,只要下中斷點就可輕易進入Asp.net MVC原始碼
此篇同步發布在筆者Blog [Day10] 透過MvcRouteHandler取得呼叫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使用IHttpHandler
是MvcHandler
MvcHandler
類別中主要核心的程式碼做了幾件事情.
Adapter
對於HttpContext
物件把他轉成可以繼承於HttpContextBase
的HttpContextWrapper
類別.ProcessRequestInit
取得執行controller
物件並且呼叫執行方法.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使用HttpHandler
是MvcHandler
透過並MvcRouteHandler
物件來返回.
下圖簡單展現MVC使用的HttpModule
和HttpHandler
關係
UrlRoutingMoudule
註冊事件.Route
物件MvcRouteHandler
取得MvcHandler
物件MvcHandler
的ProcessReqeust
方法下面會陸續介紹MVC是如何取得Controller
物件