Skip to main content

[探索 5 分鐘] 淺談 ASP.NET MVC 的生命週期

任何「生命週期」的探討都是一門學問, ASP.NET MVC Life Cycle 的官網以及網路文獻也很多,今天找到一個淺顯易懂的版本 ASP.NET MVC - Life Cycle

他將所謂的生命週期分兩個來探討, 然後再配上圖片 :
  • The application life cycle
  • The request life cycle
Web Application 的生命週期是起於 IIS (或其他 web server) 運行應用程式, 終止於服務暫停, 回收或關閉。但細部的 process 是: 當第一個請求發出時, 觸發 Application_Start() 事件 (Global.asax.cs 文件中), 做應用程式初始配置、路由設定等等載入工作。但當 web 服務器回收應用程序或在一段不活動狀態 (InActive) 或超過 cpu、memory 閾值之後, Application_End() 事件將觸發, 接下來的請求將被視為第一個請求, 並且再次觸發 Application_Start() 事件。


request 比較複雜, 但對 MVC 有概念的人大方向應該可以抓出一個順序: request → routing → controller → action → result → response。
提醒兩點, 應該有看到一個 Controller Intialization ? 順便分享一下, 過去曾有專案有效能問題, 結果是 Controller 建構子做了一些 AutoMapper.Attributes 的 mapping 動作, 天真以為他只會初始化一次。但 sorry, 是每一個請求都會進入構造函式, 這邊慢, 大家就一起漫步了。第二點, 不是每個 result 都需要 view engine 處理, 我們也可以回傳一個字串, JSON..., 對吧 ? 所以上圖 Result Execution 才會有兩種處理方式。

System.Web.Mvc / MvcHandler.cs 的 程式碼 也滿值得欣賞一下。是由 IControllerFactory 類來創建 Controller 實體去執行後續動作 :

protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
    SecurityUtil.ProcessInApplicationTrust(delegate
    {
        IController controller;
        IControllerFactory factory;
        this.ProcessRequestInit(httpContext, out controller, out factory);
        try
        {
            controller.Execute(this.RequestContext);
        }
        finally
        {
            factory.ReleaseController(controller);
        }
    });
}
再深入一點, 來看 Detailed ASP.NET MVC Pipeline 的大圖 :
是不是眼花撩亂 ? 其實 request 的生命周期不離開一開始介紹的原則 :
  • request → routing → controller → action → result → response
大圖版本 - 不須 rendering :
  • request → routing → controller initialization → action execution → result execution → response
大圖版本 - 需要 rendering
  • request → routing → controller initialization → action execution → result execution → view initialization & rendering → response
掌握這些大小原則, 要客製化一些檢核點或過濾器 (filter), 是不是就比較清楚他在整個流程中的相對位置了呢。不過還是要多開發, 累積實戰經驗, 最後才會內化為個人的知識。下面這一段程式碼, 是一個 filter 過濾器, 你覺得會在 life cycle 中的哪一個地方被執行呢 ?

public class CustomAuthorizationAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        bool isAuthorized = GoCheckToken(filterContext);
        if (!isAuthorized)
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }
}

參考資料

  • https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/lifecycle-of-an-aspnet-mvc-5-application
  • http://www.dotnettricks.com/learn/mvc/aspnet-mvc-request-life-cycle
  • https://www.tutorialspoint.com/asp.net_mvc/asp.net_mvc_life_cycle.htm
  • https://www.tektutorialshub.com/asp-net-mvc-request-life-cycle/
  • http://www.dotnettricks.com/learn/mvc/detailed-aspnet-mvc-pipeline
  • https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Mvc/MvcHandler.cs

Comments

Post a Comment