【问题标题】:Inconsistent behavior with AJAX and ViewState in .NET.NET 中 AJAX 和 ViewState 的行为不一致
【发布时间】:2008-12-09 20:50:02
【问题描述】:

我发现点击浏览器上的“刷新”按钮会暂时破坏 UpdatePanel 中控件的 ViewState。

这是我的情况:我制作了一个自定义 WebControl,将值存储在 ViewState 中。我将此控件放在 UpdatePanel 中。当我点击浏览器上的“刷新”按钮时,它会暂时清除 ViewState 中的值。然而,在下一次回发时,我点击“刷新”之前 ViewState 中的值神奇地重新出现。

这种行为搞砸了我的网络控制。在我点击“刷新”后,控件返回到其初始状态,因为 ViewState 为空且 IsPostBack 设置为 false。但是,当我单击 WebControl 中的一个回发控件时,WebControl 将使用与我点击“刷新”之前 ViewState 中相同的值重新加载。

奇怪的是,这只发生在我使用 AJAX 时。当我的控件在 UpdatePanel 之外时,Firefox 会给我它的标准消息,“要显示此页面,Firefox 必须发送将重复之前执行的任何操作(例如搜索或订单确认)的信息(重新发送)(取消) 。”这很好,因为至少行为是一致的。但是,我绝对必须为这个项目使用 AJAX。

所以这就是我想做的——我想让“刷新”行为保持一致。如果点击“刷新”完全不影响 ViewState,那将是最好的。但是,如果它必须清除 ViewState,那很好,只要 ViewState STAYS 清除即可。这些东西都没有价值消失和重新出现。

哦,是的,这是我的示例代码:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace TestControls
{
    public class TestControl : WebControl
    {
        int _clickCount;
        bool _mustUpdate;

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);

            _clickCount = ((int)ViewState["clickCount"]);
            _mustUpdate = ((bool)ViewState["mustUpdate"]);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            Controls.Clear();
            ControlCreator();
        }

        private void ControlCreator()
        {
            Label tempLabel = new Label();
            LiteralControl tempLiteral = new LiteralControl("<br/><br/>");
            LinkButton tempLink = new LinkButton();

            tempLink.ID = "testLink";
            tempLink.Text = "Click me!";
            tempLink.Click += new EventHandler(tempLink_Click);

            tempLabel.ID = "testLabel";
            tempLabel.Text = _clickCount.ToString();

            Controls.Add(tempLabel);
            Controls.Add(tempLiteral);
            Controls.Add(tempLink);
        }

        void tempLink_Click(object sender, EventArgs e)
        {
            _clickCount++;
            _mustUpdate = true;
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (_mustUpdate)
            {
                Controls.Clear();
                ControlCreator();

                _mustUpdate = false;
            }
        }

        protected override object SaveViewState()
        {
            ViewState["clickCount"] = _clickCount;
            ViewState["mustUpdate"] = _mustUpdate;

            return base.SaveViewState();
        }
    }
}

【问题讨论】:

  • 您的更新面板是否设置为条件刷新?您可能希望跟踪控件生命周期中的重要事件。正如您所说,当您使用更新面板时,问题就开始了。

标签: c# .net ajax updatepanel viewstate


【解决方案1】:

我刚刚重新阅读了您的问题,并意识到我错过了一些东西......

您正在点击浏览器刷新按钮!

这是个问题吗? 是的!

点击浏览器上的刷新按钮会发生什么? 它刷新当前页面。如果有回发,它会重新发送帖子数据。

就页面而言,AJAX 回调可能会更新 ViewState,但点击浏览器刷新按钮将重新发布旧的 ViewState。

有很多关于这件事的讨论,你可以谷歌。

一个非常简单的想法是也许将信息存储在会话状态中。当然,那也可能有它自己的问题。但它可能会实现您的近期目标。

擦除回发历史记录(以防止重新发布)的提示是再次重定向回同一页面。

【讨论】:

  • 实际上,我确实有最后一个问题 - 我明白为什么点击“刷新”会清除 Viewstate....但是为什么点击我的 LinkBut​​tons 会带回 ViewState 之前的值“刷新?”这才是真正令人费解的部分。
【解决方案2】:

试试下面...

    protected override void LoadViewState(object savedState)
    {
        if (savedState != null)
        {
            object[] myState = (object[])savedState;

            if (myState[0] != null) base.LoadViewState(myState[0]);
            if (myState[1] != null) _clickCount = ((int)myState[1]);
            if (myState[2] != null) _mustUpdate = ((bool)myState[2]);
        }
    }

    protected override object SaveViewState()
    {
        object[] allStates = new object[3];

        allStates[0] = base.SaveViewState();
        allStates[1] = _clickCount;
        allStates[2] = _mustUpdate;

        return allStates;
    }

上面的代码基本上是从Control.LoadViewState MethodControl.SaveViewState Method从MSDN推导出来的。

【讨论】:

    【解决方案3】:

    您的 ViewState 没有被保存。 SaveViewState 覆盖用于保存 OBJECTS,而不是用于将内容放入 ViewState 包中。 ViewState 包已经超出了将内容标记为脏的程度,并且您所做的更改将不会被保留。您需要创建一个对象数组来加载/查看 ViewState 信息。

    做 BlackMael 展示的事情。

    【讨论】:

      猜你喜欢
      • 2011-12-24
      • 1970-01-01
      • 1970-01-01
      • 2011-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多