前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >四:理解Page类的运行机制(例:基于PageStatePersister的页面状态存取)

四:理解Page类的运行机制(例:基于PageStatePersister的页面状态存取)

作者头像
liulun
发布2022-05-08 17:56:30
3470
发布2022-05-08 17:56:30
举报
文章被收录于专栏:liulunliulun

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

代码语言:javascript
复制
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来实现自定义的页面状态存取

代码语言:javascript
复制
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文件

代码语言:javascript
复制
<?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>

用来测试的一个页面

代码语言:javascript
复制
<%@ 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

代码语言:javascript
复制
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要做的事情也多了 用与不用还要自己权衡

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2009-01-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档