代码之家  ›  专栏  ›  技术社区  ›  Seb Nilsson

ASP.NET:压缩视图状态

  •  9
  • Seb Nilsson  · 技术社区  · 15 年前

    压缩ASP.NET ViewState内容的最新和最佳方法是什么?

    这个表演怎么样?保持页面的快速和最小化数据流量是否值得?

    我怎样才能做到:

    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
    value="/wEPDwUKMTM4Mjc3NDEyOWQYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgkFLGN0b
    DAwJENvbnRlbnRQbGFjZUhvbGRlcl9NYWluQ29udGVudCRSYWRCdXQxBSxjdGwwMCRDb250ZW50UGxhY2VIb
    2xkZXJfTWFpbkNvbnRlbnQkUmFkQnV0MQUsY3RsMDAkQ29udGVudFBsYWNlSG9sZGVyX01haW5Db250ZW50J
    FJhZEJ1dDIFLGN0bDAwJENvbnRlbnRQbGFjZUhvbGRlcl9NYWluQ29udGVudCRSYWRCdXQyBSxjdGwwMCRDb
    250ZW50UGxhY2VIb2xkZXJfTWFpbkNvbnRlbnQkUmFkQnV0MwUsY3RsMDAkQ29udGVudFBsYWNlSG9sZGVyX
    01haW5Db250ZW50JFJhZEJ1dDQFLGN0bDAwJENvbnRlbnRQbGFjZUhvbGRlcl9NYWluQ29udGVudCRSYWRCd
    XQ0BSxjdGwwMCRDb250ZW50UGxhY2VIb2xkZXJfTWFpbkNvbnRlbnQkUmFkQnV0NQUsY3RsMDAkQ29udGVud
    FBsYWNlSG9sZGVyX01haW5Db250ZW50JFJhZEJ1dDXz21BS0eJ7991pzjjj4VXbs2fGBw==" />
    

    像这样的事情:

    <input type="hidden" name="__VIEWSTATE"  id="__VIEWSTATE" 
    value="/wEPDwUKMTM4Mjc3N==" />
    
    8 回复  |  直到 12 年前
        1
  •  8
  •   Bernhard Hofmann    15 年前

    简单的答案可能不是你想听到的。通常,页面上的控件在它们确实不需要视图状态时,默认情况下具有视图状态。最好关闭view state,直到你知道你需要它为止,并且只在你真正想要保持视图状态的少数情况下才打开它。

        2
  •  8
  •   Thomas    15 年前
    1. 避免使用视图状态
    2. 在IIS服务器上使用压缩。
    3. 您可以通过执行以下操作来连接将视图状态压缩到页面内外的内容:
    public abstract class PageBase : System.Web.UI.Page
    {
        private ObjectStateFormatter _formatter = new ObjectStateFormatter();
    
        private static byte[] Compress( byte[] data )
        {
                var compressedData = new MemoryStream();
                var compressStream = new GZipStream(output, CompressionMode.Compress, true);
                compressStream.Write(data, 0, data.Length);
                compressStream.Close();
                return compressedData.ToArray();
        }
        private static byte[] Uncompress( byte[] data )
        {
                var compressedData = new MemoryStream();
                input.Write(compressedData, 0, compressedData.Length);
                input.Position = 0;
                var compressStream = new GZipStream(compressedData, CompressionMode.Decompress, true);
                var uncompressedData = new MemoryStream();
                var buffer = new byte[64];
                var read = compressStream.Read(buffer, 0, buffer.Length);
    
                while (read > 0)
                {
                    uncompressedData.Write(buffer, 0, read);
                    read = compressStream.Read(buffer, 0, buffer.Length);
                }
                compressStream.Close();
                return uncompressedData.ToArray();
        }
        protected override void SavePageStateToPersistenceMedium(object viewState)
        {
            var ms = new MemoryStream();
            _formatter.Serialize(ms, viewState);
            var viewStateBytes = ms.ToArray();
            ClientScript.RegisterHiddenField("__COMPRESSED_VIEWSTATE"
                , Convert.ToBase64String( Compress(viewStateArray)) );
        }
        protected override object LoadPageStateFromPersistenceMedium()
        {
            var compressedViewState = Request.Form["__COMPRESSED_VIEWSTATE"];
            var bytes = Uncompress( Convert.FromBase64String( compressedViewState ) );
            return _formatter.Deserialize( Convert.ToBase64String( bytes ) );
        }
    }
    
        3
  •  6
  •   Rob Lauer    14 年前

    我意识到这是一个旧的线程,但我们已经使用Telerik的Radcompression httpmodule一段时间了,它在压缩viewstate、Ajax和Web服务响应方面非常有效。您还可以在会话中欺骗并保存viewstate,这对低流量站点很好。

    http://www.telerik.com/help/aspnet-ajax/radcompression.html

        4
  •  1
  •   Seb Nilsson    15 年前

    SEB,视图状态已被压缩…这就是你看到的……控件的压缩版本。如果您希望减少开销,那么不要使用viewstate:)

    视图状态的使用应保持在最低限度!

        5
  •  1
  •   vdboor    15 年前

    这是已发布视图状态的XML化可视化:

    <viewstate>
      <Pair>
        <Pair>
          <String>1382774129</String>
        </Pair>
      </Pair>
    </viewstate>
    <controlstate>
      <HybridDictionary>
        <DictionaryEntry>
          <String>__ControlsRequirePostBackKey__</String>
          <ArrayList>
            <String>ctl00$ContentPlaceHolder_MainContent$RadBut1</String>
            <String>ctl00$ContentPlaceHolder_MainContent$RadBut1</String>
            <String>ctl00$ContentPlaceHolder_MainContent$RadBut2</String>
            <String>ctl00$ContentPlaceHolder_MainContent$RadBut2</String>
            <String>ctl00$ContentPlaceHolder_MainContent$RadBut3</String>
            <String>ctl00$ContentPlaceHolder_MainContent$RadBut4</String>
            <String>ctl00$ContentPlaceHolder_MainContent$RadBut4</String>
            <String>ctl00$ContentPlaceHolder_MainContent$RadBut5</String>
            <String>ctl00$ContentPlaceHolder_MainContent$RadBut5</String>
          </ArrayList>
        </DictionaryEntry>
      </HybridDictionary>
    </controlstate>
    

    基本上只有几个按钮,它们喜欢知道它们的存在。(浏览器不发送 <input type="radio"> 如果未选中,则包含postdata的字段)。这已经很小了。

    它可能通过挂接在加载/保存方法或HTTP模块中进行压缩,但这可能并不实际也不真正需要。


    如果你的真实应用中的视图状态要大得多,那么就不要在视图状态中获取对象。这可以通过初始化 OnInit() Page_Init() 方法而不是默认值 Page_Load() .

    这背后的基本原理可以在 http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx http://msdn.microsoft.com/en-us/library/ms972976.aspx

    快速总结:

    • viewstate只是几乎所有控件属性(包括默认值)的后备存储。
    • 设置默认值后 OnInit()。 ,的 TrackViewState() 将调用方法。
    • 任何后续更改(例如 PayLyLoad() )或者事件处理程序,将被跟踪并提交给客户端。这样,这些控件可以在下次请求时恢复其状态。
    • 不依赖框架来恢复对象,而是在 ONIN() 当需要时。(例如,重新填充 DropDownList 从数据库)。

    一个例外:

    如果一个控件被动态地添加到控件树中,它将扮演一个追赶者。他们 ONIN() 方法可能稍后运行,导致这些属性最终以视图状态结束。如果控件的初始化无法在 ONIN() 设置 EnableViewState="false" 可以用作解决方法。

    每次我的viewstate意外增长时,我都会使用“viewstate decoder 2.2”应用程序来找出在viewstate中到底发生了什么。通常,数据不需要存在。

    最后一句话:

    视图状态不用于重新填充窗体!! 这些值已随PostData一起提交。

        6
  •  1
  •   Seb Nilsson    12 年前

    同样,在对此进行了一些研究之后,我在一篇关于 Compressing View State .

    要保存压缩视图状态,我执行了以下操作:

    protected override void SavePageStateToPersistenceMedium(object state) {
        SaveCompressedPageState(state);
    }
    
    private void SaveCompressedPageState(object state) {
        byte[] viewStateBytes;
        using(MemoryStream stream = new MemoryStream()) {
            ObjectStateFormatter formatter = new ObjectStateFormatter();
            formatter.Serialize(stream, state);
            viewStateBytes = stream.ToArray();
        }
    
        byte[] compressed = CompressionHelper.Compress(viewStateBytes);
        string compressedBase64 = Convert.ToBase64String(compressed);
    
        ClientScript.RegisterHiddenField(ViewStateFieldName, compressedBase64);
    }
    

    对于加载部分,这段代码使它对我起作用:

    protected override object LoadPageStateFromPersistenceMedium() {
        return LoadCompressedPageState();
    }
    
    private object LoadCompressedPageState() {
        string viewState = Request.Form[ViewStateFieldName];
        if(string.IsNullOrEmpty(viewState)) {
            return string.Empty;
        }
    
        byte[] decompressed = CompressionHelper.Decompress(viewState);
        string decompressedBase64 = Convert.ToBase64String(decompressed);
    
        ObjectStateFormatter formatter = new ObjectStateFormatter();
        return formatter.Deserialize(decompressedBase64);
    }
    
        7
  •  0
  •   kemiller2002    15 年前

    最小化视图状态的最佳方法就是不要使用它。它将使您进行一些额外的工作编程(在回发时重新填充控制值等,但它将为您节省发送到浏览器的信息量)。你不能篡改它。

    以下是到msdn上视图状态的链接:

    http://msdn.microsoft.com/en-us/library/ms972976.aspx

    下面是一个描述一些最佳实践的链接:

    http://mnairooz.blogspot.com/2007/01/aspnet-20-viewstate-and-good-practices.html

    还有一个关于禁用视图状态:

    http://www.codeproject.com/KB/aspnet/ASPNET_Best_Practices.aspx

        8
  •  0
  •   Matloob Ali    13 年前

    压缩视图状态在某些情况下失败: -如果使用的是第页的更新面板,请不要使用压缩模式。 -如果您以某种方式更改了返回代码导致的视图状态,请不要使用压缩模式,因为这不会在返回后反映正确的视图状态。

    推荐文章