🚫 Ad Blocker Detected

Please disable your AD blocker to continue using this site. Ads help us keep the content free! please press keyboard F5 to refresh page after disabled AD blocker

請關閉廣告攔截器以繼續使用本網站。廣告有助於我們保證內容免費。謝謝! 關閉後請按 F5 刷新頁面

0%

透過MvcRouteHandler取得呼叫IHttphandler (第10天)

Agenda

前言

前一篇介紹路由封裝了Http請求路徑資訊可以讓我們找到相對應的ActionController並呼叫執行外,也可透過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)
{
//設置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釋放之前使用過資源
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;
//取得 控制器工廠(預設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物件

__此文作者__:Daniel Shih(石頭)
__此文地址__: https://isdaniel.github.io/Ithelp-day10/
__版權聲明__:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!

如果本文對您幫助很大,可街口支付斗內鼓勵石頭^^