簡體   English   中英

回發時,Viewstate為null

[英]Viewstate is null on postback

是的,我在這里有一些非常特別的東西......

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

我真的很遺憾可能是什么問題。 有任何想法嗎?

首先我錯了,有問題的代碼不是在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”,則使用來自qs的數據正確填充ListView,但是當單擊刪除按鈕時會拋出NullReferenceException,因為ViewState沒有持久化QuickShopBag對象。

但是,如果您單擊“添加”按鈕,您可以看到向QuickShopBagInstance(和ViewState)添加相同的值,ListView將正確填充,當您單擊“刪除”按鈕時,它將完美地工作,因為ViewState已被持久化。

現在,如果您將查詢字符串位讀取更改為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個項目)並更新按鈕的文本。

合乎邏輯的解釋是,其他地方還會發生其他事情,或者您未能提供額外的重要信息。

快速說明一下。 如果要在page_load上設置ViewState值,請確保將其包裝在其中

if (!IsPostBack)
{

ViewState["MyValue"] = MyValue // set dynamically with appropriate code

}

如果你不這樣做並且你做回發...但你的代碼設置這個ViewState值不在 !IsPostBack括號中,它會在你每次回發時將你的ViewState值重置為null,無論你在哪里啟用頁面上的ViewState。

這看起來很明顯,但如果你有很多代碼,很容易錯過。

或者我猜你不能使用!IsPostBack如果你想讓你的代碼在每次回發上運行。 但是如果你在回發時將值設置為null時遇到問題,請仔細檢查以上內容。

過去讓我絆倒的東西是

  1. 在頁面的ViewState中設置內容
  2. 然后嘗試在用戶控件中檢索它。 找不到它 - 哪里去了?

看起來每個頁面應該有一個ViewState,但每個usercontrol都保留它自己的版本。

可能是這樣的嗎?

這個SO鏈接給出了我剛才做的更好的解釋

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM