日期:2011-08-27  浏览次数:20457 次

  前言

  只要对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
 {}<