本節內容不是MVC入門教程,主要講MVC原理,實現一個和ASP.NET MVC相似基本原理的項目.html
MVC原理是依賴於ASP.NET管道事件基礎之上的.對於這塊,可閱讀上節內容編程
本節目錄:緩存
隨着技術的發展,如今已經將MVC模式等同於三層模式。源碼分析
若是要嚴格區分的話,UI層指View和Controller,BLL,DAL層和模型層都屬於Model中。post
在創建MVC項目的時候,選擇空的項目,會創建一個以下的項目結構性能
因爲MVC具備如下優勢ui
因此MVC不得不成爲ASP.NET的首選開發this
擴展url
Action的本質就是方法,只要是public的方法,外部都能訪問到
路由系統
類圖
代碼圖
路由對象
路由系統
RouteTable
路由表,有個RouteDictionary屬性,存放RouteBase的實現類Route。經過Route能返回RouteData.
RouteData中包括
路由系統原理
首先添加一條路由對象,路由對象至關於定製一個url模板
而後建立一個Controller工廠,用來反射調用Controller方法,並緩存全部Controller Type,將其賦值給ControllerBuilder,這個是一個單例對象.
UrlRoutingModule
註冊第7個事件,而且根據HttpContext(實際就是讀取URL),從RouteTable中獲取到RouteData,
而後經過RouteData獲取IHttpHandler
擴展:
路由系統依賴UrlRoutingModule,而這個在默認配置的Web.config中已經配置,因此路由並非ASP.Net MVC專屬,而是Asp.Net必經之路.
ActionResult
咱們的Action實際上就是返回一個ActionResult.
實際上ActionResult是HttpHandle中PR方法最終輸出也是最核心的方法.
這裏看下ActionResult源碼和JsonResult源碼
public abstract class ActionResult { public abstract void ExecuteResult(ControllerContext context); }
public class JsonResult : ActionResult { public object Data { get; set; } public JsonRequestBehavior JsonRequestBehavior { get; set; } public JsonResult() { this.JsonRequestBehavior = JsonRequestBehavior.DenyGet; } public override void ExecuteResult(ControllerContext context) { JavaScriptSerializer scriptSerializer = new JavaScriptSerializer(); if (this.MaxJsonLength.HasValue) scriptSerializer.MaxJsonLength = this.MaxJsonLength.Value; if (this.RecursionLimit.HasValue) scriptSerializer.RecursionLimit = this.RecursionLimit.Value; response.Write(scriptSerializer.Serialize(this.Data)); } }
MVC請求流程
IController
public interface IController { void Execute(RequestContext requestContext); }
ControllerBase(精簡源碼)
protected virtual void Execute(RequestContext requestContext) { this.Initialize(requestContext); using (ScopeStorage.CreateTransientScope()) this.ExecuteCore(); }
Controller
protected override void ExecuteCore() { this.PossiblyLoadTempData(); try { string requiredString = this.RouteData.GetRequiredString("action"); if (this.ActionInvoker.InvokeAction(this.ControllerContext, requiredString)) return; this.HandleUnknownAction(requiredString); } finally { this.PossiblySaveTempData(); } }
ControllerActionInvoker
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName) { if (controllerContext == null) throw new ArgumentNullException("controllerContext"); if (string.IsNullOrEmpty(actionName)) throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName"); ControllerDescriptor controllerDescriptor = this.GetControllerDescriptor(controllerContext); ActionDescriptor action = this.FindAction(controllerContext, controllerDescriptor, actionName); if (action == null) return false; FilterInfo filters = this.GetFilters(controllerContext, action); try { AuthorizationContext authorizationContext = this.InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, action); if (authorizationContext.Result != null) { this.InvokeActionResult(controllerContext, authorizationContext.Result); } else { if (controllerContext.Controller.ValidateRequest) ControllerActionInvoker.ValidateRequest(controllerContext); IDictionary<string, object> parameterValues = this.GetParameterValues(controllerContext, action); ActionExecutedContext actionExecutedContext = this.InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, action, parameterValues); this.InvokeActionResultWithFilters(controllerContext, filters.ResultFilters, actionExecutedContext.Result); } } catch (ThreadAbortException ex) { throw; } catch (Exception ex) { ExceptionContext exceptionContext = this.InvokeExceptionFilters(controllerContext, filters.ExceptionFilters, ex); if (!exceptionContext.ExceptionHandled) throw; else this.InvokeActionResult(controllerContext, exceptionContext.Result); } return true; }
從這個方法中,也能夠看出MVC過濾器的執行順序.
(MVC沒有WebForm的控件生命週期,可是提供過濾器實現相似效果性能更高.)
這個方法中的InvokeActionResult方法實際就是調用
protected virtual void InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) { actionResult.ExecuteResult(controllerContext); }
也就到達咱們最上面的ActionResult的抽象方法中了.
至此MVC核心源碼分析結束了.
看完MVC源碼,實現一個MVC源碼也很簡單,這裏咱們乾脆把路由系統和MVC用到的類都實現出來,徹底脫離System.MVC和System.Web.Routing2個程序集
代碼效果
Global文件
public class Global : HttpApplication { protected void Application_Start(object sender, EventArgs e) { RouteTable.Routes.Add("default", new Route()); } }
HomeController
public class HomeController : Controller { public ActionResult Index() { return Content("Hello World"); } }
運行效果
性能
後臺代碼
說明:本實現代碼主要偏MVCHandle一塊
擴展
從微軟的源碼中能夠看出微軟偏心於AOP和麪向接口的編程方式.