[關於ASP.NET的23事] Lesson 1 瞭解ASP.NET的生命週期 (Understanding ASP.NET Life Cycle)

[關於ASP.NET的23事]Lesson 1瞭解ASP.NET的生命週期

瞭解Asp.Net的網頁生命週期與控件生命週期有助於開發Asp.Net的網頁程式

以下作為資料的整理,方便隨時可以查閱(未來會大約整理23個主題,都跟ASP.NET有關)

 

image

根據上圖,當一個Web網頁被請求的時候,伺服器就會建立了與Page相關的物件(以ASP.NET來說,就是一個稱為Page的物件)以及所有的控件物件,包含控件中的子控件。

透過這些物件來產生Page頁面並傳回瀏覽器。當最終的階段(第8階段)結束以後,網頁伺服器就會消滅這些物件,並將資源釋放以接受其他的請求。

也正因為這樣網頁開發者就無法維持了這些物件的資料(這些資料被稱為State),因此ASP.NET又使用了稱為ViewState的機制來解決這個問題。(階段4、7)

 

ViewState是ASP.NET被用來儲存特定使用者的在頁面請求與回應所產生的資料,這些資料通常與Server Control有關,這些資料並不會被WebServer儲存。

而是在階段7被寫到Page物件中(Rendering),並送回給使用者。當Page再度被請求的時候,就會從階段4中,將資料從頁面中讀出來,並設定回Page與控件的物件中(Load)

因此WebServer不再儲存使用者的資料,這樣的機制讓WebServer擁有更多的資源來處理更多的請求。

 

為了因應Asp.NET的生命週期,我們必須要去瞭解頁面每個階段所代表的意義。因為未來我們很有可能在其中進行程式的開發。

在各個階段Page物件與控件都有可對應的事件可以去處理。因此我們具備足夠的彈性在生命週期的期間去撰寫我們的程式碼。

最常見的例子例如當使用者初次請求網頁的時候,我們可能要去初始化資料以及控件,因此我們都會在Page_Load中來判斷使用者是否為第一次請求網頁或是PostBack(透過IsPostBack)。

 

以下列出Page物件完整的生命週期事件,有助於在不同的階段適當地處理與撰寫我們的程式碼:

PreInit事件:第一個你可以透過Code來處理Page的事件,例如,可以透過程式動態地針對MasterPage以及Theme進行初始化。
另外在這個階段也非常適合用於動態產生控件。

Init事件:每個控件都被初始化以後,就會觸發這個事件,我們可以透過這個事件來改變控件的初始化後的值。

InitComplete事件:當所有的Page物件以及控件物件都被初始化後,就會觸發這個事件囉。

PreLoad事件:當ViewState被載入並設置到Page跟控件之前(上圖的階段4以前)就會被觸發。
這個事件適合撰寫當控件初始化以後,但是尚未載入ViewState到控件中的程式。

Load事件:Page物件十分穩定了,因為初始化以及ViewState(控件的狀態)已經被重建。
通常在Load事件中,我們都會去檢查是否為PostBack,並設置適當的屬性到控件中。
Load事件是由Page的率先執行,再執行其下的控件的Load事件(每個控件的Load執行完後,若控件還有子代控件,則執行子代控件的Load)。

Control Event的事件:這個事件是PostBack後才會執行。
例如我們都會設置一個按鈕的Click事件、一個DropDownList的SelectIndexChanged的事件。

LoadComplete事件:當所有的控件都已經Load完以後,就會執行這個事件。

PreRender事件:允許最終對Page物件以及控件物件進行改變。
而且這個事件發生在所有正常的PostBack Event事件被執行完,然後在儲存ViewState之前被觸發。
所有的改變(包含對控件的改變,都會在這個事件後被儲存)

SaveStateComplete事件:這個階段若對控件進行改變的話,都會被捨棄。
若當ViewState被儲存後,還有想要處理的程式,則可以撰寫於此。

Render事件:ASP.NET在這個事件的階段會呼叫所有的Page物件中的控件,並要它們執行他們自己的Render事件,將控件輸出到頁面上。
Render已經是屬於產生Client端的程式碼了(HTML、JavaScript)。因此我們可以在這個階段撰寫一些我們的自訂控件的需求。

UnLoad事件:這個事件可以用來釋放所有的資源(包含生命週期中CLR所產生的所有物件實例都會被釋放),我們也可以撰寫程式來釋放資源。

 

回想Page物件其實也是繼承Control這個最原始的祖先,所以包含所有繼承Control的Server Control,其實也都是系出同源。

因此控件的生命週期其實與Page物件一致,每個控件都會被完整的執行到init、load、render以及unload等事件。

因此當一個Page執行到Load事件以後,它會等待所有的子控件以及子控件的子控件執行完Load事件。

 

這樣的同步特性要注意:當我們動態新增了控件以後,這個動態被新增的控件的事件就會依續的被執行,直到他們的Container現階段的事件中。

例:

image

上圖中,我們可以看到動態加入的TextBox是在Load被加入的,因此TextBox會執行執到Load事件,再返回給Container的Load事件。

 

 

 

MSDN的資料來源:http://msdn.microsoft.com/zh-tw/library/ms178472(v=vs.80).aspx

書籍的資料來源:MCTS for ASP.NET