ASP.NET MVC由以下兩個核心組成部分構成:
- 一個名為UrlRoutingModule的自定義HttpModule,用來解析Controller與Action名稱;
- 一個名為MvcHandler的自定義HttpHandler,用來實現對Controller的啟用和Action的執行;
!!閱讀本文前請先弄明白asp.net執行的流程及httpmodule與httphandler的作用。
下面是進行路由轉換時相關類的簡化結構圖:
整個ASP.NET MVC系統的路由資訊全部存放在RoteTable這個類的靜態變數Routes(為一個RouteDictionary型別)中,網站開始執行時,在Application_Start中對路由進行註冊:
RouteTable.Routes.Add("default", new Route{Url="{controller}/{action}"});
當一個URL請求到來時,被UrlRoutingModule攔截,攔截後執行流程如下:
- 封裝當前http上下文,變為HttpContextWrapper物件。
- 根據當前的http上下文,從Routes中得到與當前請求URL相符合的RouteData物件。該物件儲存有RouteHandler資訊。
- 把RouteData與http上下文請求封裝成一個RequestContext物件。
- 根據RequestContext物件,從RouteData的RouteHandler中獲取IHttpHandler。
- 執行IHttpHandler,進行請求的真正處理。
執行時序圖如下圖所示:
UrlRoutingModule的程式碼如下:
HttpContextWrapper httpContext = new HttpContextWrapper(HttpContext.Current); RouteData routeData = RouteTable.Routes.GetRouteData(httpContext); RequestContext requestContext = new RequestContext{ data = routeData, context= httpContext}; IHttpHandler handler = routeData.RouteHandler.GetHttpHandler(requestContext); httpContext.RemapHandler(handler);
經過上面最後一步,執行HttpHandle後,程式正式進入Controller啟用裡面,相關類關係如下圖所示:
同URL路由一樣,MVC初始化時,也需要註冊控制器的一些資訊,這裡是要讓框架知道預設的控制器工廠是什麼,所以在Application_Start中:
ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory());
程式通過上面的URL路由轉換後,進入HttpHandle中,經過以下步驟實現對Controller的啟用:
- 從Requestcontext封裝的RouteData中得到Controller名字。
- 通過ControllerBuilder得到當前預設的Controller工廠。
- 根據Controller的名字,建立控制器物件(在ControllerFactory初始化的時候,會掃描整個程式集中所有實現IController介面的控制器型別,所以當呼叫CreateController時,實際上是直接獲取)。
- 最後執行控制器。執行的實質其實就是執行ActionInvoker.InvokeAction,即根據請求上下文執行相應的Action。
在自定義的MvcHandler中,程式碼如下:
string controllerName =this.Requestcontext.RouteData.Controller; IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory(); IController controller = controllerFactory.CreateController(this.RequestContext,controllerName); controller.Execute(this.RequestContext);
一個典型的IActionInvoker介面實現ControllerActionInvoker的InvokeAction方法如下:
public void InvokeAction(ControllerContext controllerContext, string actionName) { //找到Action方法 MethodInfo method = controllerContext.Controller.GetType().GetMethods() .First(m=>string.Compare(actionName,m.Name,true)==0); //獲取Action引數,並進行Model繫結 List<object> parameters = new List<object>(); foreach(ParameterInfo parameter in method.GetParameters()) { parameters.Add(this.ModelBinder.BindModel(controllerContext, parameter.Name, parameter.ParameterType)); } //執行Action,並得到ActionResult ActionResult actionResult = method.Invoke(controllerContext.Controller, parameters.ToArray()) as ActionResult; //最終ActionResult用HttpResponse將資料傳回客戶進行顯示 actionResult.ExecuteResult(controllerContext); }
最終形成一個Http Response傳回到客戶端!!
以上即為我整理的ASP.NET MVC的兩個核心流程,希望新手看的明白,老手多多指點其中的問題,謝謝!!有時間會繼續放出MVC其它核心技術。如Model繫結、資料驗證等,同時認真向Artech學習!!!!