欢迎光临
我们一直在努力

[ASP.NET]分析MVC5源码,并实现一个ASP.MVC

本节内容不是mvc入门教程,主要讲MVC原理,实现一个和ASP.NET MVC类似基本原理的项目.

 

MVC原理是依赖于ASP.NET管道事件基础之上的.对于这块,可阅读上节内容

 

 

 

本节目录:

 

MVC简介

随着技术的发展,现在已经将MVC模式等同于三层模式。

如果要严格区分的话,UI层指View和Controller,BLL,DAL层和模型层都属于Model中。

 

在建立MVC项目的时候,选择空的项目,会建立一个如下的项目结构

[ASP.NET]分析MVC5源码,并实现一个ASP.MVC

 

由于MVC具有以下优点

  1. 性能高,不需要经过复杂的控件生命周期
  2. SEO,页面干净,没有ViewState,url地址没后缀名
  3. 扩展多,actionresult各种子类,轻松返回JSON,string
  4. Razor视图引擎
  5. ....

所以MVC不得不成为ASP.NET的首选开发

 

扩展

Action的本质就是方法,只要是public的方法,外部都能访问到

 

 

 

 

 

MVC原理

路由系统

类图

[ASP.NET]分析MVC5源码,并实现一个ASP.MVC

 

代码图

路由对象

[ASP.NET]分析MVC5源码,并实现一个ASP.MVC

路由系统

[ASP.NET]分析MVC5源码,并实现一个ASP.MVC

 

 

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必经之路.

[ASP.NET]分析MVC5源码,并实现一个ASP.MVC

 

 

 

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请求流程

  1. 到达URLModule的第7个Application事件
  2. 首先根据URL,找到并创建MVCHandle(继承IHttpHandle),
  3. 映射IHttpHandlehttpContext.RemapHandler(handler)
  4. 在第11个Application事件后,执行MVCHandle的PR方法
  5. 根据URL,创建指定Controller(继承Controller,ControllerBase,IController),调用IController的Execute的方法.
  6. 在ControllerBase的Execute方法的调用抽象方法ExecuteCore
  7. 在Controller的ExecuteCore方法调用ActionInvoker(这个属性实现类是ControllerActionInvoker)的InvokeAction方法
  8. 执行MVC过滤器
  9. 调用控制器的方法,得到ActionResult
  10. 调用ActionResult的ExecuteResult方法
  11. Response输出

 

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源码也很简单,这里我们干脆把路由系统和MVC用到的类都实现出来,完全脱离System.MVC和System.Web.Routing2个程序集

代码效果

[ASP.NET]分析MVC5源码,并实现一个ASP.MVC

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"); } } 

 

 

运行效果

[ASP.NET]分析MVC5源码,并实现一个ASP.MVC

[ASP.NET]分析MVC5源码,并实现一个ASP.MVC

性能

[ASP.NET]分析MVC5源码,并实现一个ASP.MVC

 

 

后台代码

点击下载 

[ASP.NET]分析MVC5源码,并实现一个ASP.MVC

 

说明:本实现代码主要偏MVCHandle一块

 

扩展

从微软的源码中可以看出微软偏爱于AOP和面向接口的编程方式.

  • 海报
海报图正在生成中...
赞(0) 打赏
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
文章名称:《[ASP.NET]分析MVC5源码,并实现一个ASP.MVC》
文章链接:https://www.456zj.com/20383.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址