Agenda
前言
前一篇介紹路由封裝了Http請求路徑資訊可以讓我們找到相對應的Action和Controller並呼叫執行外,也可透過MapPageRoute來將請求教給.aspx實體檔案來處理請求.
Route甚至可以讓我們自己客製化處理HttpHandler 在Route中建立處理客製化HttpHandler可謂很有彈性
本篇介紹Route物件建立MvcRouteHandler物件且如何取到IHttpHandler.
我有做一個可以針對於Asp.net MVC Debugger的專案,只要下中斷點就可輕易進入Asp.net MVC原始碼.
MVC取得使用HttpHandler (IHttpHandler)
之前說到我們透過MapRoute擴展方法加入一個Route物件給RouteCollection全域路由集合.
在Route使用的IRouteHandler介面是由MvcRouteHandler來實現
1 2 3 4 5 6
| Route route = new Route(url, new MvcRouteHandler()) { Defaults = CreateRouteValueDictionaryUncached(defaults), Constraints = CreateRouteValueDictionaryUncached(constraints), DataTokens = new RouteValueDictionary() };
|
IRouteHandler最重要的是IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)會取得一個IHttpHandler物件.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| 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"]; 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釋放之前使用過資源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| protected virtual void ProcessRequest(HttpContext httpContext) { HttpContextBase httpContextBase = new HttpContextWrapper(httpContext); ProcessRequest(httpContextBase); }
protected internal virtual void ProcessRequest(HttpContextBase httpContext) { IController controller; IControllerFactory factory; ProcessRequestInit(httpContext, out controller, out factory);
try { controller.Execute(RequestContext); } finally { factory.ReleaseController(controller); } }
|
小結
今天我們知道MVC使用HttpHandler是MvcHandler透過並MvcRouteHandler物件來返回.
下圖簡單展現MVC使用的HttpModule和HttpHandler關係
![relationship_pic.PNG]()
- 在
UrlRoutingMoudule註冊事件.
- 取得符合Http請求
Route物件
- 呼叫
MvcRouteHandler取得MvcHandler物件
- 執行
MvcHandler的ProcessReqeust方法
下面會陸續介紹MVC是如何取得Controller物件
此文作者:Daniel Shih(石頭)
此文地址: https://isdaniel.github.io/ithelp-day10/
版權聲明:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!