前言
前一篇介紹路由封裝了Http請求路徑資訊可以讓我們找到相對應的Action和Controller並呼叫執行外,也可透過MapPageRoute來將請求教給.aspx實體檔案來處理請求.
Route甚至可以讓我們自己客製化處理HttpHandler 在Route中建立處理客製化HttpHandler可謂很有彈性
本篇介紹Route物件建立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使用IHttpHandler是MvcHandler
MVC呼叫的HttpHandler (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註冊事件. - 取得符合Http請求
Route物件 - 呼叫
MvcRouteHandler取得MvcHandler物件 - 執行
MvcHandler的ProcessReqeust方法
下面會陸續介紹MVC是如何取得Controller物件
如果本文對您幫助很大,可街口支付斗內鼓勵石頭^^

