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

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

 

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

[ASP.NET]谈谈IIS与ASP.NET管道

 

 

 

本节目录:

 

MVC简介

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

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

 

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

 

由于MVC具有以下优点

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

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

 

扩展

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

 

 

 

 

 

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

 

 

 

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个程序集

代码效果

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和面向接口的编程方式.

转载于:https://www.cnblogs.com/neverc/p/4823497.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ASP.NET MVC 5 框架揭秘》以一个模拟ASP.NET MVC内部运行机制的“迷你版MVC框架”作为开篇,其目的在于将ASP.NET MVC真实架构的“全景”勾勒出来。接下来本书以请求消息在ASP.NET MVC框架内部的流向为主线将相关的知识点串连起来,力求将”黑盒式”的消息处理管道清晰透明地展示在读者面前。相信精读本书的读者一定能够将ASP.NET MVC从接收请求到响应回复的整个流程了然于胸,对包括路由、Controller的激活、Model元数据的解析、Action方法的选择与执行、参数的绑定与验证、过滤器的执行以及View的呈现等相关的机制具有深刻的理解。 本书以实例演示的方式介绍了很多与ASP.NET MVC相关的很好实践,同时还提供了一系列实用性的扩展,相信它们一定能够解决你在真实开发过程中遇到的很多问题。本书末章提供的案例不仅仅用于演示实践中的ASP.NET MVC,很多的架构设计方面的东西也包含其中。除此之外,本书在很多章节还从设计的角度对ASP.NET MVC的架构进行了深入分析,所以从某种意义上讲本书可以当成一本架构设计的书来读。 ASP.NET MVC 5 框架揭秘 目录 第1章 ASP.NET + MVC 第2章 路由 第3章 Controller的激活 第4章 Model元数据的解析 第5章 3个描述对象 第6章 Model的绑定(上篇) 第7章 Model的绑定(下篇) 第8章 Model的验证(上篇) 第9章 Model的验证(下篇) 第10章 Action方法的执行 第11章 View的呈现 第12章 过滤器 第13章 特性路由 第14章 案例实践

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值