ASP.NET中的ViewState本質(zhì)
大家都聽(tīng)說(shuō)過(guò)也用過(guò)ASP.NET中的ViewState本質(zhì),到底ViewState本質(zhì)上到底是什么東西?為什么ASP.NET中沒(méi)有他不行?下面就來(lái)談?wù)劇?。?/P>
我們一般在開(kāi)發(fā)面向?qū)ο蟪绦虻臅r(shí)候,我們都是用對(duì)象保存數(shù)據(jù)的,比如用對(duì)象的屬性,字段來(lái)保存對(duì)象的狀態(tài)。當(dāng)調(diào)用對(duì)象的方法時(shí),就可以改變對(duì)象的狀態(tài)。釋放對(duì)象后,對(duì)象的狀態(tài)就消失。這點(diǎn)大家都熟悉。在開(kāi)發(fā)桌面程序的時(shí)候,沒(méi)有什么問(wèn)題,因?yàn)閷?duì)象都一般在本地的內(nèi)存中,直到不再用那個(gè)對(duì)象,我們就銷(xiāo)毀它。
但是在Web程序中,問(wèn)題就大了,比如我們請(qǐng)求一個(gè)頁(yè)面的時(shí)候,我們希望把上一個(gè)頁(yè)面的狀態(tài)保存下來(lái),因?yàn)橄乱粋€(gè)頁(yè)面要用到上一個(gè)頁(yè)面的狀態(tài),常見(jiàn)的例子就是填寫(xiě)用戶(hù)信息時(shí),我們要把這次的信息和上一個(gè)頁(yè)面中的信息的比較,如果信息不同,就進(jìn)行一定的操作,等等。但是一旦頁(yè)面交給服務(wù)器后,上次的頁(yè)面的狀態(tài)信息就丟失了(HTTP協(xié)議是無(wú)狀態(tài)的)。
所以ASP.NET視圖機(jī)制就可以在請(qǐng)求結(jié)束時(shí)保存對(duì)象的狀態(tài),同時(shí)在下一個(gè)對(duì)象請(qǐng)求開(kāi)始時(shí)加載之前的狀態(tài),下一個(gè)請(qǐng)求按照下面的步驟來(lái)加載狀態(tài):
1.創(chuàng)建一個(gè)與上一個(gè)請(qǐng)求結(jié)束時(shí)所注銷(xiāo)對(duì)象相同類(lèi)型的新對(duì)象。比如,我們第一次請(qǐng)求的是Default.aspx頁(yè)面,在服務(wù)器端,ASP.NET運(yùn)行時(shí)就會(huì)編譯Default.aspx頁(yè)面,經(jīng)過(guò)一系列的動(dòng)作之后,在服務(wù)器端就有一個(gè)Default_aspx類(lèi)的實(shí)例,然后再經(jīng)過(guò)一系列的動(dòng)作之后,就把我們請(qǐng)求的Default.aspx頁(yè)面的數(shù)據(jù)最后以html的形式發(fā)送了到我們的瀏覽器中。
此時(shí)服務(wù)器的Default_aspx的實(shí)例就銷(xiāo)毀了,對(duì)象就沒(méi)有了。當(dāng)我們?cè)贋g覽器中填寫(xiě)了相關(guān)的信息后,再次請(qǐng)求提交Default.aspx頁(yè)面時(shí),服務(wù)器又會(huì)重新編譯Default.aspx 頁(yè)面,在然后經(jīng)過(guò)一系列的動(dòng)作后處理我們的數(shù)據(jù)。再次把處理的結(jié)果發(fā)送給我們,然后Default_Aspx實(shí)例再次銷(xiāo)毀了。
假如我們第三次還是請(qǐng)求的Default.aspx頁(yè)面,我們把數(shù)據(jù)再次提交,然而這次Default__aspx的實(shí)例就只是處理我們這次提交的數(shù)據(jù),不會(huì)管我們之前提交的數(shù)據(jù)。說(shuō)的更加的通俗就是,我們第二次提交的數(shù)據(jù)是A,我們第三次提交的數(shù)據(jù)是B,而且我們本次希望頁(yè)面把A和B數(shù)據(jù)比較之后再發(fā)送 C數(shù)據(jù)給我們的,但是本次的處理頁(yè)面只是直到本次的提交的數(shù)據(jù),即B。所以我們永遠(yuǎn)得不到C的結(jié)果。
2.為新建的對(duì)象加載舊對(duì)象的狀態(tài)。
只有這樣我們才可以得到我們想要的數(shù)據(jù)C。我們來(lái)進(jìn)一步看看內(nèi)部機(jī)制。在每個(gè)請(qǐng)求結(jié)束時(shí)(簡(jiǎn)單的就可以認(rèn)為在服務(wù)器把數(shù)據(jù)發(fā)送給我們之前,此時(shí)數(shù)據(jù)還在服務(wù)器),就會(huì)引發(fā)一些事件,調(diào)用一些方法:
◆頁(yè)面自動(dòng)調(diào)用Controls集合中控件的SaveViewState方法,也就是迭代頁(yè)面中所有控件,調(diào)用他們的SaveViewState方法,因?yàn)榭丶际荂ontrol的子類(lèi),而Control類(lèi)中有這個(gè)方法。
◆每個(gè)控件的SaveViewState方法把控件的狀態(tài)存儲(chǔ)到一個(gè)對(duì)象中。
◆頁(yè)面獲取每個(gè)控件的返回的那個(gè)保存狀態(tài)的對(duì)象,然后用與對(duì)象有關(guān)的轉(zhuǎn)換器把保存的狀態(tài)的對(duì)象轉(zhuǎn)換為字符串,然后把這些字符串表達(dá)式組合起來(lái)保存在一個(gè)隱藏字段中,隱藏字段名為:_VIEWSTATE.如下:
- <input type=”hidden” name=”__VIEWSTATE” id=”__VIEWSTATE” value=”/wEPDwULLTE3MDU5MjY
- 4MTkPZBYCAgMPZBYCAgEPFCsAAmRkFgZmD2QWAmYPDxYCHgRUZXh0BQ5QYXltZW50IE1ldGhvZGRkAgEPZB
- YCZg8PDxYCHgtfIURhdGFCb3VuZGdkZGQCBw9kFgRmDw8PFgIfAWdkZGQCAg8PDxYCHwFnZGRkZJDAqbyjC
- j4rjagRWSiVYTp7nQfM” />
◆然后_VIEWSTATE隱藏字段就發(fā)送到了客戶(hù)端,和頁(yè)面數(shù)據(jù)一起。
◆當(dāng)頁(yè)面回傳到服務(wù)器,就發(fā)生下面的操作:
頁(yè)面字符串從_VIEWSTATE中得到字符串表達(dá)式。
頁(yè)面礦建解析字符串表達(dá)式
頁(yè)面框架使用與對(duì)象相關(guān)的類(lèi)型轉(zhuǎn)換器,根據(jù)字符串表達(dá)式重新創(chuàng)建狀態(tài)對(duì)象。
頁(yè)面框架調(diào)用Controls集合中每個(gè)對(duì)象的LoadViewState方法加載之前的狀態(tài)
然后進(jìn)行其他的處理。
就這樣,ASP.NET就在請(qǐng)求之間保存了狀態(tài)。
總結(jié):以上就是ViewState本質(zhì)介紹,大家可以這么認(rèn)為:服務(wù)器端把頁(yè)面中對(duì)象的狀態(tài)序列化到客戶(hù)端,然后下面再反序列化得到之前的狀態(tài)。
【編輯推薦】