ASP.NET MVCの処理(Controller、Viewの実行される場所について)
ASP.NET MVCが処理される流れとして、ちょっと御幣がありますが、まずはSystem.Web.Mvc.MvcHandler#ProcessRequest内で以下な感じで実行される。
public class MvcHandler : IHttpHandler, IRequiresSessionState { protected internal virtual void ProcessRequest(HttpContextBase httpContext) { AddVersionHeader(httpContext); // Get the controller type string controllerName = RequestContext.RouteData.GetRequiredString("controller"); // Instantiate the controller and call Execute IControllerFactory factory = ControllerBuilder.GetControllerFactory(); IController controller = factory.CreateController(RequestContext, controllerName); if (controller == null) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentUICulture, MvcResources.ControllerBuilder_FactoryReturnedNull, factory.GetType(), controllerName)); } try { controller.Execute(RequestContext); } finally { factory.ReleaseController(controller); } }
見て察せられるとおり、factory.CreateController内でリフレクション使ってコントローラ作ってます。デフォルトでは「System.Web.Mvc.DefaultControllerFactory」が登録されてまして、この子を読むと内部操作がわかります。
次に、System.Web.Nvc.Controller#Excecute内の中身なのですが、
public abstract class ControllerBase : MarshalByRefObject, IController { (中略) protected virtual void Execute(RequestContext requestContext) { if (requestContext == null) { throw new ArgumentNullException("requestContext"); } Initialize(requestContext); ExecuteCore(); } (中略) } public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter { (中略) protected override void ExecuteCore() { TempData.Load(ControllerContext, TempDataProvider); try { string actionName = RouteData.GetRequiredString("action"); if (!ActionInvoker.InvokeAction(ControllerContext, actionName)) { HandleUnknownAction(actionName); } } finally { TempData.Save(ControllerContext, TempDataProvider); } } (中略) }
内部でわかる通り、デフォルトではControllerBase#Excecuteが実行されて、そいつからController#ExcuteCoreが呼び出されます。メソッド内部で呼び出されるActionInvoker#InvokeActionがアクション実行、フィルター実行、レンダー実行をすべて握っていたりします。
ActionInvokerはControllerから指定されたactionNameに対応するメソッドをリフレクションを使って実行し、各種フィルタを実行します。次に、ActionResult(通常はViewResult)を用いてResponseに対する後処理(IView#Render)を実行します。(後で、その辺りもまとめるとしよう)
一応、ビューが実行されるまでの流れ自体は書いておこう(備忘録的な意味で)。
- ControllerActionInvoker#InvokeAction
- ControllerActionInvoker#InvokeActionResultWithFilters(例外が発生した場合は直にControllerActionInvoker#InvokeActionResult)
- ControllerActionInvoker#InvokeActionResult
- ActionResult#ExecuteResult
- (ViewResultの場合は)ViewResultBase#ExecuteResult
- (FindViewを実行されて)View#Render
とかになってる。この辺りの流れさえわかってると、ASP.NET MVCで何が起こってるかは大体追えると思う。