[ASP.NET]Page Life Cycle整理

  • 51193
  • 0
  • 2012-03-02

[ASP.NET]Page Life Cycle整理

前言

一個ASP.NET Webform工程師,一定得知道的東西,就是頁面生命週期的順序,以及在每個事件該放什麼樣的code。
這去面試每一家開發Web系統公司一定要準備的題目啊。

這邊簡單做個整理,如果您還不知道,就趁機把ASP.NET Webform頁面運作的機制瞭解一下。
(如果有錯誤的地方,也請各位前輩指正,因為參考Reference的時候,我遇到了衝突的情況)

 

介紹

廢話不多說,先來張比較完整的圖:

PageLifeCycle

左邊是頁面生命週期的階段,中間是頁面生命週期的事件,右邊則是寫程式比較少用到,但設計時必須得知道發生時間點的事件。

這邊先附上參考資料:

接著引用一下MSDN上的說明:(點圖可看大圖,或直接到上面參考資料連結)

stage

這邊我們把重點擺在哪些事件該做哪些事,通常就會被最右邊事件所影響。

有一些事件,其實是方便開發者在頁面與控制項交替進行事件時,安插在中間供彈性使用(通常就是拿來覆寫掉某些資訊)。

(by the way,正因為頁面生命週期事件、控制項生命週期事件與code-behind的程式碼耦合性太高,
所以跟ASP.NET MVC相比,彈性略嫌不足,
再加上繼承的特性,耦合性越來越高。
某些開出來供彈性的事件,也只是治標的方式。)

PreInit

這個事件可以用於下列各項:

  • 檢查 IsPostBack 屬性判斷是否是第一次處理網頁。

  • 建立或重新建立動態控制項。

    • 在這事件動態建立控制項,控制項的生命週期才會完整,尤其是有完整的ViewState相關處理。

  • 動態設定MasterPage。

    • 在這事件以後,因為頁面會自行呼叫套上主題與樣式的動作,之後的頁面事件都不允許再改變套用的MasterPage。

  • 動態設定 Theme 屬性。

    • 同MasterPage的觀念,Skin與Theme相關的屬性,只能在這個事件設定,之後就不允許改變。

  • 讀取或設定設定檔屬性值。

如果要求是PostBack,控制項的值尚未從ViewState還原。如果在這個階段設定控制項屬性,則在下一個事件中可能會覆寫其值。

91的叮嚀:
這個事件,因為尚未LoadViewState,
所以要讀取畫面上最新的值,只能使用Request,
因為Request的建立在頁面『開始』的階段就建立了。

常見的使用情況,例如根據畫面上的下拉選單來決定套用不同的MasterPage或Theme,
此時如果用DroDownList.SelectedValue,則沒法子達到目的。
應該使用Request[DropDownList.UniqueID]。

Init

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

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

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

Page 引發這個事件之,會先載入其本身和所有控制項的檢視狀態,再處理 Request 執行個體 (Instance) 所包含的任何回傳資料。(目前中文MSDN的參考上翻譯錯誤)

91的叮嚀:
從這個事件開始,因為已經把ViewState載入,
所以大部分控制項屬性或資料如果使用ViewState當暫存機制,
這個事件之後就可以比較安心的使用控制項的屬性了。

Load

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

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

91的叮嚀:
這邊有個特性蠻特別的,
就是子控制項Init之後,才會引發Page_Init (容器的Init都會比子控制項Init晚),
但是Load的事件,卻是Page_Load(容器)之後,才會引發子控制項Load。

同樣的道理,也可以印證在UserControl裡,UserControl就是一個容器。

而MasterPage,是繼承UserControl,所以也具備UserControl的特性。
(就知道為啥套用MasterPage後,clientID都會亂掉,因為UserControl的特性就是這樣,所以MasterPage也可以巢狀使用)

通常我會在這邊開始做控制項與資料的繫結。

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

在回傳要求中,如果網頁包含驗證程式控制項,則在執行任何處理之前,請先檢查 Page 和個別驗證控制項的 IsValid 屬性。

91的叮嚀:
通常對client端操作UI來說,這個Control的事件,就代表了User的操作,
而在操作之前,我們都應該檢查畫面上要使用或存入的資料,以避免存入garbage data。
這也是為什麼頁面的『驗證』階段,會擺在Control event的最前面。

通常我也會在Control Event對應的動作處理完後,
呼叫自己寫的重新binding資料的method。
LoadComplete 這個事件可以用於需要載入網頁上所有其他控制項的工作。

91的叮嚀:
通常在Control Event之後,會在這根據新資料對畫面UI的顯示隱藏控制的method。
還有狀態定義改變的method(例如按了新增的按鈕後,新增成功,狀態要變成修改)

也就是根據Control的執行後,要重新整理頁面相關資料,我會寫在這邊。
(寫在Control Event的最後其實也可以,但是這樣就是耦合性變高,
因為是自己去定義動作的先後順序,而非遵循頁面生命週期的順序)
PreRender

在這個事件發生之前:

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

91的叮嚀:
簡單來說,這會是我拿來定義一般頁面程式撰寫,最後的一個event。
還有什麼樣式、要註冊的js、屬性,要在server端改的,這是最後一個事件了。

正因為定位在最後一個事件,所以很常拿來當作覆寫屬性的事件。
講明白點,就是『我不管前面怎麼寫,到這邊就是要這樣做』的情況,就寫在這個事件。

針對的,仍然是頁面或控制項提供的東西。

SaveStateComplete

網頁和所有控制項的 ViewState 在這個事件發生之前就已儲存了。在這之後對網頁或控制項所做的任何變更都將會被忽略。

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

91的叮嚀:

看到沒,MSDN上寫,『在這之後,對網頁或控制項所做的任何變更,都將會被忽略。』
所以,在PreRender的事件,才會被定義為一般使用的最後一個事件。

Render

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

如果您建立自訂控制項,通常會覆寫這個方法,以便輸出控制項的標記。不過,如果自訂控制項只包含標準 ASP.NET Web 伺服器控制項且無任何自訂標記,就不需要覆寫 Render 方法。如需詳細資訊,請參閱 開發自訂的 ASP.NET 伺服器控制項

使用者控制項 (.ascx 檔案) 自動會包含呈現,因此不需要在程式碼中明確呈現控制項。

91的叮嚀:

這不是一個事件!多神奇的一句話,

沒錯,他只是個固定會在呈現階段,被呼叫的一個方法。
目的就是拿來『繪製』頁面或控制項。

為什麼TextBox長的像TextBox,為什麼Button長的像Button,
為什麼GridView最後長出來是Table,
為什麼DropDownList吐出來的原始碼是Select,
都是在這邊進行繪製的動作,也就是把Server端的WebControl相關資訊,繪製成相關的HTML。

(小的之前把當DropDownList唯讀時,要轉成label,也是用類似的作法,覆寫成其他HTML元素來呈現)

Unload

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

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

 

補充的部分,是參考資料上針對資料繫結控制項的事件,這小的也認為相當重要,
但MSDN已經說明的相當清楚,所以我就貼張MSDN說明的圖,當作補充資料。

databind

 

結論

沒有瞭解頁面的生命週期、事件的順序,就沒法把對應的code寫在最對的事件上,
不瞭解頁面生命週期的工程師,寫出來的code,一樣會動,
但是寫出來的code,不一定對。

只要遇到需求變更,bug就會一一浮現出來。

這也是為什麼,這麼多面試ASP.NET工程師的場合,都會問這問題的原因。

因為一次就可以篩選出,真正有用心去瞭解ASP.NET頁面運作原理的工程師。
而不是講了一嘴自己寫了幾年ASP.NET程式,寫過幾個大系統,連這都不知道的工程師。

[註]2010/01/20補充:http://blogs.msdn.com/aspnetue/archive/2010/01/14/asp-net-page-life-cycle-diagram.aspx

[註]2010/03/28補充:Page Lifecycle Events- Video

[註]2012/03/02補充:Understanding ASP.NET View State,雖然主要是講ViewState,卻和page life cycle息息相關。

 


blog 與課程更新內容,請前往新站位置:http://tdd.best/