萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> asp.net編程 >> ASP.NET 2.0的視圖狀態持久性機制

ASP.NET 2.0的視圖狀態持久性機制

   前言

只要對ViewState稍有了解,就會知道,Asp.net頁面中ViewState一般是存儲在頁面的一個隱藏域中: 

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="一堆亂七八糟的東西">

當我們浏覽頁面源文件時,看到的那一大堆(特別是當頁面有個有大量數據的DataGrid,或在ASP.NET2.0中的GridView時)亂七八糟的東西的時候,那就是ViewState了。

 基礎知識

因為,在ASP.NET2.0中ViewState的持久性存儲機制有了些新的變化,所以,還是簡單介紹下相關的東西。

在ASP.NET1.1中,只提供了頁面隱藏域的持久性機制,這樣在某些情況下不得不放棄使用ViewState,試想下,如果你的DataGrid中有上萬條記錄(別認為這種變態的需要是沒有的,有人就碰到過),如果啟用了ViewState,你感保證你的IIS服務器能承受得住嗎,網絡承受得主嗎?當然你是可以通過重寫Page.SavePageStateToPersistenceMedium()方法來更改你的存儲機制,但別忘了重寫Page.LoadPageStateFromPersistenceMedium(),它們可是一對的啊。

ASP.NET2.0 中的默認視圖狀態持久性機制依然是在頁上的一個隱藏 HTML 元素(一個 type 屬性設置為 "hidden" 的元素)中將狀態信息保留為一個 Base64 編碼的字符串。ASP.NET 頁使用 HiddenFieldPageStatePersister 對象執行此項工作,並使用一個 IStateFormatter 實例對對象狀態信息進行序列化和反序列化。或者,對於帶寬和資源有限的移動客戶端,您也可以使用 SessionPageStatePersister 類在服務器上的 Session 對象中存儲頁的視圖狀態,其實也就多了個Session持久機制而已,讓我們把頁面狀態保存在Session中,而不是頁面中,這對帶寬是一種節省。

但你要深入的了解ViewState持久機制的話,抽象類PageStatePersister你是應該去了解的,要在不能支持現有視圖狀態持久性機制的客戶端上保留視圖狀態,可以擴展 PageStatePersister 類,引入您自己的視圖狀態持久性方法,並且可以使用頁適配器將 ASP.NET 應用程序配置為根據為其提供頁的客戶端的類型使用不同的視圖狀態持久性機制。從 PageStatePersister 類派生的類必須重寫 Save 抽象方法,以便在持久性介質中存儲視圖狀態和控件狀態,同時重寫 Load 方法以提取狀態信息。如果需要將視圖狀態和控件狀態序列化為字符串,可以使用通過 StateFormatter 屬性來訪問的 IStateFormatter 對象。它可以高效地將對象狀態信息序列化和反序列化為 Base64 編碼字符串。還可以重寫 StateFormatter 屬性以提供自己的對象狀態序列化機制,如何為之,我的代碼中都有介紹,很簡單,看看就明白了。

ViewState持久性機制

隱藏域

這個就不介紹了,默認的就是這種。就入前言中的那樣。

Session

在ASP.NET2.0中只要重寫PageStatePersister屬性就可以了。
 

protected override PageStatePersister PageStatePersister
{
get
{
return new SessionPageStatePersister(Page);
}
}


  要是在ASP.NET1.1中需要重寫LoadPageStateFromPersistenceMedium這兩個方法:

protected override object LoadPageStateFromPersistenceMedium() 
{
return Session["ViewState"];
}

protected override void SavePageStateToPersistenceMedium(object viewState) 
{
Session["ViewState"] = viewState; 
RegisterHiddenField("__VIEWSTATE", "");
}


  數據庫(我的示例是SQL Server2000)

  在ASP1.1中,請注意下面紫色的那行,我也不太清楚那有什麼用,它讓我郁悶了好幾天,等下你就明白我的郁悶了。還有下面的代碼只是湊我的源碼中拷貝出來的,你完全可以不這樣寫的,除了那些必要的外。

protected override void SavePageStateToPersistenceMedium(object state)
{
string viewStateID = "VIEWSTATE#" + Session.SessionID.ToString() + "#" + DateTime.Now.Ticks.ToString();
ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", viewStateID);
ClientScript.RegisterHiddenField("__VIEWSTATE","");//請注意

try
{
if (losFormatter == null)
{
losFormatter = new LosFormatter();
}
StringWriter sw = new StringWriter();
losFormatter.Serialize(sw, state);
Common.ViewStateData vsd = new ViewStateData();
vsd.ViewStateID = viewStateID;
vsd.ViewState = sw.ToString();
da = new DataAccess();
string error = da.SaveViewState(vsd);
Response.Write(error);
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}

protected override object LoadPageStateFromPersistenceMedium()
{
string viewState = string.Empty;
try
{
if (losFormatter == null)
{
losFormatter = new LosFormatter();
}
string stateID = Page.Request["__VIEWSTATE_KEY"].ToString();
da = new DataAccess();
viewState = da.LoadViewState(stateID);
}
catch
{}

return losFormatter.Deserialize(viewState);
}


  在ASP2.0中這行代碼基本是可以的,為什麼是基本呢,因為就是上面那行 ClientScript.RegisterHiddenField("__VIEWSTATE","");

  有沒有這行,在Asp.net1.1中都是可行的,我也是參考過別人的代碼,這行就這麼加入了,加了這行後,只是在頁面中多了個

<input type="hidden" name="__VIEWSTATE" value="" />


  也就是運行後頁面的源文件中有兩個這樣的東西。去掉那行也可以,所以

copyright © 萬盛學電腦網 all rights reserved