回发时Viewstate为null

本文关键字:null Viewstate | 更新日期: 2023-09-27 18:16:32

好了,我这里有一些非常奇怪的事情…

ASP。. NET 4页,具有以下属性:

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

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

然而,当你在页面上执行回发时,当从回发Button_OnClick()事件访问时,ViewState是空的!

我已经检查了请求。表单,并确定_Viewstate值在那里并填充。我还通过解析器运行了这个值,它确实包含预期的数据,页面有ViewStateEnabled="true"和新的。net 4 ViewStateMode="Enabled"

我已经继续重写LoadViewState方法来检查它是否正在触发,它似乎没有。

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

我真的不知道是什么问题。什么好主意吗?

回发时Viewstate为null

首先我错了,有问题的代码不是在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没有持久化QuickShopBag对象。

但是如果你点击"添加"按钮,你可以看到添加相同的值到QuickShopBagInstance(和ViewState), ListView被正确填充,当你点击删除按钮时,它完美地工作,因为ViewState已经被持久化了。

现在,如果您将读取querystring位改为Page_InitComplete而不是Page_Init,它可以完美地工作。所以结论是……

你不能在Init_Complete!!!!!!!!之前添加视图状态

我真傻,至少是谁写的!

到目前为止,您似乎已经排除了大多数建议,因此我仅使用您提供的信息创建了一个基本页面:

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项),按钮的文本被更新。

合乎逻辑的解释应该是在别的地方发生了别的事情,或者你没有提供额外的重要信息。

我过去犯的错误是

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

看起来好像你应该有一个ViewState每个页面,但每个用户控制保持自己的版本。

会是这样吗?

这个SO链接提供了一个更好的解释,我刚刚做了

简单说一下。如果要在page_load上设置ViewState值,请确保将其包装在

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

如果你不这样做,你做一个回发…但是你的代码设置这个ViewState值是而不是IsPostBack括号中的,它会在每次回发时将你的ViewState值重置为null,无论你在页面的哪里启用ViewState。

这似乎是显而易见的,但是如果有很多代码在运行,很容易忽略它。

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