ASP.NET:压缩ViewState

时间:2010-03-04 14:44:16

标签: asp.net compression viewstate webforms

压缩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 个答案:

答案 0 :(得分:8)

简单的答案可能不是你想听到的。通常,当页面上的控件确实不需要时,它们默认具有viewstate。关闭viewstate是个好主意,直​​到你知道你将需要它为止,并且只为那些你希望保持视图状态的(希望)情况打开它。

答案 1 :(得分:8)

  1. 避免使用ViewState
  2. 在IIS服务器上使用压缩。
  3. 您可以通过执行以下操作来连接将视图状态压入和缩小页面的内容:
  4. 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 ) );
        }
    }
    

答案 2 :(得分:6)

我意识到这是一个旧线程,但我们已经使用Telerik的RadCompression HttpModule一段时间了,它在压缩ViewState,AJAX和Web Service响应方面效果非常好。您还可以在会话中作弊并保存ViewState - 适用于低流量站点。

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

答案 3 :(得分:1)

Seb,ViewState已经被压缩了...这就是你所看到的...你的控件的压缩版本。如果您想减少开销,那么不要使用viewstate:)

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

答案 4 :(得分:1)

这是您发布的视图状态的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>

基本上只是一些想知道他们存在的无线电按钮。 (如果未检查,浏览器不会发送带有postdata的<input type="radio">字段。这已经非常小了。

它可能通过挂载加载/保存方法或HTTP模块来压缩,但这可能不太实际也不是真正需要。


如果您的真实应用中的视图状态更大,请避免在视图状态中获取对象。这可以通过初始化OnInit()Page_Init()方法中的控件而非默认Page_Load()来实现。

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

快速摘要:

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

一个例外:

如果控件动态添加到控件树中,它会起到追赶作用。他们的OnInit()方法可能会在稍后运行,导致这些属性最终在视图状态中结束。如果在OnInit()中无法进行控件的初始化,则可以使用EnableViewState="false"设置作为解决方法。

每次我的观点状态出乎意料地增长时,我都会使用“ViewState Decoder 2.2”应用程序找出最终在viewstate中出现的内容。通常情况下,数据不需要存在。

最后一句话:

视图状态不用于重新填充表单!! 这些值已经与postdata一起提交。

答案 5 :(得分:1)

再次,经过一些研究,我在一篇关于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);
}

答案 6 :(得分:1)

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

答案 7 :(得分:0)

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

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

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

以下是描述一些最佳做法的链接:

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

一个关于禁用ViewState的内容:

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