本节内容不是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和面向接口的编程方式.