[ASP.NET]Page Life Cycle整理
前言
一個ASP.NET Webform工程師,一定得知道的東西,就是頁面生命週期的順序,以及在每個事件該放什麼樣的code。
這去面試每一家開發Web系統公司一定要準備的題目啊。
這邊簡單做個整理,如果您還不知道,就趁機把ASP.NET Webform頁面運作的機制瞭解一下。
(如果有錯誤的地方,也請各位前輩指正,因為參考Reference的時候,我遇到了衝突的情況)
介紹
廢話不多說,先來張比較完整的圖:
左邊是頁面生命週期的階段,中間是頁面生命週期的事件,右邊則是寫程式比較少用到,但設計時必須得知道發生時間點的事件。
這邊先附上參考資料:
接著引用一下MSDN上的說明:(點圖可看大圖,或直接到上面參考資料連結)
這邊我們把重點擺在哪些事件該做哪些事,通常就會被最右邊事件所影響。
有一些事件,其實是方便開發者在頁面與控制項交替進行事件時,安插在中間供彈性使用(通常就是拿來覆寫掉某些資訊)。
(by the way,正因為頁面生命週期事件、控制項生命週期事件與code-behind的程式碼耦合性太高,
所以跟ASP.NET MVC相比,彈性略嫌不足,
再加上繼承的特性,耦合性越來越高。
某些開出來供彈性的事件,也只是治標的方式。)
PreInit |
這個事件可以用於下列各項:
如果要求是PostBack,控制項的值尚未從ViewState還原。如果在這個階段設定控制項屬性,則在下一個事件中可能會覆寫其值。 |
Init |
在初始化所有控制項並套用任何面板設定之後引發。這個事件可以用於讀取或初始化控制項屬性。 |
InitComplete | 由 Page 物件引發。這個事件可以用於處理需要完成所有初始設定的工作。 |
PreLoad |
如果需要在 Load 事件之前先處理網頁或控制項,請使用這個物件。
在 Page 引發這個事件之前,會先載入其本身和所有控制項的檢視狀態,再處理 Request 執行個體 (Instance) 所包含的任何回傳資料。(目前中文MSDN的參考上翻譯錯誤) |
Load |
Page 會先呼叫 Page 上的 OnLoad 事件方法,再遞迴地為每個子控制項執行相同動作,它會為其每個子控制項執行相同動作,直到載入完網頁和所有控制項為止。
OnLoad 事件方法可以用於設定控制項中的屬性,以及建立資料庫連接。 通常我會在這邊開始做控制項與資料的繫結。 |
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 事件都會發生在網頁上。這個事件可以用於對網頁或其控制項的內容進行最終的變更。 針對的,仍然是頁面或控制項提供的東西。 |
SaveStateComplete |
網頁和所有控制項的 ViewState 在這個事件發生之前就已儲存了。在這之後對網頁或控制項所做的任何變更都將會被忽略。
這個事件可以用於執行需要儲存檢視狀態但不對控制項做任何變更的工作。
看到沒,MSDN上寫,『在這之後,對網頁或控制項所做的任何變更,都將會被忽略。』 |
Render |
這個不是一個事件;相反地,在這個處理階段,Page 物件會呼叫每個控制項上的這個方法。所有 ASP.NET Web 伺服器控制項都有 Render 方法,它可以寫出傳送至瀏覽器之控制項的標記。 如果您建立自訂控制項,通常會覆寫這個方法,以便輸出控制項的標記。不過,如果自訂控制項只包含標準 ASP.NET Web 伺服器控制項且無任何自訂標記,就不需要覆寫 Render 方法。如需詳細資訊,請參閱 開發自訂的 ASP.NET 伺服器控制項。
使用者控制項 (.ascx 檔案) 自動會包含呈現,因此不需要在程式碼中明確呈現控制項。 這不是一個事件!多神奇的一句話,
沒錯,他只是個固定會在呈現階段,被呼叫的一個方法。 (小的之前把當DropDownList唯讀時,要轉成label,也是用類似的作法,覆寫成其他HTML元素來呈現) |
Unload |
這個事件會先發生在每個控制項上,然後才發生在網頁上。在控制項中,這個事件可以用於對特定控制項執行最終清除,例如關閉控制項特定的資料庫連接。 對於網頁本身,這個事件可以用於執行最終清除工作,例如關閉開啟中的檔案或資料庫連接,或是結束登入或其他要求特定的工作。 |
補充的部分,是參考資料上針對資料繫結控制項的事件,這小的也認為相當重要,
但MSDN已經說明的相當清楚,所以我就貼張MSDN說明的圖,當作補充資料。
結論
沒有瞭解頁面的生命週期、事件的順序,就沒法把對應的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/