我们都知道asp.net 服务器控件状态都是通过ViewState对象存储的,实际上是存储在客户端页面上的隐藏域中,当数据量过大时频繁和服务器传输,严重影响性能。直接想到的办法就是把这些数据储存到别的介子中。 这里介绍两中存储方法,存储到数据库和物理文件中。
首先,我们要找到ViewState存储和恢复的入口函数。
Page类中LoadPageStateFromPersistenceMedium()为恢复数据函数, SavePageStateToPersistenceMedium(object state)为存储数据函数,我们只需重写这两个方法即可满足自定义处理ViewState的需求
1、存储到数据库
//存视图数据
protected override void SavePageStateToPersistenceMedium(object state)
{
string viewStateID = (DateTime.Now.Ticks + (long)this.GetHashCode()).ToString(); //产生唯一的Id编码,防止多用户访问时造成数据误读
string str = (new ObjectStateFormatter()).Serialize(state);//将对象序列化为Base64格式字符串
//将ViewStateID和序列化后数据写数据库
base.SavePageStateToPersistenceMedium(viewStateID); //将唯一Id存储到ViewState中,以便Load时一一对应读取相应数据
}
//恢复视图数据
protected override object LoadPageStateFromPersistenceMedium()
{
string viewStateID = (string)((Pair)base.LoadPageStateFromPersistenceMedium()).Second; //读取唯一Id,注意:此处为Second,为ViewState对象,First为ControlState,可通过.net反编译工具看出。
string str=//根据viewStateID从数据库读取序列化后的数据
return (new ObjectStateFormatter()).Deserialize(str);//将Base64格式字符串反序列化为对象
}
2、存储到文件
//存视图数据
protected override void SavePageStateToPersistenceMedium(object state)
{
string str = (new ObjectStateFormatter()).Serialize(state);
int length = str.Length;
string viewStateID = (DateTime.Now.Ticks + (long)this.GetHashCode()).ToString();
string filePath = MapPath("SaveViewStateFile/File(" + viewStateID + ").txt");
File.WriteAllText(filePath, str);
base.SavePageStateToPersistenceMedium(viewStateID);
}
//恢复视图数据
protected override object LoadPageStateFromPersistenceMedium()
{
string viewStateID = (string)((Pair)base.LoadPageStateFromPersistenceMedium()).Second;
string filePath = MapPath("SaveViewStateFile/File("+viewStateID+").txt");
string str= File.ReadAllText(filePath);
return (new ObjectStateFormatter()).Deserialize(str);
}
总结:
将ViewState数据转移其实很简单,只要找到两个入口函数即可,但注意多个会话同时操作时务必保证每个会话和视图数据一一对应,否则会造成数据混乱。