詳解ASP.NET加載ViewState
大家都知道,在ASP.NET上進(jìn)行Web編程中了解頁(yè)面中各事件的執(zhí)行順序是非常有用的,可以有的放矢的將自己的一些處理程序放到指定的位置,以便取得正確的結(jié)果。
初始化
當(dāng)頁(yè)面被提交請(qǐng)求第一個(gè)方法永遠(yuǎn)是構(gòu)造函數(shù)。您可以在構(gòu)造函數(shù)里面初始一些自定義屬性或?qū)ο螅贿^這時(shí)候因?yàn)轫?yè)面還沒有被完全初始化所以多少會(huì)有些限制。特別地,您需要使用HttpContext對(duì)象。當(dāng)前可以使用的對(duì)象包括QueryString, Form以及Cookies集合,還有Cache對(duì)象。注意:在構(gòu)造函數(shù)里是不允許使用Session的。
下一個(gè)將執(zhí)行的方法是AddParsedSubObject方法,這個(gè)方法將添加所有獨(dú)立的控件并把頁(yè)面組成一個(gè)控件集合樹,這個(gè)方法經(jīng)常被一些高級(jí)的頁(yè)面模板解決方案(Page Template Solutions)重寫以便添加頁(yè)面內(nèi)容到頁(yè)面模板(Page Template)中一些特殊的控件中。這個(gè)方法遞歸應(yīng)用到所有的頁(yè)面控件及相應(yīng)的的每個(gè)子控件,所有的控件都是在這個(gè)方法中開始最早的初始化。
頁(yè)面類中下一個(gè)將執(zhí)行的方法是DeterminePostBackMode。這個(gè)方法允許您修改IsPostBack的值及相關(guān)的事件。如果您需要從數(shù)據(jù)庫(kù)中加載ViewState這個(gè)方法將特別有用,因?yàn)閂iewState只有在IsPostBack為真的情況下才會(huì)進(jìn)行恢復(fù)。返回空將會(huì)導(dǎo)致強(qiáng)制執(zhí)行非回傳,返回Request.Form則強(qiáng)制執(zhí)行一個(gè)回傳。除非在特殊情況下,否則并不建議去操作這個(gè),因?yàn)檫@個(gè)還會(huì)影響其他的事件。
下一個(gè)將要執(zhí)行的方法是OnInit方法,一般這是第一個(gè)真正被使用的方法。這個(gè)方法觸發(fā)時(shí),所有頁(yè)面定義中的控件執(zhí)行初始化,這意味著所有在頁(yè)面中定義的值應(yīng)用到相應(yīng)的控件上。不過,ViewState和傳回的值還不會(huì)應(yīng)用到控件上,因此,任何被代碼或用戶改變的值還沒有被恢復(fù)到控件上。這個(gè)方法通常是最好的創(chuàng)建、重創(chuàng)建動(dòng)態(tài)控件的好地方。
恢復(fù)及加載
下一個(gè)方法, LoadPageStateFromPersistenceMedium只會(huì)在頁(yè)面被回傳的時(shí)候才會(huì)被執(zhí)行。如果因?yàn)槭褂肧ession或自定義存儲(chǔ)方式,您修改了后面將要提到的影響ViewState保存方式的方法SavePageStateToPersistenceMedium,則這個(gè)方法需要被重寫。默認(rèn)的實(shí)現(xiàn)中ViewState是一種Base64格式編碼,并且被保存在頁(yè)面的隱藏域中,您可以使用這篇文章中提及的方法修改ViewState 按以上兩種方式保存。注意:這個(gè)方法并沒有真正加載ViewState到頁(yè)面或頁(yè)面控件中。
當(dāng)?shù)玫絍iewState后,下一個(gè)方法LoadViewSate,將以遞歸的方式恢復(fù)ViewState到頁(yè)面及各個(gè)頁(yè)面控件或子控件中。這個(gè)方法執(zhí)行后,每個(gè)控件都將恢復(fù)到上一次的狀態(tài),但是用戶提交的數(shù)據(jù)還沒有應(yīng)用到控件上,因?yàn)樗麄儾皇荲iewState的一部分。這個(gè)方法主要用于恢復(fù)您在其他事件中動(dòng)態(tài)生成的控件的值,他們的值是您手動(dòng)保存在ViewSate中,并且現(xiàn)在已經(jīng)失效。
下一個(gè)方法是ProcessPostData,這個(gè)方法也同樣是回傳的時(shí)候才會(huì)被執(zhí)行,并且不允許被重寫,這個(gè)是頁(yè)面基類的私有方法。這個(gè)方法通過匹配控件的名稱恢復(fù)相應(yīng)的用戶提交的控件的值,到這一步意味著整個(gè)頁(yè)面都已經(jīng)被完全恢復(fù)了。唯一要記住的是所有動(dòng)態(tài)控件的創(chuàng)建必須在這個(gè)方法之前。這個(gè)方法也是記錄后面的改變事件的方法。
下一個(gè)方法是OnLoad方法,通常這是用得最多的方法,因?yàn)檫@個(gè)方法是頁(yè)面生存期第一個(gè)恢復(fù)了所有值的地方。大多數(shù)代碼根據(jù)判斷 IsPostBack來決定是否重新設(shè)置控件狀態(tài)。您也可以在這個(gè)方法中調(diào)用Validate并且檢查IsValid的值。也可以在這個(gè)方法中創(chuàng)建動(dòng)態(tài)控件,并且該控件的所有的方法都會(huì)被執(zhí)行以追上當(dāng)前頁(yè)面的狀態(tài)包括ViewSate,不過不包括回傳的值。
事件處理
下一個(gè)方法還是 ProcessPostData,實(shí)際上就是前一個(gè)方法的另一次調(diào)用,它仍然是只在回傳的時(shí)候執(zhí)行并且由于是私有方法不可以被重寫。如果您是第一次看頁(yè)面的運(yùn)行軌跡也許會(huì)覺得這個(gè)方法有些多余。但實(shí)際上這個(gè)方法是必要的因?yàn)樵贠nLoad中創(chuàng)建的動(dòng)態(tài)控件也需要他們回傳的值。任何在這以后創(chuàng)建的控件將可以得到他們的ViewState,但是不能再得到他們的回傳的值,并且不會(huì)觸發(fā)任何值改變事件(Change Event)。
下一個(gè)方法,RaiseChangedEvents,也是只在回傳頁(yè)面中執(zhí)行,并且也因?yàn)槭腔惖乃接蟹椒ㄋ胁荒鼙焕^承。在整個(gè)頁(yè)面生存期中,是在這兒根據(jù)之前的ProcessPostData記錄的控件的值和提交的值是否不同來觸發(fā)值改變事件。您也許需要調(diào)用Validate或者檢查 IsValid的值。這里并沒有特別的說明多個(gè)值改變事件的執(zhí)行先后順序。
下一個(gè)方法,RaisePostBackEvent,同樣是因?yàn)槭腔惖乃接蟹椒ú荒鼙焕^承,同樣也是只在回傳頁(yè)面中執(zhí)行。除非使用了 AutoPostBack,不然這是實(shí)際提交表單事件執(zhí)行的地方,特別是按鈕或者其實(shí)使用Javascript提交表單等。如果還沒有被手動(dòng)調(diào)用過并且使用了驗(yàn)證控件,那么Validate會(huì)被調(diào)用。注意IE中有個(gè)BUG有時(shí)會(huì)允許提交但卻不觸發(fā)任何事件。
下一個(gè)方法是OnPreRender,一般這是在客戶端展現(xiàn)頁(yè)面之前改變頁(yè)面及其控件的最后一次機(jī)會(huì)。您也可以在這個(gè)方法里面創(chuàng)建動(dòng)態(tài)控件,并且所有的方法都會(huì)被執(zhí)行以追上當(dāng)前頁(yè)面的狀態(tài)包括ViewSate,但是私有方法將不會(huì)被執(zhí)行,這意味著不會(huì)有回傳的值并且不會(huì)有事件觸發(fā)。由于IE中的 BUG,這是一個(gè)沒有事件趕上PostBack的好地方。
保存及顯示
下一個(gè)方法是SaveViewState,不論是否是回傳頁(yè)面,均會(huì)遞歸的執(zhí)行以保存頁(yè)面及其所有控件的ViewState。ViewState基本上保存所有與定義在aspx中的原始值不同的值,不管是被代碼還是用戶所改變。注意控件值是根據(jù)他們?cè)陧?yè)面的控件樹中的位置來保存的,所以如果動(dòng)態(tài)控件后來加到了錯(cuò)誤的位置將會(huì)導(dǎo)致混亂。
下一個(gè)方法是SavePageStateToPersistenceMedium真正的保存頁(yè)面的ViewSate。這個(gè)方法隨同 LoadPageStateFromPersistenceMediumg 一起被重寫以便保存ViewState到Session或其它自定義數(shù)據(jù),而不是用隱藏域。這對(duì)于低帶寬的用戶來說是很有幫助的。并且對(duì)于移動(dòng)設(shè)備來說, Session是默認(rèn)設(shè)置。下面這篇文章描述了使用以上兩種方式保存ViewState的具體細(xì)節(jié)。注意在ASP.NET中有個(gè)Bug:ASP.NET要求必須提交__viewstate字段,即使是空的。
下一個(gè)方法是Render方法,該方法遞歸的創(chuàng)建并發(fā)送相應(yīng)控件的html給瀏覽器。這個(gè)方法被一些頁(yè)面模板方案重寫以添加一些通用的頁(yè)面頭與腳而不使用服務(wù)器控件,他們總是有一些額外的東西。注意這兒的修改只能使用純HTML,因?yàn)榭丶谶@兒已經(jīng)被生成了。您可以用 StringBuilder,StringWriter,HtmlTextWriter捕獲相應(yīng)的HTML輸出。
最后的方法是OnUnload,這個(gè)方法會(huì)調(diào)用相應(yīng)的Dispose方法。這個(gè)方法提供機(jī)會(huì)以便清空該頁(yè)面中使用的非托管資源,如關(guān)閉打開的文件句柄,以前打開的數(shù)據(jù)庫(kù)連接等。注意這個(gè)方法是在頁(yè)面已經(jīng)發(fā)送到客戶端以后執(zhí)行的,所以它只有影響服務(wù)器對(duì)象,并且它不會(huì)顯示在頁(yè)面的顯示軌跡中。這就是頁(yè)面的生存期,對(duì)于每一次請(qǐng)求都是這么運(yùn)行的。
- ConstructorAlwaysAll
- AddParsedSubObjectAlwaysAll
- DeterminePostBackModeAlwaysPage
- OnInitAlwaysAll
- LoadPageStateFromPersistenceMediumPostBackPage
- LoadViewStatePostBackAll
- ProcessPostData1PostBackPage
- OnLoadAlwaysAll
- ProcessPostData2PostBackPage
- RaiseChangedEventsPostBackPage
- RaisePostBackEventPostBackPage
- OnPreRenderAlwaysAll
- SaveViewStateAlwaysAll
- SavePageStateToPersistenceMediumAlwaysPage
- RenderAlwaysAll
- OnUnloadAlwaysAll
以上介紹ASP.NET加載ViewState
【編輯推薦】