MvcHandler : IHttpHandler
↓ ProcessRequest(HttpContext)
Controller : ControllerBase : IController
↓ Execute(RequestContext)
ControllerActionInvoker : IActionInvoker
↓ InvokeAction → FindAction → InvokeActionMethodWithFilters → InvokeActionResultWithFilters
ViewResultBase : ActionResult
↓ ExecuteResult → FindView → ViewEngine → View.Render
// MvcHandler.cs
protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
IController controller;
IControllerFactory factory;
ProcessRequestInit(httpContext, out controller, out factory); // 解析路由、建立 ControllerFactory
try
{
controller.Execute(RequestContext); // 執行 Controller
}
finally
{
factory.ReleaseController(controller); // 釋放 Controller
}
}
// Controller.cs
protected override void ExecuteCore()
{
PossiblyLoadTempData(); // 讀取 TempData
try
{
string actionName = RouteData.GetRequiredString("action");
if (!ActionInvoker.InvokeAction(ControllerContext, actionName))
HandleUnknownAction(actionName); // 404 或預設行為
}
finally
{
PossiblySaveTempData(); // 寫回 TempData
}
}
// ControllerActionInvoker.cs
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
{
var controllerDescriptor = GetControllerDescriptor(controllerContext);
var actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName); // 反射/快取尋找 MethodInfo
if (actionDescriptor == null) return false;
var filters = GetFilters(controllerContext, actionDescriptor); // Authorization/Action/Result/Exception Filters
// 1. Authorization Filters
var authContext = InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, actionDescriptor);
if (authContext.Result != null) { InvokeActionResult(controllerContext, authContext.Result); return true; }
// 2. Model Binding & Validation
if (controllerContext.Controller.ValidateRequest) ValidateRequest(controllerContext);
var parameters = GetParameterValues(controllerContext, actionDescriptor); // DefaultModelBinder
// 3. Action Filters + Action Method
var actionExecutedContext = InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, actionDescriptor, parameters);
// 4. Result Filters + ActionResult.ExecuteResult
InvokeActionResultWithFilters(controllerContext, filters.ResultFilters, actionExecutedContext.Result);
return true;
}
// ViewResultBase.cs
public override void ExecuteResult(ControllerContext context)
{
if (string.IsNullOrEmpty(ViewName))
ViewName = context.RouteData.GetRequiredString("action");
ViewEngineResult result = View ?? FindView(context); // RazorViewEngine / WebFormViewEngine
View = result.View;
using (var writer = context.HttpContext.Response.Output)
{
var viewContext = new ViewContext(context, View, ViewData, TempData, writer);
View.Render(viewContext, writer); // 呼叫 Razor 編譯產生的 Execute() 寫入 HTML
}
if (result != null) result.ViewEngine.ReleaseView(context, View);
}
| 階段 | 核心類別/方法 | 可擴充點 |
|---|---|---|
| 路由解析 | UrlRoutingModule → MvcHandler | 自訂 RouteBase、IRouteConstraint |
| Controller 建立 | DefaultControllerFactory → GetControllerInstance | IControllerFactory、DI 容器整合 |
| Action 選擇 | ControllerActionInvoker → FindAction | ActionMethodSelectorAttribute、ActionNameSelectorAttribute |
| 模型繫結 | DefaultModelBinder → BindModel | IModelBinder、ModelBinderProvider |
| 過濾器管線 | Authorization → Action → Result → Exception | FilterAttribute、IFilterProvider |
| View 解析 | ViewEngineCollection → FindView | IViewEngine、VirtualPathProvider |
| View 渲染 | RazorView → Render → Execute() | @helpers、HtmlHelper 擴充、TagHelper |
理解 MVC 管線從 `IHttpHandler` 進入、經由 `Controller`、`ActionInvoker`、Filter 管線、Model Binding、View Engine 到最終 `View.Render` 輸出,有助於: