分享
 
 
 

ASP.NET 2.0的视图状态持久性机制

王朝asp·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

前言

只要对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="" />

也就是运行后页面的源文件中有两个这样的东西。去掉那行也可以,所以我不明白语句是用做什么的,请明白的告诉我吧。但是在Asp.net2.0中就不行,有如下错误:

The state information is invalid for this page and might be corrupted.

反正当时就是晕晕的,我以前从来没有碰到过如是错误,去google也无所得,是啊,打死我也不知道是那句错了啊,就这么郁闷了两天,问题无法解决,本人天生愚钝的,我跟踪视图状态的存入数据库与从数据库的读取的整个过程,硬是找不到错误,我就反复思考这些代码,惟有那行,我就是有点迷惑,为什么还要页面注册一个“__VIEWSTATE”的隐藏域呢,于是我就注释掉这行,居然可以运行了,所以我还是不明白那行是什么用意。

当然我们还可以通过写一个PageStatePersister新子类也可以完成上述功能,这是ASP.NET2.0新增的:

namespace PageAdapter

{

using System;

using System.IO;

using System.Security.Permissions;

using System.Web;

using System.Web.UI;

[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]

public class DatabasePageStatePersister : PageStatePersister

{

public DatabasePageStatePersister(Page page): base(page)

{}

//

// Load ViewState and ControlState.

//

public override void Load()

{

string viewState;

IStateFormatter formatter = this.StateFormatter;

DataAccess da = new DataAccess();

string stateID = base.Page.Request["__VIEWSTATE_KEY"].ToString();

viewState = da.LoadViewState(stateID);

Pair statePair = (Pair)formatter.Deserialize(viewState);

ViewState = statePair.First;

ControlState = statePair.Second;

}

//

// Persist any ViewState and ControlState.

//

public override void Save()

{

if (ViewState != null || ControlState != null)

{

if (Page.Session != null)

{

string viewStateID = "VIEWSTATE#" + base.Page.Session.SessionID.ToString() + "#" + DateTime.Now.Ticks.ToString();

base.Page.ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", viewStateID);

Pair statePair = new Pair(ViewState, ControlState);

IStateFormatter formatter = this.StateFormatter;

// Serialize the statePair object to a string.

string serializedState = formatter.Serialize(statePair);

ViewStateData vsd = new ViewStateData();

vsd.ViewStateID = viewStateID;

vsd.ViewState = serializedState;

DataAccess da = new DataAccess();

string error = da.SaveViewState(vsd);

}

else

throw new InvalidOperationException("Session needed for StreamPageStatePersister.");

}

}

}

}

再有重写PageStatePersister属性就可以了:

protected override PageStatePersister PageStatePersister

{

get

{

return new DatabasePageStatePersister(Page);

}

文件

这其实也跟数据库的差不了多少,我这只讲ASP.NET2.0的,在ASP.NET1.1也应该差不多,但我没有写代码调试:

还是用那种写PageStatePersister新子类的办法:

namespace StreamPageAdapter

{

using System;

using System.IO;

using System.Security.Permissions;

using System.Web;

using System.Web.UI;

//

// The StreamPageStatePersister is an example view state

// persistence mechanism that persists view and control

// state on the Web server.

//

[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]

public class StreamPageStatePersister : PageStatePersister

{

public StreamPageStatePersister(Page page): base(page)

{}

//

// Load ViewState and ControlState.

//

public override void Load()

{

Stream stateStream = GetSecureStream();

// Read the state string, using the StateFormatter.

StreamReader reader = new StreamReader(stateStream);

IStateFormatter formatter = this.StateFormatter;

string fileContents = reader.ReadToEnd();

// Deserilize returns the Pair object that is serialized in

// the Save method.

Pair statePair = (Pair)formatter.Deserialize(fileContents);

ViewState = statePair.First;

ControlState = statePair.Second;

reader.Close();

stateStream.Close();

}

//

// Persist any ViewState and ControlState.

//

public override void Save()

{

if (ViewState != null || ControlState != null)

{

if (Page.Session != null)

{

Stream stateStream = GetSecureStream();

StreamWriter writer = new StreamWriter

[1] [2] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有