[ASP.NET]分析MVC5源碼,並實現一個ASP.MVC

本節內容不是MVC入門教程,主要講MVC原理,實現一個和ASP.NET MVC相似基本原理的項目.html

 

MVC原理是依賴於ASP.NET管道事件基礎之上的.對於這塊,可閱讀上節內容編程

[ASP.NET]談談IIS與ASP.NET管道

 

 

 

本節目錄:緩存

 

MVC簡介ide

隨着技術的發展,如今已經將MVC模式等同於三層模式。源碼分析

若是要嚴格區分的話,UI層指View和Controller,BLL,DAL層和模型層都屬於Model中。post

 

在創建MVC項目的時候,選擇空的項目,會創建一個以下的項目結構性能

 

因爲MVC具備如下優勢ui

  1. 性能高,不須要通過複雜的控件生命週期
  2. SEO,頁面乾淨,沒有ViewState,url地址沒後綴名
  3. 擴展多,ActionResult各類子類,輕鬆返回JSON,string
  4. Razor視圖引擎
  5. ....

因此MVC不得不成爲ASP.NET的首選開發this

 

擴展url

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

相關文章
相關標籤/搜索