ASP.Net ViewState压缩:我应该打扰吗?

时间:2009-05-12 20:20:20

标签: asp.net .net-3.5 viewstate

所以基本上我正在尝试针对手机进行优化的网站(这包括几乎所有支持浏览器的手机)由于网站的性质,我希望它尽快加载。此时,我认为页面的大小约为30k左右。

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

我已经看到很多这样的例子,例如(I swear not my blog),但是没有涉及到3.5,这让我想知道从那以后没有任何改变或压缩视图状态已经失宠了。

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

5 个答案:

答案 0 :(得分:4)

  

我正在使用viewstate,主要用于datagrids之类的东西,而不是自己“保存”任何字段。

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

请记住,用户必须将viewstate的内容从浏览器上传到服务器,然后在每次回发时将其下载回来。如果你有一个100Mbit的连接到web服务器 - 就像一个公司的局域网,webforms往往更受欢迎 - 那么viewstate是伟大的。但是对于手机浏览器,许多用户可能相当于拨号,甚至更糟糕:按字节付费。在这种情况下,我会尝试尽可能地关闭它,并且只在必要时启用它。

答案 1 :(得分:2)

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

首先,我们需要一种压缩和解压缩内存中字节数组的方法。我将这个简单的静态类放在一起,它暴露了两种方法:压缩和解压缩。根据MSDN,两个可用的类GZipStream和DeflateStream使用相同的算法,因此与您选择的算法无关。

以下代码非常简单,无需进一步说明:



    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

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



    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解码,解压缩和反序列化__VSTATE的内容,并将其返回到运行时。在第二种方法中,我们执行相反的操作:在Base64中进行序列化,压缩和编码。然后将Base64字符串保存到__VSTATE隐藏字段中。 LosFormatter对象执行序列化和反序列化任务。

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

以上内容首先由Dario Solera在codeproject上发布。 http://www.codeproject.com/Articles/14733/ViewState-Compression

答案 2 :(得分:1)

我不认为它已经失宠,只是在2.0中保存视图状态应该与在3.5中保存视图状态相同。减少viewstate的最佳方法是不使用它,但这并不总是可行的。

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

修改

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

Here's a code project article
Looks like a good article

答案 3 :(得分:0)

拥有ViewState与快速加载网页相反。你为什么需要ViewState?尽可能少地重新考虑您的设计和使用。我会将Session数据的粗略部分放在服务器和/或数据库上,直到有理由在ViewState中保留一些数据。

答案 4 :(得分:0)

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

这里我已经用代码编写了如何做到这一点.. http://ashishnangla.com/2011/07/21/reducing-size-of-viewstate-in-asp-net-webforms-by-writing-a-custom-viewstate-provider-pagestatepersister-part-12/