ASP.NET (WEB FORM) 網頁生命週期探索

John Tsai
7 min readAug 29, 2018

--

最近面試被問到WEB FORM 的頁面生命週期,雖是意料中的問題但覺得自己回答得不夠完整,且當下腦中浮現的反而是MVC的生命週期…… 為避免觀念混淆故從新學習並筆記一次。

首先我們先從ASP.NET 對Client 發起的Request處理進程做講解,參考下圖:

Image source: https://msdn.microsoft.com

可藉由上方圖解快速理解一遍: ASP.NET 請求處理過程是基於管道模型,這個管道模型是由多個HttpModule和HttpHandler組成,ASP.NET 把http請求依次傳遞給管道中各個HttpModule,最終被HttpHandler處理,處理完成後,再次經過管道中的HttpModule,把結果返回給客戶端。

以下為較詳細的流程解釋:

Client 端發送request到IIS server時,ASP.NET的處理可分為以下兩大步驟:

(1)ASP.NET會創建一個能夠處理request的作業環境。它會創建一個可處理request、response以及context對象的應用進程。

(2)一旦ASP.NET環境被創建,request就會通過由HttpModule、Http Handler 和page objects 所觸發的一系列事件。
為方便記憶我們可將這些流程稱為: MHPM(Module、Handler、Page and Module Event)。

以下針對兩大步驟進行更詳細的流程說明:

Step 1:Request到達IIS後,IIS會檢查哪一個ISAPI Extension能夠處理這個request,這取決於文檔的後綴名。
EX:’.aspx’=> 會被傳遞到’aspnet_isapi.dll’來進行處理。

Step 2:如果這是針對該網站的首次request,會由’ApplicationManager’類別 創建一個該網站可以運行的應用程式定義域(App Domain)。該定義域隔離部署在同一台IIS server上的兩個不同的Web Application,所以即使其中一個定義域中的程式出現了錯誤,也不會影響其他定義域的正常運作。

Step 3:在創建應用程式定義域後,建立hosting 環境HttpRuntime 物件,一旦hosting環境被創建完成,處理requset的核心物件如HttpContext、HttpRequest和HttpResponse都會被創建。

Step 4: 在初始化所有應用程式物件後,會藉由建立 HttpApplication 類別的執行個體來啟動應用程式。如果應用程式有 Global.asax 檔案,則 ASP.NET 會建立 Global.asax 類別的執行個體 (此類別衍生自 HttpApplication 類別)。然後使用衍生的類別來代表此應用程式。

目前為止的說明圖像化

Step 5: 應用程式啟動後,基於HttpApplication類別執行個體,request就會通過由HttpModule、HttpHandler 和page objects 所觸發的一系列事件。

多到有點數不清的事件會在一個request中被觸發

在文章一開始提到的頁面生命週期,就發生在MHPM 中的Page ,其實也就是我們的.aspx 頁面;一個Page的實例,其本身就是此request流程中的HttpHandler 本人啦! 因它繼承實作了 IHttpHandler 介面。

由上圖可知,在Page也有一個獨立的生命週期,從頁面的建立到卸載都有其對應的事件可以供開發者注入客制邏輯,以下介紹其可用事件:

====Init====

在初始化所有控制項並套用任何面板設定之後引發。這個事件可以用於讀取或初始化控制項屬性。

====InitComplete====

由 Page 物件引發。這個事件可以用於處理需要完成所有初始設定的工作。

====PreLoad====

如果需要在 Load 事件之前先處理網頁或控制項,請使用這個物件。

在 Page 引發這個事件之後,會先載入其本身和所有控制項的檢視狀態,再處理 Request 執行個體 (Instance) 所包含的任何回傳資料。

====Load====

Page 會先呼叫 Page 上的 OnLoad 事件方法,再遞迴地為每個子控制項執行相同動作,它會為其每個子控制項執行相同動作,直到載入完網頁和所有控制項為止。

OnLoad 事件方法可以用於設定控制項中的屬性,以及建立資料庫連接。

====控制項事件====

這些控制項事件可以用於處理特定控制項事件,例如 Button 控制項的 Click 事件,或 TextBox 控制項 TextChanged 事件。

====LoadComplete====

這個事件可以用於需要載入網頁上所有其他控制項的工作。

====PreRender====

在這個事件發生之前:

每個已設定其 DataSourceID 屬性的資料繫結控制項會呼叫其 DataBind 方法。

每個控制項的 PreRender 事件都會發生在網頁上。這個事件可以用於對網頁或其控制項的內容進行最終的變更。

====SaveStateComplete====

這個事件可以用於執行需要儲存檢視狀態但不對控制項做任何變更的工作。

====Render====

這個不是一個事件;相反地,在這個處理階段,Page 物件會呼叫每個控制項上的這個方法。所有 ASP.NET Web 伺服器控制項都有 Render 方法,它可以寫出傳送至瀏覽器之控制項的標記。

====Unload====

這個事件會先發生在每個控制項上,然後才發生在網頁上。在控制項中,這個事件可以用於對特定控制項執行最終清除,例如關閉控制項特定的資料庫連接。

對於網頁本身,這個事件可以用於執行最終清除工作,例如關閉開啟中的檔案或資料庫連接,或是結束登入或其他要求特定的工作。

除了Page中的事件外,其實在HttpModule 中也有許多事件可以攔截利用,但此文章先不細究,其事件觸發的順序跟時機可參考上面的MHPM流程圖。若想在更詳細的了解,可逛逛以下我寫作時參考的網站:

ASP.NET Application and Page Life Cycle

Asp.Net高級知識回顧_HttpHandler

[ASP.NET]Page Life Cycle整理

ASP.NET 網頁存留週期概觀(MSDN)

希望以上分享對各位讀者有所幫助囉~

--

--

No responses yet