ViewState机制由浅入深1
1???????? ViewState機(jī)制是什么?
ViewState機(jī)制是asp.net中對(duì)同一個(gè)Page的多次請(qǐng)求(PostBack)之間維持Page及控件狀態(tài)的一種機(jī)制。在WebForm中每次請(qǐng)求完,Page對(duì)象都會(huì)被釋放,對(duì)同一個(gè)Page的多次請(qǐng)求之間的狀態(tài)信息,如何進(jìn)行維護(hù)呢?WebForm中,每次請(qǐng)求都會(huì)存在客戶端和服務(wù)器之間的一個(gè)交互。如果請(qǐng)求完成之后將一些信息傳回到客戶端,下次請(qǐng)求的時(shí)候客戶端再將這些狀態(tài)信息提交給服務(wù)器,服務(wù)器端對(duì)這些信息使用和處理,再將這些信息傳回給客戶端。這樣是不是就可以對(duì)同一個(gè)Page的多次請(qǐng)求(PostBack)之間維持狀態(tài)了。對(duì)這就是ViewState的基本工作模式。ViewState的設(shè)計(jì)目的主要就是為了將必要的信息持久化在頁(yè)面中。這樣通過(guò)ViewState在頁(yè)面回傳的過(guò)程中保存狀態(tài)值,使原本沒(méi)有“記憶”的Http協(xié)議變得有“記憶”起來(lái)。
2???????? ViewState機(jī)制如何工作?
下面我們看看ViewState機(jī)制是如何具體的工作的。
2.1?客戶端:
我們先從客戶端看起,在客戶端的HTML源代碼中我們可以看到下面的代碼
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
value="/wEPDwULLTE0MTAzNDUwNThkZKr77J2uy7fatyBou8PocG80X4Jt" />
這個(gè)就是ViewState在客戶端的保存形式,它保存在一個(gè)ID為_(kāi)_VIEWSTATE的Hidden中,它的Value是使用Base64編碼后的字符串。這個(gè)字符串實(shí)際上是一個(gè)對(duì)象(Pair類型)序列化之后的結(jié)果。這個(gè)對(duì)象保存了整個(gè)頁(yè)面的控件樹(shù)的ViewState。可以使用一些工具將這個(gè)字符串進(jìn)行解碼查看其內(nèi)容,比如ViewStateDecoder,ViewStateAnalyzer。
2.2?服務(wù)器端:
在服務(wù)器端和ViewState機(jī)制密切相關(guān)的有三個(gè)類Page,Control,StateBag。他們3者的關(guān)系如下圖所示:
圖1
Page繼承自Control,Control和StateBag是聚合關(guān)系,在Control中有一個(gè)StateBag的實(shí)例ViewState。這三個(gè)類互相協(xié)作完成ViewState機(jī)制的大概過(guò)程如下。Page對(duì)客戶端請(qǐng)求進(jìn)行處理,在處理的過(guò)程中先是將客戶端提交的_VIEWSTATE反序列化為對(duì)象,調(diào)用Control的相關(guān)方法給所有的控件裝載數(shù)據(jù),這些數(shù)據(jù)是上次請(qǐng)求結(jié)束后控件的狀態(tài)數(shù)據(jù)。在之后的一些事件中這些狀態(tài)數(shù)據(jù)可能被修改。在請(qǐng)求結(jié)束之前調(diào)用Control的相關(guān)方法得到所有控件的被修改過(guò)的狀態(tài)數(shù)據(jù),之后Page將其進(jìn)行序列化,并返回給客戶端。在Control中又具體調(diào)用StateBag類的方法完成狀態(tài)數(shù)據(jù)的加載和保存。
2.2.1?? Page中的處理
圖2 Page生命周期
1)???? InitRecursive
在Page的生命周期中有3處與ViewState相關(guān),在初始化階段調(diào)用Control. InitRecursive,它遞歸對(duì)所有的控件進(jìn)行初始化,其中調(diào)用了Control.TrackViewState。TrackViewState中打開(kāi)跟蹤ViewState開(kāi)關(guān)。
2)???? LoadAllState
在初始化完成之后會(huì)調(diào)用Page.LoadAllState,LoadAllState只有在PostBack的時(shí)候才會(huì)執(zhí)行,它的主要功能是將從頁(yè)面?zhèn)鬟f來(lái)的__VIEWSTATE的值反序列化為Pair類型的對(duì)象,然后將這個(gè)對(duì)象中存儲(chǔ)的ViewState的值加載到Page及所有控件中。實(shí)際上LoadAllState加載了ControlState(控件狀態(tài))及ViewState(視圖狀態(tài)),本文主要是討論ViewState,對(duì)ControlState部分的處理不進(jìn)行描述。
LoadAllState中主要有兩步:Page.LoadPageStateFromPersistenceMedium和Control.LoadViewStateRecursive。
在LoadPageStateFromPersistenceMedium中發(fā)生了如下的調(diào)用層次
Page.LoadPageStateFromPersistenceMedium
è??? HiddenFieldPageStatePersister.Load
è??? ObjectStateFormatter.Deserialize
以上完成的功能是將客戶端提交的_VIEWSTATE反序列化為一個(gè)類型為Pair的對(duì)象pair。
Control.LoadViewStateRecursive中將遞歸加載控件的ViewState,具體在下面進(jìn)行講解。
3)???? SaveAllState
SaveAllState它的操作和LoadAllState相反。SaveAllState中主要有兩步Control.SaveViewStateRecursive及Page SavePageStateToPersistenceMedium。
Control.SaveViewStateRecursive中將所有控件的ViewState屬性遞歸加載到一個(gè)Pair對(duì)象中,具體實(shí)現(xiàn)細(xì)節(jié)在下面講解。
Page SavePageStateToPersistenceMedium中發(fā)生如下的調(diào)用關(guān)系。
Page SavePageStateToPersistenceMedium
è??? HiddenFieldPageStatePersister.Save
è??? ObjectStateFormatter.Serialize
將Control.SaveViewStateRecursive生成的對(duì)象序列化為一個(gè)字符串,并賦值給Page.ClientState屬性。
在Render階段發(fā)生如下的調(diào)用關(guān)系:
HtmlForm.RenderChildren
è??? Page.BeginFormRender
è??? Page.RenderViewStateFields
最終將ClientState屬性中的值寫入到HTML頁(yè)面的_VIEWSTATE中。
在Control.InitRecursive中打開(kāi)跟蹤開(kāi)關(guān),打算對(duì)ViewState的值進(jìn)行跟蹤,在Page.LoadAllState中將客戶端提交的__VIEWSTATE的值裝載到各個(gè)控件的ViewState中,在Page.SaveAllState中將發(fā)生變化的ViewState序列化為一個(gè)字符串,在Render階段發(fā)送回客戶端。
4)???? ViewState序列化與反序列化
PageStatePersister 是一個(gè)抽象類,是表示將ViewState信息序列化及反序列化機(jī)制的基類。在Page.LoadPageStateFromPersistenceMedium中示意代碼如下:
protected internal virtual object LoadPageStateFromPersistenceMedium()
{
????????? PageStatePersister pageStatePersister = this.PageStatePersister;
????????? pageStatePersister.Load();
????????? return new Pair(pageStatePersister.ControlState, pageStatePersister.ViewState);
}
在Page.SavePageStateToPersistenceMedium中的示意代碼如下:
protected internal virtual void SavePageStateToPersistenceMedium(object state)
{
??? ??? PageStatePersister pageStatePersister = this.PageStatePersister;
??????? Pair pair = (Pair) state;
??????? pageStatePersister.ControlState = pair.First;
??????? pageStatePersister.ViewState = pair.Second;
??????? pageStatePersister.Save();
}
在Asp.net2.0中實(shí)現(xiàn)PageStatePersister這個(gè)抽象類,具體提供持久化機(jī)制的類是HiddenFieldPageStatePersister。它實(shí)現(xiàn)了Load和Save兩個(gè)方法,Load時(shí)將__VIEWSTATE反序列化為一個(gè)Pair對(duì)象,Save時(shí)將Pair對(duì)象序列化為一個(gè)字符串賦值給Page.ClientState。HiddenFieldPageStatePersister中采用的格式器是ObjectStateFormatter,其實(shí)現(xiàn)string Serialize(object state),和object Deserialize(string serializedState)這兩個(gè)方法,從而實(shí)現(xiàn)對(duì)Pair對(duì)象的序列化和反序列化。
public string Serialize(object state)中的示意代碼如下:
MemoryStream memoryStream = GetMemoryStream();
Serialize(memoryStream, state);
byte[] buf = memoryStream.GetBuffer();
if (RequiresViewStateEncryptionInternal)
{
?buf = MachineKeySection.EncryptOrDecryptData(true, buf, this.GetMacKeyModifier(), 0, length);
?length = buf.Length;
}
else if (EnableViewStateMac)
{
buf = MachineKeySection.GetEncodedData(buf, this.GetMacKeyModifier(), 0, ref length);
}
return Convert.ToBase64String(buf, 0, length);
將state序列化為內(nèi)存流,在將其轉(zhuǎn)換為字節(jié)流。如果需要加密則對(duì)其進(jìn)行加密處理,否則需要Mac則進(jìn)行Mac處理。最后將字節(jié)流進(jìn)行Base64編碼轉(zhuǎn)換為字符串。
public object Deserialize(string serializedState) 中的示意代碼如下:
byte[] buf = Convert.FromBase64String(serializedState);
int length = buf.Length;
if (ContainsEncryptedViewState)
{
buf = MachineKeySection.EncryptOrDecryptData(false, buf, this.GetMacKeyModifier(), 0, length);
?length = buf.Length;
}
else if (EnableViewStateMac)
{
buf = MachineKeySection.GetDecodedData(buf, this.GetMacKeyModifier(), 0, length, ref length);
}
MemoryStream memoryStream = GetMemoryStream();
memoryStream.Write(buf, 0, length);
return this.Deserialize(memoryStream);
將字符串進(jìn)行Base64解碼為字節(jié)流,如果需要解密則進(jìn)行解密處理,否則需要進(jìn)行需要Mac則進(jìn)行Mac處理,將字節(jié)流轉(zhuǎn)換為內(nèi)存流,進(jìn)行反序列化返回Pair對(duì)象。
轉(zhuǎn)載于:https://www.cnblogs.com/hobe/archive/2008/03/25/1122203.html
總結(jié)
以上是生活随笔為你收集整理的ViewState机制由浅入深1的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Kafka SCRAM和PLAIN实战
- 下一篇: Sql server时间转时间long