Agenda
前言
上篇得知MVC預設透過DefaultControllerFactory反射方式動態建立Controller物件
本篇會分享我們常用到Controller基礎類別和相關物件.
我有做一個可以針對於Asp.net MVC Debugger的專案,只要下中斷點就可輕易進入Asp.net MVC原始碼.
ControllerBase(Controller基礎類別)
ControllerBase具有如下幾個重要的屬性
TempData:將設置資料存於Session中,生命週期除了當下請求, 導頁後仍可續存.ViewBag:儲存Controller向view傳遞資料或變數 (型別dynamic)ViewData:儲存Controller向view傳遞資料或變數 (型別ViewDataDictionary)
雖說ViewBag和ViewData看起來使用不同的物件,但從程式碼了解到其實ViewBag也是使用ViewData引用.
1 | public abstract class ControllerBase : IController |
SessionStateTempDataProvider 控制儲存TempData
上面說到TempData字典集合生命週期除了當下請求, 導頁後仍可續存.原因是在SessionStateTempDataProvider將資料存在Session中
1 | controllerContext.HttpContext.Session["__ControllerTempData"] |
可以透過上面程式碼取得當前的TempData字典集合物件.
ControllerBase Excute方法
ControllerBase這個類別繼承IController,前篇說到在HttpHandler ProcessRequest方法會透過反射找到一個符合Http請求IController介面物件.
並呼叫其Execute方法
在Execute做了幾件事情.
- 初始化
ControllerContext物件,對於RequestContext簡易封裝. ExecuteCore呼叫Hock方法(ExecuteCore是一個抽象方法提供繼承他的物件實做,預設是Controller類別)
1 | protected virtual void Execute(RequestContext requestContext) |
Controller
在專案中Controller是我們預設使用繼承控制器類別,此類別中定義了很多的輔助方法和屬性讓撰寫控制器變得簡單。Controller類別除了直接繼承ControllerBase之外,Controller還顯式實現IController和IAsyncController介面,跟ASP.NET MVC 四大篩選器(IAuthorizationFilter,IActionFilter、IResultFilter,IExceptionFilter)的4個介面。
1 | public abstract class Controller : |
ExecuteCore
在Controller重載實做ExecuteCore方法.
主要透過GetActionName(RouteData)取得執行的Action名稱,並透過ActionInvoker取得要Invoker的ActionInvoker.
PossiblyLoadTempData:建立載入TempDataPossiblySaveTempData:儲存TempData的資料
1 | protected override void ExecuteCore() |
ControllerContext
第一次初始話ControllerContext利用建構子
1 | public ControllerContext(RequestContext requestContext, ControllerBase controller) |
在ControllerBase.Initialize方法對於ControllerContext初始化,這個上下文資料封裝了許多此次請求的資料.
1 | protected virtual void Initialize(RequestContext requestContext) |
後面對於繼承ControllerContext的Context傳入第一次初始化ControllerContext物件,
在建構子函數把傳入ControllerContext的RequestContext資料填入繼承ControllerContext物件中
下面是MVC有繼承ControllerContext類別
- AuthorizationContext
- ExceptionContext
- AuthenticationChallengeContext
- ResultExecutedContext
- ViewContext
- ResultExecutingContext
ControllerContext
在原始碼中可以看到ControllerContext(ControllerContext controllerContext)很巧妙把自身類別當作建構子方法參數傳入.
1 | Controller = controllerContext.Controller; |
主要是要把RequestContext值給填充,之後就可以利用RequestContext取得理面一些資料.
1 | public class ControllerContext |
AuthorizationContext
我們看一下Authorizationfilter用到的參數AuthorizationContext.
在InvokeAuthorizationFilters方法將AuthorizationContext初始化
1 | AuthorizationContext context = new AuthorizationContext(controllerContext, actionDescriptor); |
其中傳入參數controllerContext是第一次透過ControllerBase.Initialize初始化Context.
1 | public class AuthorizationContext : ControllerContext |
之後再呼叫base(controllerContext)利用ControllerContext建構子把資料填充.
小結:
Asp.net MVC對於為了方便我們使用控制器所以對於Controller進行許多資料封裝,讓我們只要繼承Controller就可以方便使用許多屬性.
下圖是Controller核心類別關係圖.Controller類別左右兩側有本次沒介紹到類別(之後會介紹到)

當我看到ControllerContext的設計時讓我驚艷的,因為他把MVC用到Context都關聯綁定到一個類別中.
因為在商業邏輯中會有許多Model類別,且這些類別資料存在一定的相關性,我覺得這個設計可以使用可以大大改善資料傳遞上的麻煩,讓程式寫起來更安全,簡單
之後我會把上面的UML圖慢慢畫出來,一步一步揭開Asp.net MVC面紗.
__此文作者__:Daniel Shih(石頭)
__此文地址__: https://isdaniel.github.io/Ithelp-day12/
__版權聲明__:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!