locked
Dynamic controls have their data restored on a page refresh RRS feed

  • Question

  • User-1982395779 posted

    Re: VB.NET, framework 4.7.2
    I have a page where I create many dynamic checkbox & Textbox controls. Each control is named using a unique key. When the user enters some data and clicks a button to save the entered data, when the page refreshes, I repopulate the page from scratch, but, all of the controls where the user entered data (that have the same control ID) get repopulated with the data they entered, even though I explicitly populate the controls as unchecked (checkbox) or with empty strings (text boxes).

    I found a wacky solution where I append a random number to the end of the control ID, so the controls have different names, but I don't want to do this - I want to repopulate the page WITHOUT data.

    I've turned off viewstate for the page and the controls, but that didn't help.

    What's causing the page to get repopulated with data?

    Thursday, October 10, 2019 1:31 PM

Answers

  • User475983607 posted

    I'm not sure I understand what mechanism is causing the inputs to be bound to the controls. That article describes the opposite of what I'm seeing (  Why dynamically created controls disappear after a post back). 

    I guess what I need to understand is what causes this binding, and how do I disable it. Is there some kind of page directive? Is using a random number in the ID the only way?

    .NET binds the server controls to the parameter collection where the input parameter name matches the server control name.   Use HTML elements if you do not want this behavior.   Keep in mind, doing so will affect postbacks as the controls will not longer automatically bind when clicking a submit button.

    From my perspective, the test code works as expected.  If you post a form then click the browser's refresh button, the browser will prompt for a resubmit.  If you click yes, then the form us resubmitted.  This is the expected behavior.  If you want to stop the prompt then use the Post/Redirect/Get pattern.

    https://en.wikipedia.org/wiki/Post/Redirect/Get

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Sunday, October 13, 2019 3:34 PM

All replies

  • User475983607 posted

    What's causing the page to get repopulated with data?

    Dynamic controls are not members of the page class.  ASP.NET Web Forms have no record of dynamic controls and cannot maintain state.  You must have written code accomplish this or the browser cached the page.  

    Press ctrl-F5 ion the browser to reload the page.

    Thursday, October 10, 2019 1:39 PM
  • User-1982395779 posted

    mgebhard

    Dynamic controls are not members of the page class.  ASP.NET Web Forms have no record of dynamic controls and cannot maintain state.  You must have written code accomplish this or the browser cached the page.  

    Press ctrl-F5 ion the browser to reload the page.

    That makes sense - but I'm explicitly putting an empty string in all of the text boxes, yet the data still is being repopulated. It's happening with both IE11 and Chrome.

    Is there a way I can cause the browser not to cache this page?

    Thursday, October 10, 2019 1:51 PM
  • User475983607 posted

    Is there a way I can cause the browser not to cache this page?

    First, verify caching is the problem by pressing ctrl-F5 in the browser. 

    There's a lot of options when it comes to cache in .NET.  Cachng is documented at the following link. 

    https://docs.microsoft.com/en-us/dotnet/framework/performance/caching-in-net-framework-applications

    The page directive has options to control (turn off) caching in the current page.

    <%@ OutputCache Location="None" VaryByParam="None" %>

    Thursday, October 10, 2019 1:59 PM
  • User-1982395779 posted

    ctrl-f5 refreshes the page, but the data still comes back, so am I correct in assuming it's not the browser?

    If not, what would be causing the data to return?

    Thursday, October 10, 2019 2:18 PM
  • User475983607 posted

    If not, what would be causing the data to return?

    It must be your code.  

    Thursday, October 10, 2019 2:21 PM
  • User-1982395779 posted

    Thanks, but I don't think it's my code. The code is pretty simple - and when I create each control, I explicitly blank out the text boxes:

    txtData = New TextBox
    txtData.ID = "txtDollar_" & sUniqueKey
    txtData.Text = ""
     

    If I append a random number to the ID (e.g., txtData.ID = "txtData_" & sUniqueKey '& "_" & sRandomNumber) , the controls don't get re-populated, thus, I can't see how my code is doing it. There has to be something else going on.

    Thursday, October 10, 2019 2:32 PM
  • User475983607 posted

    BertSirkin

    Thanks, but I don't think it's my code. The code is pretty simple - and when I create each control, I explicitly blank out the text boxes:

    txtData = New TextBox
    txtData.ID = "txtDollar_" & sUniqueKey
    txtData.Text = ""
     

    If I append a random number to the ID (e.g., txtData.ID = "txtData_" & sUniqueKey '& "_" & sRandomNumber) , the controls don't get re-populated, thus, I can't see how my code is doing it. There has to be something else going on.

    Well, the problem can't be ASP.NET Web Forms because ViewState is persisted over post backs not between HTTP GET.  Pressing ctrl-F5 in your browser causes the browser to HTTP GET from the server.

    It must be your code.  Perhaps you are using Session or some other form of state management?  Keep in mind that we cannot see your code so it is up to you to figure out what's going on.  Try using the Visual Studio debugger and set a break point within each event handler.  This could be a bug related to the page life cycle where the code is setting values after the following block executes.

    txtData = New TextBox
    txtData.ID = "txtDollar_" & sUniqueKey
    txtData.Text = ""

    Thursday, October 10, 2019 2:54 PM
  • User-1982395779 posted

    Thanks, I understand what you're saying, but I've set breakpoints and interrogated the control values over and over. They're always blank when leaving the code-behind, but somehow when the page refreshes, the data is back.

    I've been writing/debugging code in the same VS project in my current job for 14 years now, and this is the first time I've seen anything like this. 

    Thursday, October 10, 2019 3:01 PM
  • User288213138 posted

    Hi BertSirkin,

    BertSirkin

    but somehow when the page refreshes, the data is back

    I agree with mgebhard's point of view. It should be your code.

    please post your aspx and aspx.cs code, I will help you to find out where the problem is.

    Best regards,

    Sam

    Friday, October 11, 2019 7:00 AM
  • User-1982395779 posted

    OK, I've removed any extraneous code - here's both what's in the ASPX page along with the code-behind. There are many rows of data displayed on the page (up to 100), and there is one check-box and 3 text boxes for each row. 

    This code includes the random number that I'm appending to each dynamic control id - this prevents the data from getting restored when the page reloads - if the random number is removed, the data will be restored.

    I've also created a second (different) page, which also has dynamic controls, and it is also restoring the data, unless I append a random number to the control IDs.

    Appreciate any help!!

    ----------------------------------------------------------
    ASPX page
    ----------------------------------------------------------

    <%@ Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/B2Standard.Master" EnableViewState="false" CodeBehind="ProjectCostCodes.aspx.vb" Inherits="Belsuite2.ProjectCostCodes" %>
    
    <asp:Panel ID="pnlData" runat="server" HorizontalAlign="Center" Width="100%">
        <table style="border: none; margin-left: auto; margin-right: auto; vertical-align: top;">
            <tr>
              <td style="text-align: left; vertical-align: middle;">
                <asp:Table ID="tblData" runat="server"></asp:Table>
              </td>
            </tr>
          </table>
    </asp:Panel>
    
    

    ----------------------------------------------------------
    Code-behind
    ----------------------------------------------------------

    Option Explicit On
    Option Strict On
    Option Infer Off
    
    Public Class ProjectCostCodes
        Inherits System.Web.UI.Page
       
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
       	<some initiation stuff>
    
    
            If IsPostBack Then
    	    <if SAVE button was clicked, save data>
    
    	    <in a loop as there are multiple rows of data to save>
    		<Get data from Request.Form>
    		<Save data to database>
    	    <end loop>
            End If
    
    
            <get data from database>
            PopulateNewData(ds)
        End Sub
    
    
        Private Sub PopulateNewData(ds As DataSet)
            Dim tr As New TableRow
            Dim cl As New TableCell
    
            Dim txtCCN As TextBox
            Dim rfvCCN As RequiredFieldValidator
            Dim chk As CheckBox
    
            ' the random number is added to each control key so that Visual Studio doesn't repopulate it when the page is refreshed
            Dim sRandomNumber As String = Utils.GetRandomNumber()
    
            For Each dr As DataRow In ds.Tables(1).Rows
    	    <get data from record>
    
                tr = New TableRow
    
                cl = New TableCell
    
                chk = New CheckBox
                chk.ID = "chk_" & sCostCodePrefix & "_" & sRandomNumber
                chk.Checked = False
                chk.Text = ""
                cl.Controls.Add(chk)
                tr.Cells.Add(cl)
    
    
                cl = New TableCell
                txtCCN = New TextBox
                txtCCN.ID = "txtCCN_" & sCostCodePrefix & "_" & sRandomNumber
                txtCCN.Text = sCostCodeNumber
    
                rfvCCN = New RequiredFieldValidator
                rfvCCN.ControlToValidate = txtCCN.ID
                rfvCCN.ErrorMessage = "The Cost Code Number is required."
                rfvCCN.ID = "rfvCCN_" & sCostCodePrefix & "_" & sRandomNumber
                rfvCCN.SetFocusOnError = True
                rfvCCN.Text = "*"
    
                cl.Attributes.Add("style", "padding-left:7px;padding-right:7px;")
                cl.Controls.Add(txtCCN)
                cl.Controls.Add(rfvCCN)
                tr.Cells.Add(cl)
    
    
                tblNew.Rows.Add(tr)
            Next
        End Sub
    
    
    End Class
    
    
    
    
    
    

    Friday, October 11, 2019 1:19 PM
  • User-1982395779 posted

    There has to be a simple explanation for this! 

    Here's some simple "hello world" code that shows what's happening.

    When you run the app, if you type something into the textbox and click the "Save" button, the page posts, and the data entered into the textbox is repopulated into the textbox on the new page.

    But, If you add a random number to the textbox ID, the textbox will be blank after the page posts, as it should be.

    Webpage HTML:

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="TestApp2.WebForm1" %>
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <table style="border: none; margin-left: auto; margin-right: auto; vertical-align: top;">
                    <tr>
                        <td style="text-align: left; vertical-align: middle;">
                            <asp:Table ID="tblData" runat="server"></asp:Table><br />
                            <asp:Button ID="btnSave" runat="server" Text="Save" />
                        </td>
                    </tr>
                </table>
            </div>
        </form>
    </body>
    </html>
    

    Code-behind:

    Public Class WebForm1
        Inherits System.Web.UI.Page
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            PopulateData()
        End Sub
    
        Private Sub PopulateData()
            Dim tr As New TableRow
            Dim cl As New TableCell
            Dim txt As TextBox
    
            ' the random number is added to each control key so that Visual Studio doesn't repopulate it when the page is refreshed
            Dim sRandomNumber As String = Convert.ToString(CInt(Rnd() * 1000) + 1)
            'Dim sRandomNumber As String = ""
    
            tr = New TableRow
            cl = New TableCell
            cl = New TableCell
            txt = New TextBox
            txt.ID = "txt_123" & sRandomNumber
            txt.Text = ""
            cl.Controls.Add(txt)
            tr.Cells.Add(cl)
            tblData.Rows.Add(tr)
        End Sub
    End Class
    

    There has to be a simple explanation for this!  Why is the data entered in the textbox showing up again after the page posts?

    Sunday, October 13, 2019 1:03 AM
  • User475983607 posted

    Creating control in Page_Load or Page_Init allows the framework to bind the inputs to the controls.  This is a well documented and well know behavior on the forums but usually forum members have the opposite issue where state is not maintained because the controls are recreated in an event other than Page_Init or Page_Load.

    Sunday, October 13, 2019 12:11 PM
  • User-1982395779 posted

    Creating control in Page_Load or Page_Init allows the framework to bind the inputs to the controls.  This is a well documented and well know behavior on the forums but usually forum members have the opposite issue where state is not maintained because the controls are recreated in an event other than Page_Init or Page_Load.

    I'm not sure I understand what mechanism is causing the inputs to be bound to the controls. That article describes the opposite of what I'm seeing (  Why dynamically created controls disappear after a post back). 

    I guess what I need to understand is what causes this binding, and how do I disable it. Is there some kind of page directive? Is using a random number in the ID the only way?

    thanks,

    bert

    Sunday, October 13, 2019 3:01 PM
  • User475983607 posted

    I'm not sure I understand what mechanism is causing the inputs to be bound to the controls. That article describes the opposite of what I'm seeing (  Why dynamically created controls disappear after a post back). 

    I guess what I need to understand is what causes this binding, and how do I disable it. Is there some kind of page directive? Is using a random number in the ID the only way?

    .NET binds the server controls to the parameter collection where the input parameter name matches the server control name.   Use HTML elements if you do not want this behavior.   Keep in mind, doing so will affect postbacks as the controls will not longer automatically bind when clicking a submit button.

    From my perspective, the test code works as expected.  If you post a form then click the browser's refresh button, the browser will prompt for a resubmit.  If you click yes, then the form us resubmitted.  This is the expected behavior.  If you want to stop the prompt then use the Post/Redirect/Get pattern.

    https://en.wikipedia.org/wiki/Post/Redirect/Get

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Sunday, October 13, 2019 3:34 PM