简体   繁体   中英

Why can't I see any data on HtmlTables even with runat=server enabled?

I have two HTML tables, the first one is populated on the server side through entries in the database, and the second is populated through client-side Javascript that allows the user to dynamically add rows and enter in data through input text boxes.

A button at the end of my form is responsible for committing the data from both to a SQL Server back end. The issue is on postback I am not able to read from these tables. This is the case for the client-side managed table, as well as the server sided managed table.

<table style="display: none; width: 100%" runat="server" id="tblWebOrderArbitraryContacts" class="borderBottomStyle">
                                            <table runat="server" id="recipientTable" style="display: block; width: 100%" class="borderBottomStyle"></table>



//the problem is the row count is always zero, regardless of what data is in it

if(tblWebOrderArbitraryContacts.Rows != null && tblWebOrderArbitraryContacts.Rows.Count > 0)
            {
                //go through automatically derived (from integrations) contacts
                foreach (HtmlTableRow row in tblWebOrderArbitraryContacts.Rows)
                {
...

Explanation

The issue is that when a request is sent to the server for that page, a new instance of the page is created, along with all of the controls as defined within your .aspx file. This new instance of the page and child controls start out with no data.

When you submit a "post" request back to the server (a "Postback"), the page looks at the request's form collection (the data from <input> tags submitted by the browser) and attempts to update the web controls on the page with the data found within that form collection.

Also, but beside the point, viewstate aware controls may attempt to populate themselves based on data found in viewstate left behind by a different instance of the same control from a previous request.

Specifically, if you look at the TextBox webcontrol, you can see that it implements the IPostBackDataHandler interface. What happens is that during the beginning of the request, the page looks at all of the values in the form collection submitted by the request. When the page locates a value in the form collection whose key matches the ID of a TextBox control, the page is able to apply that updated value to that TextBox control using the LoadPostData method of the IPostBackDataHandler interface.

It sounds like what you're doing is add several rows of data to a table and post them all back to the server at one time. You can do this, but the problem is that there are no controls on your page that can act as targets for that data. Specifically, you need to be assigning the name attribute of your <input> tags in order for the data to be submitted to the server, but what would you put as the value of the name attribute? It's not going to match up to a control on your page. Furthermore, if you are submitting multiple rows at once, how would you distinguish one from the other?

Possible Solution

Assuming that your page, after javascript manipulation and user input, looks something like this:

<table>
  <thead><tr></th>First Name</th><th>Last Name</th></tr></thead>
  <tbody>
    <tr><td><input name="FirstName[0]" value="John" /></td><td><input name="LastName[0]" value="Smith" /></td></tr>
    <tr><td><input name="FirstName[1]" value="Jane" /></td><td><input name="LastName[1]" value="Doe" /></td></tr>
    <tr><td><input name="FirstName[2]" value="Spider" /></td><td><input name="LastName[2]" value="Man" /></td></tr>
  </tbody>
</table>

In your code-behind during the postback you can access that data using code such as the following:

string firstName = Request.Form["FirstName[0]"];
string lastName = Request.Form["LastName[0]"];

You could also do something like this:

int index = 0;
bool dataFound;
do
{
  dataFound = false;

  string firstName = Request.Form["FirstName["+index+"]"];
  if (firstName != null)
    dataFound = true;

  string lastName = Request.Form["LastName["+index+"]"];
  if (lastName != null)
    dataFound = true;

  // do something with firstName and lastName ...

  index++;
} while (dataFound);

I believe the issue with your client side changes is that your table is not adding anything to the form's post data. You are manipulating the markup on the client but the markup itself is not what posts back, just the input elements and their values are posted. Try adding a hidden input and recording the client side changes there so that the data gets posted back to the server. Then on the server side you can parse the contents of the input field to determine what changes were made.

I suspect that you have a similar issue with your table that is populated through server side code. If you are not storing a record of your changes to the declared markup somewhere (viewstate, session, etc.) then the server has no idea what was generated by the previous request and falls back on the declared markup.

Look at some of the articles about declaring controls dynamically for a deeper explanation. http://www.4guysfromrolla.com/articles/081402-1.aspx#postadlink give a pretty good look into what is happening though the techniques and examples used are a bit dated.

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