ASP.Net视图状态压缩:我应该麻烦吗?

ASP.Net视图状态压缩:我应该麻烦吗?,asp.net,.net-3.5,viewstate,Asp.net,.net 3.5,Viewstate,所以基本上,我正在一个网站上工作,该网站正试图为手机(这几乎包括任何支持浏览器的手机)进行优化,由于该网站的性质,我希望它尽快加载。在这一点上,我认为页面的大小大约是30k左右 现在我使用viewstate,主要用于数据网格之类的东西,而不是自己“保存”任何字段 我在2.0中看到了很多这样的例子,但是3.5中没有任何内容,这让我怀疑从那时起是否没有任何变化,或者压缩viewstate是否不受欢迎 问题是,我应该费心压缩视图状态,还是有更好的解决方案?我不认为在2.0中保存视图状态与在3.5中保存

所以基本上,我正在一个网站上工作,该网站正试图为手机(这几乎包括任何支持浏览器的手机)进行优化,由于该网站的性质,我希望它尽快加载。在这一点上,我认为页面的大小大约是30k左右

现在我使用viewstate,主要用于数据网格之类的东西,而不是自己“保存”任何字段

我在2.0中看到了很多这样的例子,但是3.5中没有任何内容,这让我怀疑从那时起是否没有任何变化,或者压缩viewstate是否不受欢迎


问题是,我应该费心压缩视图状态,还是有更好的解决方案?

我不认为在2.0中保存视图状态与在3.5中保存视图状态的效果是一样的,这已经不受欢迎了。减少viewstate的最佳方法是不使用它,但这并不总是可行的

在这些情况下,您应该试验带宽与服务器上所需额外处理时间之间的权衡。要知道它是否值得,唯一的办法就是去做并衡量它的影响

编辑

我看到的另一个选项是在服务器上保存视图状态。它可以保存在内存、数据库或磁盘中。取决于您的环境要求。这将是最大的带宽节约



拥有ViewState与拥有快速加载网页相反。为什么需要ViewState?重新考虑你的设计,尽量少用。我会将大量会话数据放在服务器和/或数据库上,直到有理由将某些数据保留在ViewState中

我使用viewstate,主要用于数据网格之类的东西,而不是自己“保存”任何字段

我最担心的是网格。您自己保存在那里的字段往往是简单的变量,如数据库ID或用户名。这些不会引起那么多问题,因为它们很小。整个网格可能包含大量数据,而这正是您遇到麻烦的地方


请记住,用户必须将viewstate的内容从浏览器上载到服务器,然后在每次回发时将其下载回来。如果你有一个100Mbit的网络服务器连接,就像公司的局域网一样,webforms往往更受欢迎,那么viewstate就很棒了。但在手机浏览器中,许多用户可能使用拨号上网,甚至更糟的是:按字节付费。在这个场景中,我会尽量关闭它,并且只在必要时启用它

压缩和解压缩内存中的数据

首先,我们需要一种方法来压缩和解压缩内存中的字节数组。我把这个简单的静态类放在一起,它公开了两种方法:压缩和解压缩。根据MSDN,两个可用的类GZipStream和deflatesttream使用相同的算法,因此选择哪一个并不重要

下面的代码非常简单,不需要进一步解释:



    using System.IO;
    using System.IO.Compression;

    public static class Compressor {

      public static byte[] Compress(byte[] data) {
        MemoryStream output = new MemoryStream();
        GZipStream gzip = new GZipStream(output, 
                          CompressionMode.Compress, true);
        gzip.Write(data, 0, data.Length);
        gzip.Close();
        return output.ToArray();
      }

      public static byte[] Decompress(byte[] data) {
        MemoryStream input = new MemoryStream();
        input.Write(data, 0, data.Length);
        input.Position = 0;
        GZipStream gzip = new GZipStream(input, 
                          CompressionMode.Decompress, true);
        MemoryStream output = new MemoryStream();
        byte[] buff = new byte[64];
        int read = -1;
        read = gzip.Read(buff, 0, buff.Length);
        while(read > 0) {
          output.Write(buff, 0, read);
          read = gzip.Read(buff, 0, buff.Length);
        }
        gzip.Close();
        return output.ToArray();
      }
    }

您需要将该类保存在.cs文件中,并将其放入ASP.NET应用程序的App_Code目录中,确保它包含在正确的自定义命名空间中(如果未指定任何命名空间,则该类将在内置ASP命名空间中可用)

压缩视图状态

现在,我们可以实际压缩页面的ViewState。为此,我们必须重写LoadPageStateFromPersistenceMedium和SavePageStateToPersistenceMedium这两个方法。代码只是使用一个额外的隐藏字段--VSTATE来存储压缩后的ViewState。如您所见,通过查看页面的HTML,_VIEWSTATE字段为空,而我们的_VSTATE字段包含压缩的VIEWSTATE,用Base64编码。让我们看看代码



    public partial class MyPage : System.Web.UI.Page {

      protected override object LoadPageStateFromPersistenceMedium() {
        string viewState = Request.Form["__VSTATE"];
        byte[] bytes = Convert.FromBase64String(viewState);
        bytes = Compressor.Decompress(bytes);
        LosFormatter formatter = new LosFormatter();
        return formatter.Deserialize(Convert.ToBase64String(bytes));
      }

      protected override void SavePageStateToPersistenceMedium(object viewState) {
        LosFormatter formatter = new LosFormatter();
        StringWriter writer = new StringWriter();
        formatter.Serialize(writer, viewState);
        string viewStateString = writer.ToString();
        byte[] bytes = Convert.FromBase64String(viewStateString);
        bytes = Compressor.Compress(bytes);
        ClientScript.RegisterHiddenField("__VSTATE", Convert.ToBase64String(bytes));
      }

      // The rest of your code here...

    }

在第一种方法中,我们只是从Base64解码,解压缩并反序列化u VSTATE的内容,然后将其返回到运行时。在第二种方法中,我们执行相反的操作:在Base64中序列化、压缩和编码。Base64字符串随后保存到_VSTATE隐藏字段中。LosFormatter对象执行序列化和反序列化任务

您可能还希望创建一个新类,例如CompressedPage,继承自System.Web.UI.Page,在该类中重写这两个方法,然后从该类继承页面,例如MyPage:CompressedPage。请记住,.NET只有一个继承,按照这种方式,您“花费”了您唯一的继承机会来使用ViewState压缩。另一方面,在每个类中重写这两个方法是浪费时间,因此您必须选择最适合您需要的方式

上述内容由Dario Solera在codeproject上首次发布。
压缩viewstate只能将其减少50%左右。我向前走了几步,使用了ViewState替换技术,其中ViewState被页面上的GUID替换。实际的ViewState数据保存在服务器本身的数据库中,客户端(浏览器)获取和提交的只是一个62字节的令牌。它将200-300KB的大视图状态减少到62字节

在这里,我写了如何用代码实现这一点。。

ViewState有它自己的位置(还有一些),但在我看来,提倡完全不使用它太极端了。它对于存储您不希望存储在页面上隐藏字段中的身份密钥(恶意用户可以篡改)非常宝贵。现在,如果你要在其中存储整个数据集之类的东西,那么,是的,你需要重新考虑你的游戏计划。好吧……我的许多客户都向我寻求“一些增强和性能改进”。在这种情况下,我无法更改由其他程序员编写的会话管理应用程序逻辑。我需要实施一些快速(客户称之为)修复来提高应用程序速度。您应该编辑此文件以格式化源代码,使其更清晰。我本以为在IIS中启用GZip压缩