asp.net 生命週期

轉載:http://www.techmango.com/blog/default.asp?log_Year=2007&log_Month=6&page=5

介紹
Asp.net是微軟.Net戰略的一個組成部分。它相對以前的Asp有了很大的發展,引入了許多的新機制。本文就Asp.net頁面的生命週期向大家做一個初步的介紹,以期能起到指導大家更好、更靈活地操縱Asp.net的作用。
當一個獲取網頁的請求(可能是通過用戶提交完成的,也可能是通過超鏈接完成的)被髮送到Web服務器後,這個頁面就會接着運行從創建到處理完成的一系列事件。在我們試圖建立Asp.net頁面的時候,這個執行週期是不必去考慮的,那樣只會自討苦吃。然而,如果被正確的操縱,一個頁面的執行週期將是一道有效而且功能強大的工具。許多開發者在編寫Asp.net的頁面以及用戶控件的時候發現,如果知道整個過程中發生了什麼以及在什麼時候發生將對完成整個任務起到很重要的幫助作用。下面我就向大家介紹一下一個Asp.net頁面從創建到處理完成過程中的十個事件。同時,也向大家展示如何在這些事件中添加自己的代碼以達到預定的效果。
一.初始化對象
一個頁面的控件(以及頁面本身)最初應被正確的初始化。通過在你的C#文件的構造函數中聲名所有對象(如圖1),頁面就知道要創建多少對象以及它們的類型。一旦你在你的構造函數中聲名了所有的對象,你就可以通過繼承類、方法、事件或是屬性訪問它們。然而,如果你的一些對象是在Aspx文件中指定的一些控件,那麼這些控件就沒有屬性可言了。同時,通過代碼訪問它們會產生一些意外的錯誤,因爲這些控件實例是沒有一個確定的創建順序的(如果它們是被一起創建的)。還有,你可以通過OnInit來重載初始化事件,圖示如下(圖1):

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"></shapetype><stroke joinstyle="miter"></stroke> <formulas> </formulas> <f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f> <lock v:ext="edit" aspectratio="t"></lock><shape id="_x0000_i1025" style="WIDTH: 415.5pt; HEIGHT: 155.25pt" type="#_x0000_t75"></shape><imagedata src="file:///C:/DOCUME~1/XUXIAN~1/LOCALS~1/Temp/msoclip1/02/clip_image001.png" o:title="Pic1"></imagedata>

圖1

二.導入Viewstate數據
在初始化事件後,所有控件只可以通過它們的ID被引用訪問(因爲還沒有相應的DOM可使用)。在LoadViewState這個事件中,所有的控件將獲得它們的第一個屬性:Viewstate屬性。這個屬性最終將被返回給服務器以判斷這個頁面是已經被用戶訪問完畢還是仍然在被用戶所訪問。Viewstate屬性以“名稱/值”對的字符串方式被保存,它包含了控件的文本以及值等信息。該屬性被存儲在一個隱藏的控件的值屬性裏,在請求頁面時被傳遞。這種方式比起Asp3.0的維持、判斷頁面狀態的方式有了很大的進步啊。還有,你可以重載LoadViewState事件函數來對相應的控件進行值設定。下圖(圖2)是一個例子:

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"></shapetype><stroke joinstyle="miter"></stroke> <formulas> </formulas> <f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f> <lock v:ext="edit" aspectratio="t"></lock><shape id="_x0000_i1025" style="WIDTH: 414.75pt; HEIGHT: 100.5pt" type="#_x0000_t75"></shape><imagedata src="file:///C:/DOCUME~1/XUXIAN~1/LOCALS~1/Temp/msoclip1/02/clip_image001.png" o:title="Pic2"></imagedata>

圖2

三.用LoadPostData處理Postback數據
在頁面創建的這個階段,服務器對頁面上的控件提交的表單數據(在Asp.net中稱postback數據)進行處理。當一個頁面提交一個表單時,框架就在每個提交了數據的控件上執行一個IPostBackDataHandler接口操作。然後頁面執行LoadPostData事件,解析頁面,找到每個執行了IpostBackDataHandler接口操作的控件,並用恰當的postback數據更新這些控件狀態。Asp.net是通過用NameValue集中的“名稱/值”對和每個控件的唯一的ID匹配來實現這一操作的。所以,在Asp.net的頁面上每個控件必須有一個唯一的ID,不可以出現幾個控件共有ID的情況。即使是用戶自定義的一些控件,框架也會賦予它們各自唯一的ID的。在LoadPostData事件後,就要執行下面的RaisePostDataChanged事件了。
四.導入對象
在Load事件中,對象都實例化了。所有的對象第一次被佈置在DOM頁面(在Asp.net中稱控件樹)裏了並且可以通過代碼或是相關的位置被引用。這樣,對象就可以很容易的從客戶端獲得諸如寬度、高度、值、可見性等在Html中的屬性值。在Load事件中,當然還有像設置控件屬性等操作的發生。這個過程是整個生命週期中最重要、最主要的,你可以通過調用OnLoad來重載Load事件,圖示如下(圖3):

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"></shapetype><stroke joinstyle="miter"></stroke> <formulas> </formulas> <f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f> <lock v:ext="edit" aspectratio="t"></lock><shape id="_x0000_i1025" style="WIDTH: 415.5pt; HEIGHT: 186pt" type="#_x0000_t75"></shape><imagedata src="file:///C:/DOCUME~1/XUXIAN~1/LOCALS~1/Temp/msoclip1/02/clip_image001.png" o:title="Pic3"></imagedata>

圖3

五.RaisePostBackChanged事件
就像在上面提到的那樣,這個事件是發生在所有的控件執行了IPostBackDataHandler接口操作並被正確的postback數據更新後的。在這個過程中,每個控件都被賦予一個布爾值來標誌該控件有沒有被更新。然後,Asp.net就在整個頁面上尋找任何已被更新過的控件並執行RaisePostDataChanged事件操作。不過,這個事件是要在所有的控件都被更新了以及Load事件完成後才進行的。這樣就保證了一個控件在被postback數據更新前,別的控件在RaisePostDataChanged事件中是不會被手動改變的。
六.處理客戶端PostBack事件
當由postback數據在服務器端引起的事件都完成後,產生postback數據的對象就執行RaisePostBackEvent事件操作。可是會有這種情況,由於一個控件狀態的改變使得它將表單返回給服務器或是用戶點擊了提交按鈕使得表單返回給服務器。在這種情況下應該有相應的處理代碼來體現事件驅動這一面向對象(OOP)編程原則。由於要滿足呈現給瀏覽器的數據的精確性要求,在一系列postback事件中RaisePostBackEvent事件是最後發生的。
在postback過程中改變的控件不應在執行功能函數被調用後更新。也就是說,任何由於一個預期的事件而改變的數據應該在最終的頁面上被反映出來。你可以通過修改RaisePostBackEvent函數來滿足你的要求,圖示如下(圖4):

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"></shapetype><stroke joinstyle="miter"></stroke> <formulas> </formulas> <f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f> <lock v:ext="edit" aspectratio="t"></lock><shape id="_x0000_i1025" style="WIDTH: 415.5pt; HEIGHT: 147.75pt" type="#_x0000_t75"></shape><imagedata src="file:///C:/DOCUME~1/XUXIAN~1/LOCALS~1/Temp/msoclip1/02/clip_image001.png" o:title="Pic4"></imagedata>

圖4

七.預先呈遞對象
可以改變對象並將改變保存的最後時刻就是這一步――預先呈遞對象。這樣,你可以在這一步對控件的屬性、控件樹結構等作出最後的修改。同時還不用考慮Asp.net對其作出任何改變,因爲此時已經脫離了數據庫調用以及viewstate更新了。在這一步之後,對對象的所有修改將最終被確定,不能被保存到頁面的viewstate中了。你可以通過OnPreRender來重載這一步。
八.保存ViewState
所有對頁面控件的修改完成後viewstate就被保存了。對像的狀態數據還是保留在隱藏的控件裏面,呈現給Html的對象狀態數據也是從這裏取得的。在SaveViewState事件中,其值能被保存到viewstate對象,然而這時在頁面上控件的修改卻不能了。你可以用SaveViewState來重載這一步,圖示如下(圖5):

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"></shapetype><stroke joinstyle="miter"></stroke> <formulas> </formulas> <f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f> <lock v:ext="edit" aspectratio="t"></lock><shape id="_x0000_i1025" style="WIDTH: 415.5pt; HEIGHT: 147.75pt" type="#_x0000_t75"></shape><imagedata src="file:///C:/DOCUME~1/XUXIAN~1/LOCALS~1/Temp/msoclip1/02/clip_image001.png" o:title="Pic5"></imagedata>

圖5

九.呈遞給Html
運用Html創建給瀏覽器輸出的頁面的時候Render事件就發生了。在Render事件過程中,頁面調用其中的對象將它們呈遞給Html。然後,頁面就可以以Html的形式被用戶的瀏覽器訪問了。當Render事件被重載時,開發者可以編寫自定義的Html代碼使得原先生成的Html都無效而按照新的Html來組織頁面。Render方法將一個HtmlTextWriter對象作爲參數並用它將Html在瀏覽器上以網頁的形式顯示。這時仍然可以做一些修改動作,不過它們只是客戶端的一些變化而已了。你可以重載Render事件,圖示如下(圖6):

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"></shapetype><stroke joinstyle="miter"></stroke> <formulas> </formulas> <f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f> <lock v:ext="edit" aspectratio="t"></lock><shape id="_x0000_i1025" style="WIDTH: 415.5pt; HEIGHT: 147.75pt" type="#_x0000_t75"></shape><imagedata src="file:///C:/DOCUME~1/XUXIAN~1/LOCALS~1/Temp/msoclip1/02/clip_image001.png" o:title="Pic6"></imagedata>

圖6

十.銷燬對象
在呈遞給Html完成後,所有的對象都應被銷燬。在Dispose事件中,你應該銷燬所有在建立這個頁面時創建的對象。這時,所有的處理已經完畢,所以銷燬任何剩下的對象都是不會產生錯誤的,包括頁面對象。你可以重載Dispose事件,見圖6。
全文總結
以上就是Asp.net頁面生命週期中的十個事件。每次我們請求一個Asp.net頁面時,我們都經歷着同樣的過程:從初始化對象到銷燬對象。通過了解Asp.net頁面的內部運行機制,我相信大家在編寫、調試代碼的時候會更加遊刃有餘的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章