什么是ViewState
虽然本文并不是专门来研究ViewState的,但我们还是简单的讨论一下吧。你如果看过web form生成的HTML代码的话,就会发现在一个名为__VIEWSTATE的隐藏域。聪明的ASP.NET会持久化这些控件的值到这个隐藏域中,这对于往返服务器的过程中保存控件的值是非常有用的。但是,此时ViewState会带来性能问题。因为ViewState要在服务端与客户端之间传输,所以会增加网络带宽的流量。
要减少ViewState的话,可以关闭ViewState,就是设置控件的EnableViewState属性,如果设置该属性为false则控件的ViewState将被关闭。但是,如果没有ViewState的话,控件状态持久化的工作就需要你自己来做了,这将是令人非常头痛的。还有另一种减少ViewState的方法就是本文将要介绍的方法,即在ViewState传输之前先压缩它,这样ViewState的数据将会大幅度减少。
在ASP.NET 1.x中如果我们要使用压缩功能的话需要自己写一些代码。而现在.NET 2.0提供了System.IO.Compression命名空间,将会使压缩功能的实现变得非常简单。System.IO.Compression命名空间的GZipStream类可以处理流的压缩和解压,注意,GZipStream只能以流的方式工作。GZipStream类不知专门压缩ViewState而设计的,所以我们为了实现ViewState的压缩和解压要自己写一些代码。
开发ViewStateHelper
我们首先用Visual Studio新建一个web站点,然后再App_Code文件夹中增加一个名为ViewStateHelper的类。增加如下代码用来负责压缩与解压:
public class ViewStateHelper
{
public static byte[] Compress(byte[] data)
{
MemoryStream ms = new MemoryStream();
GZipStream gzip = new GZipStream(ms, CompressionMode.Compress);
gzip.Write(data, 0, data.Length);
gzip.Close();
return ms.ToArray();
}
public static byte[] Decompress(byte[] data)
{
int bytes = 0;
MemoryStream ms = new MemoryStream();
ms.Write(data, 0, data.Length);
ms.Position = 0;
GZipStream gzip = new GZipStream(ms, CompressionMode.Decompress);
MemoryStream tms = new MemoryStream();
byte[] buff = new byte[1024];
while ((bytes = gzip.Read(buff, 0, buff.Length)) > 0)
{
tms.Write(buff, 0, bytes);
}
gzip.Close();
return tms.ToArray();
}
}
最后在需要压缩viewstate的页重载如下两个方法:
protected override void SavePageStateToPersistenceMedium(object state)
{
LosFormatter losFmt = new LosFormatter();
StringWriter writer = new StringWriter();
losFmt.Serialize(writer, state);
byte[] viewState = Convert.FromBase64String(writer.ToString());
byte[] buff = ViewStateHelper.Compress(viewState);
string vstate = Convert.ToBase64String(buff);
Page.ClientScript.RegisterHiddenField("__MyViewState", vstate);
}
protected override object LoadPageStateFromPersistenceMedium()
{
string vstate = Request.Form["__MyViewState"];
byte[] buff = Convert.FromBase64String(vstate);
byte[] viewState = ViewStateHelper.Decompress(buff);
string rvs=Convert.ToBase64String(viewState);
LosFormatter losFmt = new LosFormatter();
return losFmt.Deserialize(rvs);
}
总结
从本文中你学到了如何通过压缩ViewState来改善你web站点的性能。GZipStream类提供了现成的把你的数据压缩成gzip格式的方法。被压缩的数据需要通过重写Page基类的SavePageStateToPersistenceMedium()方法保存。相似的,读取ViewState后我们需要通过重写LoadPageStateFromPersistenceMedium()来解压数据。
注:IIS6是内建gzip压缩支持的,IE6和Firefox也都是支持客户端gzip。如何启用IIS的gzip压缩功能请google;