同桌上课用手指进去了好爽_欧美丰满熟妇xxⅹⅹ性大i_成人av天天日天天拍拍_猛男gay帅男gay男男同志_欧美va天堂在线观看_人妻无码av中文系列三里桃花_亚欧免费无码在线观看_久久久精品国产亚洲av水_日韩在线免费看污污污_2021无码专区人妻系列日韩

首頁(yè) 優(yōu)化推廣 ASP.Net ViewState怎么實(shí)現(xiàn)

ASP.Net ViewState怎么實(shí)現(xiàn)

來(lái)源: | 時(shí)間:2013/1/5 22:23:32 |

ViewState是.Net中提出的狀態(tài)保存的一種新途徑(實(shí)際上也是老瓶裝新酒);我們知道,傳統(tǒng)的Web程序保存狀態(tài)的方式有這樣幾種:
1、Application 這是Web應(yīng)用程序生命期中的全局保存區(qū),保存在Application中的數(shù)據(jù)是全局有效的;在Asp.Net中,有一個(gè)應(yīng)用程序池,其中保存了數(shù)個(gè)(或數(shù)十個(gè))應(yīng)用程序?qū)嵗?,每一次?qǐng)求都會(huì)從池中取一個(gè)實(shí)例來(lái)處理請(qǐng)求,在請(qǐng)求完畢之前,這個(gè)實(shí)例不會(huì)接受其他請(qǐng)求;這就出現(xiàn)一個(gè)問(wèn)題,同一時(shí)間可能存在多個(gè)應(yīng)用程序,也就是多個(gè)線程,這些線程都存在訪問(wèn)Application的可能,所以在對(duì)Application中的對(duì)象進(jìn)行處理的時(shí)候需要考慮線程同步的問(wèn)題;實(shí)際上Application對(duì)象內(nèi)部實(shí)現(xiàn)了一個(gè)線程鎖,調(diào)用它本身的Add、Remove等方法的時(shí)候會(huì)自動(dòng)調(diào)用加鎖和解鎖的操作,但是出于性能考慮,對(duì)于直接通過(guò)索引器或其他方式得到其中的對(duì)象并進(jìn)行操作的過(guò)程,Application并沒(méi)有自動(dòng)處理線程同步,需要利用下列類似的代碼來(lái)處理:
Application.Lock();
((int)Application["Count"])++;
Application.Unlock();
值得注意的是,調(diào)用了Lock之后,如果沒(méi)有顯示的調(diào)用Unlock,那么在這個(gè)請(qǐng)求結(jié)束的時(shí)候,Application對(duì)象會(huì)自動(dòng)解鎖,這樣防止了造成死鎖的問(wèn)題,但是為了代碼的健壯性,調(diào)用完Lock并且修改完畢應(yīng)該立即的調(diào)用Unlock方法。
Application對(duì)象本質(zhì)上就是一個(gè)Hash表,按照鍵值存放了對(duì)象,由于對(duì)象是全局并且存放在服務(wù)器,并且存在多線程同時(shí)訪問(wèn),所以,Application里面存放的應(yīng)該是訪問(wèn)較多,修改較少并且是全局至少大部分功能會(huì)使用的數(shù)據(jù),例如計(jì)數(shù)器或者數(shù)據(jù)庫(kù)連接串等。

2、Session 在Asp.Net內(nèi)部,有一個(gè)StateApplication來(lái)管理Session,實(shí)際上就是一個(gè)輔助進(jìn)程,處理Session到期、創(chuàng)建的特殊請(qǐng)求,在收到每一次請(qǐng)求的時(shí)候,輔助進(jìn)程就會(huì)調(diào)用狀態(tài)服務(wù)器(可以通過(guò)Web.config設(shè)置不同的狀態(tài)服務(wù)器)來(lái)獲取Session,如果沒(méi)有對(duì)應(yīng)該SessionId的Session,則會(huì)新建一個(gè),然后綁定到上下文中(HttpContext);與Asp不同的是,Session的狀態(tài)服務(wù)器有多種,目前在Asp.Net內(nèi)部實(shí)現(xiàn)了三種:
1) InProcStateClientManager 這是傳統(tǒng)的Session保存方式,但是還是有些細(xì)微差別
2) SqlStateClientManager 這是將Session保存到數(shù)據(jù)庫(kù)方式
3) OutOfProcStateClientManager 這是將Session保存到進(jìn)程外的方式
Asp.Net的Session機(jī)制有一個(gè)特點(diǎn),就是處理Session的輔助進(jìn)程與保存Session的狀態(tài)服務(wù)器是分開的,按照MSDN的說(shuō)法,有下列好處:
“因?yàn)橛糜跁?huì)話狀態(tài)的內(nèi)存不在 ASP.NET 輔助進(jìn)程中,所以可以實(shí)現(xiàn)從應(yīng)用程序故障的恢復(fù)。”
“因?yàn)樗袪顟B(tài)與輔助進(jìn)程不存儲(chǔ)在一起,您可以干凈地跨多個(gè)進(jìn)程對(duì)應(yīng)用程序進(jìn)行分區(qū)。這種分區(qū)可以顯著地提高多個(gè)進(jìn)程的計(jì)算機(jī)上應(yīng)用程序的可用性和可縮放性。”
“因?yàn)樗袪顟B(tài)與輔助進(jìn)程不存儲(chǔ)在一起,所以您可以跨運(yùn)行于多個(gè)計(jì)算機(jī)上的多個(gè)輔助進(jìn)程對(duì)應(yīng)用程序進(jìn)行分區(qū)。”
Asp.Net的Session機(jī)制個(gè)人觀點(diǎn),感覺(jué)靈活性比較好,內(nèi)部實(shí)現(xiàn)也比較巧妙,但是實(shí)際上因?yàn)闆](méi)有做過(guò)多的測(cè)試,所以應(yīng)用上會(huì)不會(huì)像它說(shuō)的那么美好,不敢打包票。有機(jī)會(huì),我會(huì)單獨(dú)寫篇文章來(lái)深入的探討Asp.Net 內(nèi)部的Session機(jī)制。

3、Cookie 這個(gè)沒(méi)甚么好說(shuō),實(shí)際上Asp.Net與Asp的Cookie沒(méi)甚么分別,也許這項(xiàng)技術(shù)毀譽(yù)參半,而且比較依賴客戶機(jī)實(shí)現(xiàn),MS也沒(méi)什么改進(jìn)的。

4、ViewState 這是我們今天重點(diǎn)討論的;實(shí)際上ViewState并不神秘,就是一個(gè)Hidden字段,但是它是服務(wù)器控件狀態(tài)保存的基礎(chǔ);不熟悉的朋友可以用IE查看Html源碼,找到一個(gè)名為"__VIEWSTATE"的Hidden字段,其中有一大堆亂七八糟的字符,這就是頁(yè)面的ViewState。

做過(guò)Web程序的人可能都有這種痛苦的體會(huì),有時(shí)候?yàn)榱颂幚眄?yè)面上面比較復(fù)雜的功能,常常會(huì)加很多Hidden,然后在服務(wù)器端用一大堆判斷來(lái)分析目前的狀態(tài),寫起來(lái)煩人,寫完了代碼更是難看;實(shí)際上,ViewState就是幫我們系統(tǒng)的實(shí)現(xiàn)了保存控件狀態(tài)的功能,服務(wù)器端控件能夠在多次請(qǐng)求間保存狀態(tài)也全靠它。
好,介紹就到這里,今天我們不是討論ViewState的使用,而是從內(nèi)部來(lái)探探這個(gè)東西的本質(zhì)。
我們首先建一個(gè)測(cè)試的頁(yè)面:
<%@ Page language="c#" Codebehind="ViewStateTest.aspx.cs" Inherits="CsdnTest.ViewStateTest" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html>
<head>
<title>ViewStateTest</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
</head>
<body>
<form id="ViewStateTest" method="post" runat="server">
<asp:Button ID="btnPostBack" Runat="server" Text="Post Back" Width="85px"></asp:Button>
<br/>
<asp:CheckBox ID="chkTest" Runat="server" Text="This is a check box"></asp:CheckBox>
</form>
</body>
</html>

這是用Vs.Net設(shè)計(jì)出來(lái)的一個(gè)簡(jiǎn)單的頁(yè)面,里面包含了一個(gè)服務(wù)器端的按鈕和一個(gè)CheckBox,然后我們?cè)诜?wù)器端響應(yīng)按鈕的事件:

private void btnPostBack_Click(object sender, System.EventArgs e)
{
[1] Response.Write( "ViewState :"+Request.Params["__VIEWSTATE"]+"<br/>" );

[2] string decodeValue = Encoding.UTF8.GetString( Convert.FromBase64String( Request.Params["__VIEWSTATE"] ) );

[3] Response.Write( "ViewState decode :"+decodeValue+"<br/>" );

[4] object viewstate = (new LosFormatter()).Deserialize( Request.Params["__VIEWSTATE"] );

[5] Response.Write( "ViewState Object :"+viewstate.GetType().Name );
}

為了方便看,我加上了行號(hào);第一行我們把ViewState的值打出來(lái),第二行是什么呢?實(shí)際上ViewState保存到客戶端的一串字符串就是內(nèi)部的ViewState通過(guò)某種方式序列化之后再經(jīng)過(guò)Base64編碼得來(lái)的,所以我們把Base64編碼的字符串反編碼一次再打出來(lái);至于第四行,我先不說(shuō),先看執(zhí)行結(jié)果:
運(yùn)行之后,頁(yè)面上什么都沒(méi)有,除了按鈕和CheckBox(廢話 :)),我們點(diǎn)擊按鈕,然后結(jié)果如下:

[A] ViewState :dDwxMjU2MDI5MTA3OztsPGNoa1Rlc3Q7Pj6Gg0Qzm+7gacYWcy0hnRCT9toOdA==
[B] ViewState decode:t<1256029107;;l>D3i s-! t
[C] ViewState Object :Triplet

然后我們來(lái)分析這個(gè)結(jié)果,A中顯示的就是ViewState傳到客戶端的值,B中顯示的是通過(guò)Base64反編碼之后的值,從這里面好像還是看不出什么,C中出現(xiàn)了一個(gè):Triplet ?這是什么呢,我們回到上面的代碼:
object viewstate = (new LosFormatter()).Deserialize( Request.Params["__VIEWSTATE"] );

注意我們使用了一個(gè)LosFormatter類,實(shí)際上這個(gè)類就是Asp.Net內(nèi)部為ViewState提供序列化的類,它有兩個(gè)方法,一個(gè)是Serialize,就是序列化一個(gè)對(duì)象,一個(gè)是Deserialize,是反序列化,我們這里使用了反序列化的方法來(lái)把ViewState直接反序列化成一個(gè)對(duì)象,然后把這個(gè)對(duì)象的類型打出來(lái),這個(gè)對(duì)象就是:Triplet類型,實(shí)際上Asp.Net中頁(yè)面保存的ViewState就是這個(gè)類型,我們先分析一下LosFormater,再來(lái)細(xì)說(shuō).
我們?cè)倩貋?lái)看打出來(lái)的結(jié)果B:t<1256029107;;l>D3i s-!
t,實(shí)際上通過(guò)查看LosFormatter反編譯后的代碼,大致上可以看出它序列化的方式是很簡(jiǎn)單的,就是判斷要序列化對(duì)象的類型,如果不是直接序列化的類型,則把它的類型記錄下來(lái),然后在遞歸序列化它的屬性,我們看B中的"t"就是表示Triplet這個(gè)類型,這個(gè)類型有三個(gè)屬性,這三個(gè)屬性包含在"<"和">"之間,用";"分割,而最后面的D3i s-!
t據(jù)我分析應(yīng)該是一個(gè)防止ViewState被改變的Hash值,這個(gè)不是很確定,因?yàn)榉淳幾g的代碼實(shí)在是很難看,我只是了解之后就沒(méi)仔細(xì)看了。

我們剛剛分析出來(lái)Page中的ViewState反序列化之后是Triplet這個(gè)類型,實(shí)際上這個(gè)類在MSDN中就查得到,它就是一個(gè)包含了三個(gè)對(duì)象的對(duì)象,說(shuō)簡(jiǎn)單點(diǎn),它就是一個(gè)能放三個(gè)箱子的大箱子(好像還是說(shuō)的比較糊涂,呵呵),它有三個(gè)屬性:First、Second、Thrid :),分別代表三個(gè)對(duì)象。
對(duì)應(yīng)到Page當(dāng)中,F(xiàn)irst是Page.GetTypeHashCode()的返回值,這個(gè)方法是System.Web.UI.Page定義的一個(gè)保護(hù)的虛擬方法,返回一個(gè)整型,由Aspx文件生成的類來(lái)實(shí)現(xiàn)的,因?yàn)檫@個(gè)類是有Asp.Net負(fù)責(zé)在運(yùn)行期生成源代碼并編譯,它會(huì)計(jì)算出一個(gè)大常量作為返回值,這個(gè)返回值在整個(gè)Web應(yīng)用程序所有的Page中是唯一的。(提一句題外話,Asp.Net自動(dòng)產(chǎn)生的源代碼可以到系統(tǒng)盤:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\Temporary ASP.NET Files下面去找),

服務(wù)熱線

153 8323 9821

功能和特性

價(jià)格和優(yōu)惠

網(wǎng)站和維護(hù)

推廣和優(yōu)化

微信服務(wù)號(hào)