Viewstate压缩问题

时间:2009-04-06 13:47:52

标签: asp.net compression viewstate

我目前正在与.NET Viewstate斗争,它开始让我疲惫不堪。发现我们的一个应用程序中的某些页面由大约80%的viewstate组成,我已经考虑尽可能地减少这些。

我已经看过(并且很满意)禁用viewstate以获取不需要它的控件(标签,按钮等)并且在这里取得了一些小的收益。

我现在正在查看视图状态压缩,虽然我可以证明其大小减少了40-50%,但它似乎与我的应用程序不一致。

方案: 页面包含一些下拉列表,一个按钮和一个Grdiview(因此需要处理ViewState!)。页面加载时,将填充DDL并进行默认选择。按OK按钮将导致Gridview按预期填充。

现在问题:启用Viewstate压缩后,如果用户在单击“确定”按钮之前更改DDL中的选定项目,则会收到“必填字段验证程序”错误,指示尚未在其中一个DDL中进行选择- 但这种情况并非如此!禁用压缩代码可以解决问题,并且页面按预期运行(即数月!)。

问题可能归结为现在存储在__VIEWSTATE以外的密钥中的视图状态[我见过的代码使用了不同的密钥名称 - 例如VSTATE。)

我的网页来源如下;

带压缩的页面源(请注意空的__VIEWSTATE键):

<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__LASTFOCUS" id="__LASTFOCUS" value="" />
<input type="hidden" name="__VSTATE" id="__VSTATE" value="H4sIAAAAAEAO29B2AcSZYlJ
.
.
MKd2afqdaImFR5UiFXVyQPwLPA//8xt+pMsSQ8vlOklcoNgmZfJd8hHvk6/S/7UbxxAJTjzZfp6Qcm039
h3d3dvvPO7/Oa/7i57uemj1H2a/gw5lJQ+ySjFRtPZUL7A/3o2ImFR5UiFXVyLPA+38At70F1EkwAAA=" />
<input type="hidden" name="__VIEWSTATE" id="
__VIEWSTATE" value="" />
</div>

没有压缩的网页来源:

<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__LASTFOCUS" id="__LASTFOCUS" value="" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTYxOTM1NDg4N
A9kFgJmD2QWAgIDD2QWAgIFD2QWAmYPZBYKAgEPZBYIAgcPZBYCAgMPDxYCHgRUZXh0BRdEYXduQyBbY2hhbm
dlIHBhc3N3b3JkXWRkAgkPFgIeB1Zpc2libGVoFgQCAQ8PFgIfAAUFQWRtaW5kZAIDDw8WAh8ABQUxNDoyNGR
.
.
.
.
.
.
kAgsPDxYEHwAFWVNlbGVjdGVkIFNlcnZpY2UgVXNlcjogPGEgY2xhc3M9J3N1U2VsZWN0b3InIGhyZWY9J2xp
c3RzZXJ2aWNldXNlcnMuYXNweCc+PGI+bm9uZTwvYj48L2E+HwFoZGQCDw8QZGQWAGQCBQ8UKwADZDwrABQEA
BYSHg9QYXJlbnRJdGVtQ2xhc3MFC2lnbW5fUGFyZW50HhdUb3BMZXZlbFBhcmVudEl0ZW1DbGFzcwUTaWdtbl
Ub3BFBhcmVudB4KSlNGaWxlTmFtZWUeFlRvcExldmVsSG92ZXJJdGVtQ2xhc3MFNGlnbW5fVG9wTGV"     
/>
</div>

.NET如何知道VIEWSTATE的存储位置,是否知道我已将其移动了?

除了实现SavePageStateToPersistenceMedium和LoadPageStateFromPersistenceMedium之外,我是否需要对我的代码进行任何其他更改?

6 个答案:

答案 0 :(得分:3)

嘿viewstate压缩对我没有任何问题。基本上我有一个使用viewstate的所有aspx页面的基类。即使我使用不同的viewstate键来保存我的viewstate。但是你必须为此重写2个方法:

1) - 保存视图状态 2) - 加载viewstate

只要你这样做,你应该没有问题。看下面我用于我的基类的代码

using System;
using System.IO;
using System.Web.UI;

namespace XC.UI.WebForms
{

    public class PageBase : System.Web.UI.Page
    {

        protected override object LoadPageStateFromPersistenceMedium()
        {
            string viewState = Request.Form["__VSTATE"];
            byte[] bytes = Convert.FromBase64String(viewState);
            bytes = XC.Common.ViewStateHelper.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 = XC.Common.ViewStateHelper.Compress(bytes);
            ClientScript.RegisterHiddenField("__VSTATE", Convert.ToBase64String(bytes));
        }

    }

}

答案 1 :(得分:3)

如果您在页面中使用ajax,请更改此行代码。它会解决你的问题。 ClientScript.RegisterHiddenField(“__ VSTATE”,Convert.ToBase64String(bytes)); 用ScriptManager替换上面的语句。 ScriptManager.RegisterHiddenField(this,“__ VSTATE”,Convert.ToBase64String(bytes));

答案 2 :(得分:2)

.NET中有一个常量隐藏视图状态字段名称。我们通过挂钩您描述的方法进行压缩,但保持视图状态名称相同而没有问题。

答案 3 :(得分:1)

这可能有点矫枉过正,但www.strangeloop.net上有一个非常酷的硬件解决方案来解决这个问题。没有任何关系,只是对这项技术印象深刻。

回到页面 - 什么样的控件生成所有这个viewstate?网格?你已经表明你已经过了这个,但是要注意那些设置了runat =“server”的表,td,tr,div等的'不必要的runats'。这些控件的全部内容在viewstate中保持不变。我们最近通过识别div是客户端并且不需要runat =“server”来削减我们的viewstate有效负载40%的折扣。

答案 4 :(得分:1)

压缩对我来说不起作用,因为它降低了40%。我有200-300KB的ViewStates,并且大大降低了应用程序的性能。

我写了一些viewstate替换技术,用页面上的GUID标记替换它,并将服务器本身的实际数据保存在数据库中。

这是代码和技术。

http://ashishnangla.com/2011/07/21/reducing-size-of-viewstate-in-asp-net-webforms-by-writing-a-custom-viewstate-provider-pagestatepersister-part-12/

答案 5 :(得分:0)

以下答案不是我的,而是OP(包含在问题中)。我将其移出问题并将其作为社区维基。


我已经深究了这一点 - 差不多,我有它的工作!出于某种原因,使用ClientScript.RegisterHiddenField方法似乎是问题的根源。修改代码以利用基类保存方法,即base.SavePageStateToPersistenceMedium(compressedBytes)并处理base.LoadPageStateFromPersistenceMedium()返回的Pair对象,我现在有了一个可行的解决方案。测试显示测试页面减少了70%,所以我很满意。

现在我已经进行压缩工作了,我需要建议下一个(第一个正确的)Code Review重点关注删除不需要它的viewstate。