有人说类似gridview datalist这样的控件最好不要用在高并发,IO大的网站中
企业应用中为了快速开发到可以用一用
因为这是一类"沉重"的组件
我们姑且不谈这种看法的正确性(我个人觉得有道理)
只谈它为什么笨重:
因为这些控件给页面带来了大量的
viewstate
<input type="hidden" name="____VIEWSTATE" id="____VIEWSTATE" value=
这就是页面状态
一个页面里可能存在两种状态
控件状态,视图状态
page类是在
LoadPageStateFromPersistenceMedium()
SavePageStateToPersistenceMedium()
存取页面状态的
这两个方法都是可以重写的
他们也可以把状态信息存储在别的媒介中
我们这里通过重写PageStatePersister属性
来实现自己的状态存取逻辑
我们为了压缩viewstate里的数据,必须先实现一个工具类:如下

Code
using System;
using System.IO;
using System.IO.Compression;
using System.Web.UI;
/// <summary>
///GZipCompress 的摘要说明
/// </summary>
public class GZipCompress
{
//LosFormatter序列化web窗体页的视图状态
private static LosFormatter _formater = new LosFormatter();
public GZipCompress()
{}
//带压缩功能的序列化
public static string Compress(object state)
{
StringWriter writer = new StringWriter();
//序列化状态
_formater.Serialize(writer, state);
//取得序列化结果
string stateString = writer.ToString();
writer.Close();
//将字符串转换成八位无符号整数数组
byte[] buffer = Convert.FromBase64String(stateString);
MemoryStream ms = new MemoryStream();
//搞一个压缩流出来,将流保持为打开的状态
GZipStream zipStream = new GZipStream(ms, CompressionMode.Compress, true);
zipStream.Write(buffer, 0, buffer.Length);
zipStream.Close();
buffer = new byte[ms.Length];
//获取或设置流中的当前位置
ms.Position = 0;
ms.Read(buffer, 0, buffer.Length);
ms.Close();
//将压缩结果转成字符串,便于保存在页面中
stateString = Convert.ToBase64String(buffer);
return stateString;
}
public static object Decompress(string stateString)
{
byte[] buffer = Convert.FromBase64String(stateString);
MemoryStream ms = new MemoryStream(buffer);
GZipStream zipStream = new GZipStream(ms, CompressionMode.Decompress);
MemoryStream msReader = new MemoryStream();
buffer = new byte[0x1000];//开辟0x1000个字节空间16*16*16=4K
while (true)
{
int read = zipStream.Read(buffer, 0, buffer.Length);
if (read <= 0)
{ break; }
msReader.Write(buffer, 0, read);
}
zipStream.Close();
ms.Close();
msReader.Position = 0;
buffer = msReader.ToArray();
stateString = Convert.ToBase64String(buffer);
return _formater.Deserialize(stateString);
}
}
下面重写PageStatePersister来实现自定义的页面状态存取

Code
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.IO;
using System.IO.Compression;
/// <summary>
///PageStatePersister 的摘要说明
/// </summary>
public class CompressPageStatePersister:PageStatePersister
{
private const string STATEKEY = "____VIEWSTATE";
//调用基类构造函数
public CompressPageStatePersister(Page page) : base(page) { }
//加载页面状态
public override void Load()
{
//取得保存在客户端的状态内容
string postbackstate = Page.Request.Form[STATEKEY];
if (!string.IsNullOrEmpty(postbackstate))
{
//解压,反序列化
//asp.net的viewstate包括控件状态和视图状态
//存储两个相关对象
Pair statePair = (Pair)GZipCompress.Decompress(postbackstate);
if (Page.EnableViewState)
{
ViewState = null;
}
else
{
ViewState = statePair.First;
}
ControlState = statePair.Second;
}
}
//保存页面状态
public override void Save()
{
if (!Page.EnableViewState)
{
ViewState = null;
}
if (ViewState != null || ControlState != null)
{
string stateString;
Pair statePair = new Pair(ViewState, ControlState);
//序列化,压缩
stateString = GZipCompress.Compress(statePair);
//把页面状态注册到页面上
Page.ClientScript.RegisterHiddenField(STATEKEY, stateString);
}
}
}
项目的webconfig文件

Code
<?xml version="1.0"?>
<configuration>
<appSettings/>
<connectionStrings>
<add name="AntMallConnectionString" connectionString="Data Source=192.168.1.186;Initial Catalog=AntMall;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true"></compilation>
<authentication mode="Forms"/>
</system.web>
</configuration>
用来测试的一个页面

Code
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>无标题页</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server" AllowPaging="True"
DataSourceID="SqlDataSource1" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="title" HeaderText="title" SortExpression="title" />
<asp:BoundField DataField="memo" HeaderText="memo" SortExpression="memo" />
<asp:BoundField DataField="fullPrice" HeaderText="fullPrice"
SortExpression="fullPrice" />
<asp:BoundField DataField="defaultPic" HeaderText="defaultPic"
SortExpression="defaultPic" />
<asp:BoundField DataField="inputTime" HeaderText="inputTime"
SortExpression="inputTime" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:AntMallConnectionString %>"
SelectCommand="SELECT [fullPrice], [inputTime], [memo], [title], [defaultPic] FROM [Product]">
</asp:SqlDataSource>
</div>
</form>
</body>
</html>
用来测试的页面的cs文件
注意里面重写了PageStatePersister

Code
using System;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
public partial class _Default : System.Web.UI.Page
{
#region 重写PageStatePersister定制页面状态持久化行为
CompressPageStatePersister _pageStatePersister = null;
protected override PageStatePersister PageStatePersister
{
get
{
if (_pageStatePersister == null)
{
_pageStatePersister = new CompressPageStatePersister(this);
}
return _pageStatePersister;
}
}
#endregion
protected void Page_Load(object sender, EventArgs e)
{
}
}
实验做完
大家运行一下就知道
定制出来的viewstate比自动生成的要小很多
最后评价一句
传输给客户的东西是少了许多
但是服务器的CPU要做的事情也多了
用与不用还要自己权衡
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?