概述 ASP.NET 平臺定義了兩個非常重要的生命周期。第一個是 應用生命周期 (application life cycle),用來追蹤應用從啟動的那一刻到終止的那一刻。另一個就是 請求生命周期 (request life cycle),它定義了 HTTP 請求在 ASP.NET 平臺中首次接收到
概述
ASP.NET 平臺定義了兩個非常重要的生命周期。第一個是 應用生命周期 (application life cycle),用來追蹤應用從啟動的那一刻到終止的那一刻。另一個就是 請求生命周期 (request life cycle),它定義了 HTTP 請求在 ASP.NET 平臺中首次接收到,到最終響應發出之間的路徑。
ASP.NET 應用生命周期
在 ASP.NET 中有兩個時刻——應用啟動的時刻和應用停止接收請求的時刻,這兩個時刻定義了應用生命周期。ASP.NET 在應用啟動和當應用在可控的情況下停止的時候提供了通知功能,我們接下來就討論這樣的通知功能。
應用生命周期通知允許了我們在應用啟動或者應用在可控的情況下停止的時候執行某些任務。如果我們在應用啟動的時候需要執行一次性的配置任務或者在應用停止的時候需要釋放資源的時候,通知就會變得非常有用。MVC 框架開發者在應用生命周期中最常使用的就是配置一個依賴註入容器。MVC 框架使用應用生命周期來執行與請求相關的配置任務,比如建立 routes, areas, 和 content bundles。
理解應用生命周期
ASP.NET 應用的生命周期從應用啟動的那一刻開始,在接收 HTTP 請求並處理生成響應的過程中一直延續。這包括將請求分配到合適的 controllers, actions 上,並從 Razor 視圖中渲染內容。生命周期直到應用停止的那一刻結束。
全局應用類在早期版本的 ASP.NET 中就已經存在了,它包含有兩個文件:Global.asax 和 Global.asax.cs。嚴格來講,Global.asax 文件才是全局應用類,而 Global.asax.cs 文件是與之關聯的隱藏代碼 (code-behind) 文件。這是一個很經典的 Web Forms 將聲明性代碼與編程性代碼分開的做法,但是現在,這僅僅是為了相容性,即使在 Web Forms 項目中。下麵是 Global.asax 文件中的內容,在 MVC 框架項目中,我們從不需要修改這個文件。
1 <%@ Application Codebehind="Global.asax.cs" Inherits="SimpleApp.MvcApplication" Language="C#" %>
之前版本中遺留下來的 Global.asax 文件多少都會有點有趣,但是,我們關註的重點還是 Global.asax.cs 文件。這個文件的角色在 ASP.NET 進化的過程中也慢慢地改變了,現在 全局應用類 這個術語一般直接用來指 Global.asax.cs 文件了,在解決方案資源管理器中雙擊 Global.asax 文件直接打開 Global.asax.cs 文件你就可以明白其中緣由了。
下麵是案例項目中 Global.asax.cs 文件中的內容:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using System.Web.Routing; 7 8 namespace SimpleApp 9 { 10 public class MvcApplication : System.Web.HttpApplication 11 { 12 protected void Application_Start() 13 { 14 AreaRegistration.RegisterAllAreas(); 15 RouteConfig.RegisterRoutes(RouteTable.Routes); 16 } 17 } 18 }
預設的全局應用類叫做 MvcApplication,繼承自 System.Web.HttpApplication 類。我們在後面會接觸到更多的 System.Web 命名空間下麵的類。
MvcApplication 類由 ASP.NET 框架實例化,這裡面定義的方法會在應用生命周期的關鍵時刻被調用。
預設的 MvcApplication 類中只包含了一個方法,叫做 Application_Start,但是還有另外一個方法可用,接下來我們就來介紹。
應用啟動和停止的時候接收通知
全局應用類支持兩種特殊的方法用來定義應用生命周期的開始與結束:
名稱 | 描述 |
Application_Start() | 當應用啟動的時候調用 |
Application_End() | 當應用將要終止的時候調用 |
Application_Start 方法在應用第一次啟動的時候被調用,並且提供了執行一次性配置任務的機會。比如,Visual Studio 在 Application_Start 方法中添加了建立 MVC areas 和 URL routes 的聲明。
Application_End方法僅會在應用終結之前執行,提供了釋放資源的機會。通常使用這個方法的理由就是釋放資料庫的連接,但是大多數的現代應用都不直接管理這樣的連接,我很少在自己的項目中使用到這個方法。而如今,資料庫已經能夠足夠好的管理它們的連接,而且,Application_End 方法僅會在應用在一個可控制的方式下關閉才會被調用到。因此我們不能夠依賴這個方法,因為伺服器可能發生不可預知的故障,比如突然斷電,這就會導致 Application_End 方法並不會被執行。
我說這些方法是 特殊 的是因為它們實現的方式特別。這些方法並沒有定義在全局應用類的基類中 (System.Web.HttpApplication),所以我們並不需要使用 override 關鍵字來實現它們。事實上,ASP.NET 框架使用反射的方式根據方法名稱來檢索它們。如果你寫錯了方法的名稱並不會得到任何的錯誤提示,ASP.NET 會假設你在應用開始或者結束的時候不想得到通知。正因為這樣,測試並確保你的代碼能夠被執行是非常重要的。
提示:有時候,我們在 Application_Start 和 Application_End 方法的定義中看到 Object 和 EventArgs 參數,這是為了遵循 C# 事件處理器方法的約定。這是可選的,ASP.NET 框架能夠定位到那些有這兩個參數或者沒有參數的方法。
圖 1 - 應用生命周期
測試啟動和停止通知
我們可以在應用中直接使用 Application_Start 和 Application_End 方法來執行一次性的啟動和關閉任務。接下來,我將會教大家怎麼使用調試器來確保者兩個方法能夠被執行——特別是在我們自定義代碼不能夠像我們預期的那樣執行的時候顯得格外重要。
最簡單的方法來測試這些方法是否被執行就是使用 Visual Studio 的調試器,下麵的代碼片段中,我們會看到怎麼在 Application_start 和 Application_End 方法中調用添加的靜態 System.Diagnostics.Debugger.Break 方法,這和我們在 Visual Studio 代碼編輯器中直接設置一個斷點的效果是一樣的。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using System.Web.Routing; 7 8 namespace SimpleApp 9 { 10 public class MvcApplication : System.Web.HttpApplication 11 { 12 protected void Application_Start() 13 { 14 AreaRegistration.RegisterAllAreas(); 15 RouteConfig.RegisterRoutes(RouteTable.Routes); 16 System.Diagnostics.Debugger.Break(); 17 } 18 19 protected void Application_End() 20 { 21 System.Diagnostics.Debugger.Break(); 22 } 23 } 24 }
測試啟動通知
測試 Application_Start 方法是非常簡單的,在 Visual Studio 調試菜單中選擇啟動調試,Visual Studio 會打開一個瀏覽器視窗。ASP.NET 框架開始初始化這個應用,創建了一個全局應用類的實例,發現了 Application_Start 方法,然後調用它,這將會引起 Break 方法被調用。應用的執行將會暫停,控制將會傳遞給調試器,如下圖所示:
圖 2 - Application_Start 方法調用的時候控制傳遞給調試器
在調試菜單中選擇繼續,應用的執行將會恢復。來自瀏覽器的請求將會被處理,並生成相應的 HTML 響應發送給用戶。
測試停止通知
測試 Application_End 方法有一點點困難,因為如果選擇停止調試將會導致在 Application_End 方法被調用之前調試器將會從應用上分離出去。瀏覽器視窗關閉,調試器終止掉,Visual Studio 將會返回到預設的狀態——然而,Debugger.Break 方法並沒有被調用。
為了測試 Application_End 中的代碼,我們必須直接使用 IIS Express,而非通過 Visual Studio。IIS Express 是 Visual Studio 中自帶的一個簡化版的 IIS 應用伺服器,只是用於在開發過程中運行 ASP.NET 應用的。
在 Windows 任務欄中定位到 IIS Express 圖標,右擊它會有一個彈窗菜單出現。在菜單項目中,我們會看到一個 SimpleApp 項目(應用名稱),當你選中它的時候會看到一個停止站點菜單項目,如下圖所示:
圖 3 - 使用 IIS Express 停止一個應用
當選擇停止站點的時候,IIS Express 會停止這個應用,作為處理過程的一部分,Application_End方法將會被調用。在本例中,Debugger.Break 方法將會被調用,如下圖所示:
圖 4 - 測試 Application_End 方法中的代碼
[根據 Adam Freeman – Pro ASP.NET MVC 5 Platform 選譯]