简体   繁体   中英

ASP.NET issue when removing Control on Page Load

I have following Index.aspx web form:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="ProblematicWebApplication.Index" %>

<!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>
    <asp:Label ID="dummyLabel" runat="server" Text="This is dummy label." />
    <form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="intDropDownList" runat="server"/>
        <br />
        <asp:Button Text="Submit" OnClick="OnSubmitClicked" runat="server"/>
        <br />
        Selected value: <asp:Label ID="selectedValueLabel" runat="server" />
    </div>
    </form>
</body>
</html>

And following code behind Index.aspx.cs file:

using System;
using System.Linq;

namespace ProblematicWebApplication
{
    public partial class Index : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                this.intDropDownList.DataSource = Enumerable.Range(0, 11).ToArray();
                this.intDropDownList.DataBind();
            }

            if (this.Request["remove-dummy"] != null)
                this.Controls.Remove(this.dummyLabel);
        }

        protected void OnSubmitClicked(object sender, EventArgs e)
        {
            this.selectedValueLabel.Text = this.intDropDownList.SelectedValue;
        }
    }
}

When I run my application with no remove-dummy parameter in query string and select some value from intDropDownList and click Submit button, selected value is accordingly presented in selectedValueLabel.

But if I run my application with remove-dummy=1 parameter in query string, dummyLabel gets removed. Now when I select some value from intDropDownList and click Submit button, selected value is not correctly written to selectedValueLabel and all items from intDropDownList are removed.

Can someone explain it to me why this is happening? Why removing unrelated dummyLabel control has influence on intDropDownList control?

Hmm, seems odd. I got it to work by moving your code that removes the control into the Page's PreInit event:

protected void Page_PreInit(object sender, EventArgs e)
{
    if (this.Request["remove-dummy"] != null)
    {
        this.Controls.Remove(this.dummyLabel);
    }
}

It seems that ViewState loading fails in postback after dummyLabel is removed in previous page load.

Details:

first study following articles:

Following image shows important ASP.NET page events and where in between ViewState handling takes place.

ASP.NET Page事件和ViewState处理

So what happens when declarative Control dummyLabel is removed? Here is a process:

  1. Page is requested for the first time with query string parameter remove-dummy=1.
  2. In Page_Load event declarative Control dummyLabel is removed.
  3. Before SaveStateComplete event, ViewState is saved. There is no control dummyLabel in control tree, so its ViewState won't be saved.
  4. Submit button is clicked.
  5. Between InitComplete and PreLoad events, ViewState gets loaded. This is where it breaks because control tree now contains dummyLabel (dummyLabel gets removed after, in Load event) and ASP.NET fails in recursively loading ViewState into Page control tree . My assumption is that ViewState and Page control tree are tightly coupled and recursive ViewState loading fails as a consequence of this tight coupling.

One more situation that backs-up this theory: if you place dummyLabel at the very end of the page, issue doesn't happen anymore, because all other controls in Page control tree that come before dummyLabel already picked correct values from ViewState (ViewState structure and Page control tree are tightly coupled). If there were more controls after dummyLabel, their ViewState loading would fail.

To resolve this issue, all declarative Controls (defined in ASPX file) that should be removed, must be removed before ViewState loading takes place - in InitComplete event or any other event before it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM