在.NET中使用AJAX和ViewState的行为不一致

我发现在我的浏览器上点击“刷新”按钮会暂时搞砸UpdatePanel内的控件的ViewState。

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

这种行为搞砸了我的webcontrol。 在我点击“刷新”之后,控件返回到其初始状态,因为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("

"); 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(); } } }

我只是重新阅读你的问题并意识到我错过了一些东西……

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

这是一个问题吗? 是!

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

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

有关此问题的讨论很丰富,你可以谷歌。

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

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

试试以下……

  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; } 

基本上从MSDN中的Control.LoadViewState方法和Control.SaveViewState方法派生上面的代码。

您的ViewState未被保存。 SaveViewState覆盖用于保存OBJECTS,而不是用于将东西放入ViewState包中。 ViewState包已经超出了肮脏的东西,你所做的改变将不会被持久化。 您需要创建一个对象数组来加载/查看ViewState信息。

做BlackMael所展示的。