【问题标题】:Viewstate is null on postbackViewstate 在回发时为空
【发布时间】:2023-04-02 06:50:01
【问题描述】:

对,我这里发生了一些非常奇怪的事情......

具有以下属性的 ASP.NET 4 页面:

protected QuickShopBag QuickShopBagInstance
{
    get { return (QuickShopBag)ViewState["QuickShopBag"]; }
    set { ViewState["QuickShopBag"] = value; }
}

在 (!Page.IsPostBack) 中的初始 Page_Load() 期间,QuickShopBagInstance 被填充,ViewState 被保存。

但是,当您在页面上执行回发时,从回发Button_OnClick() 事件访问时,ViewState 为空!!!

我检查了 Request.Form 并且确定_Viewstate 值在那里并且被填充。我还通过解析器运行了这个值,它确实包含预期的数据,页面有 ViewStateEnabled="true" 和新的 .NET 4 ViewStateMode="Enabled"

我已经着手重写 LoadViewState 方法以检查它是否正在触发,但似乎没有。

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

我真的不知道可能是什么问题。有什么想法吗?

【问题讨论】:

  • 您没有显示用于填充将内容放入视图状态的属性的逻辑。可能它在回发期间做错了
  • 假设 this.QuickShopBagInstance = new QuickShopBag() 在初始加载。我也已经说过,我已经验证了在回发时传递的视图状态数据,这是正确的。
  • 能否请您发布 QuickShopBag 类定义。真的不需要这些属性。
  • 别担心,QuickShopBag 被标记为 [Serializable],就像我说的返回的 viewstate 是有效的。

标签: c# asp.net webforms


【解决方案1】:

到目前为止,您似乎已经排除了大部分建议,因此我创建了一个基本页面,其中仅包含您在上面提供的信息:

namespace SO_Questions
{
    [Serializable()]
    public class QuickShopBag
    {
        public string MyProperty { get; set; }
    }
}

后面的代码

namespace SO_Questions
{
    public partial class TestPage : System.Web.UI.Page
    {
        protected QuickShopBag QuickShopBagInstance
        {
            get { return (QuickShopBag)ViewState["QuickShopBag"]; }
            set { ViewState["QuickShopBag"] = value; }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                this.QuickShopBagInstance = new QuickShopBag() { MyProperty = "Test String" };
            }
            Message.Text = "Value is: " + this.QuickShopBagInstance.MyProperty.ToString();
        }

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

        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            btnSubmit.Text += QuickShopBagInstance.MyProperty;
        }
    }
}

标记:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestPage.aspx.cs" Inherits="SO_Questions.TestPage" ViewStateMode="Enabled" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server"><title></title></head>
<body>
    <form id="form1" runat="server"><div>
        <asp:Label ID="Message" runat="server"></asp:Label>
        <asp:Button runat="server" ID="btnSubmit" Text="Submit" OnClick="btnSubmit_Click" />
    </div></form>
</body></html>

正如预期的那样,这运行正常;覆盖的 LoadViewState 方法被命中(并且 viewstate 正确包含 2 个项目)并且按钮的文本被更新。

合乎逻辑的解释是其他地方发生了其他事情,或者您未能提供额外的重要信息。

【讨论】:

    【解决方案2】:

    过去让我感到不安的事情是

    1. 在页面的 ViewState 中设置一些东西
    2. 然后尝试在用户控件中检索它。找不到 - 它去哪儿了?

    似乎每页应该有一个 ViewState,但每个用户控件都保留自己的版本。

    会是这样吗?

    这个SO link 给出了我刚刚做的更好的解释

    【讨论】:

      【解决方案3】:

      首先我弄错了,有问题的代码不在 Page_Load 中,而是在 Page_Init 中,尽管我没有读到任何说您不能在 Init 时分配给 ViewState 的内容。

      所以我整理了一个非常基本的测试来复制我遇到的问题......

      <form id="form1" runat="server">
      <div>
          <asp:ListView id="QuickshopListView" runat="server">
              <LayoutTemplate>
                  <asp:PlaceHolder ID="itemPlaceHolder" runat="server" />
              </LayoutTemplate>
              <ItemTemplate>
                  <asp:TextBox ID="txtItem" runat="server" Text='<%# Container.DataItem %>' />
                  <asp:Button ID="btnDelete" runat="server" Text="Delete" OnClick="btnDelete_Click" />
                  <br />
              </ItemTemplate>
          </asp:ListView>
          <asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="btnAdd_Click" />
      </div>
      </form>
      
      public partial class Quickshop : System.Web.UI.Page
      {
          protected QuickShopBag QuickShopBagInstance
          {
              get { return (QuickShopBag)ViewState["QuickShopBag"]; }
              set { ViewState["QuickShopBag"] = value; }
          }
      
          protected void Page_Init(object sender, EventArgs e)
          {
              if (!Page.IsPostBack)
              {
                  if (QuickShopBagInstance == null)
                      QuickShopBagInstance = new QuickShopBag();
      
                  if (!String.IsNullOrEmpty(Request.QueryString.ToString()))
                  {
                      string[] items = Server.UrlDecode(Request.QueryString.ToString()).Split(',');
                      if (items.Length > 0)
                      {
                          foreach (string item in items)
                          {
                              QuickShopBagInstance.QuickShopItems.Add(item);
                          }
                      }
                  }
              }
          }
      
          protected void Page_LoadComplete(object sender, EventArgs e)
          {
              QuickshopListView.DataSource = QuickShopBagInstance.QuickShopItems;
              QuickshopListView.DataBind();
          }
      
          protected void btnAdd_Click(object sender, EventArgs e)
          {
              if (QuickShopBagInstance == null)
                  QuickShopBagInstance = new QuickShopBag();
      
              QuickShopBagInstance.QuickShopItems.Add("add1");
              QuickShopBagInstance.QuickShopItems.Add("add2");
              QuickShopBagInstance.QuickShopItems.Add("add3");
          }
      
          protected void btnDelete_Click(object sender, EventArgs e)
          {
              Button DeleteButton = (Button)sender;
              ListViewDataItem item = (ListViewDataItem)DeleteButton.NamingContainer;
              QuickShopBagInstance.QuickShopItems.RemoveAt(item.DisplayIndex);
          }
      }
      
      [Serializable]
      public class QuickShopBag
      {
          public List<string> QuickShopItems { get; set; }
      
          public QuickShopBag()
          {
              this.QuickShopItems = new List<string>();
          }
      }
      

      如果您请求说“/quickshop.aspx?add1,add2,add3”,ListView 会正确填充来自 qs 的数据,但是当单击删除按钮时会抛出 NullReferenceException,因为 ViewState 没有t 持久化 QuickShopBag 对象。

      但是,如果您单击“添加”按钮,如您所见,该按钮会将相同的值添加到 QuickShopBagInstance(和 ViewState),ListView 会正确填充,并且当您单击删除按钮时,它会像 ViewState 一样完美运行被持久化了。

      现在,如果您将读取查询字符串位更改为 Page_InitComplete 而不是 Page_Init 它可以完美运行。所以结论是……

      您不能在 Init_Complete 之前添加到 VIEWSTATE !!!!!!!!!

      我真傻,至少是谁写的!

      【讨论】:

      【解决方案4】:

      只是一个简短的说明。如果要在 page_load 上设置 ViewState 值,请确保将其包裹在

      if (!IsPostBack)
      {
      
      ViewState["MyValue"] = MyValue // set dynamically with appropriate code
      
      }
      

      如果您不执行此操作并执行回发...但您设置此 ViewState 值的代码在 !IsPostBack 括号中是 not,它将每次将您的 ViewState 值重置为 null无论您在页面的哪个位置启用 ViewState,您都会进行回发。

      这可能看起来很明显,但如果你有很多代码,很容易错过。

      或者我猜你不能使用 !IsPostBack 如果你希望你的代码在每次回发时都运行。但是,如果您在回发时将值设置为 null 时遇到问题,请仔细检查上述内容。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多