Embedding Forms in a GridView


I have an ASP.NET 2.0 page with a GridView on it, populated programmatically from the code-behind.

Each GridView row displays a unique object. I'd like each row of the GridView to have it's own little form that submits to another page, where a user can edit the object.

To accomplish this, I've inserted the following code into one of the template fields:

                    <form id="frmEditObject<%# Eval("ObjectID") %>" action="editObject.aspx" method="POST">
                    <input type="hidden" name="ObjectID" value="<%# Eval("ObjectID") %>" />
                    <a href="javascript: document.forms['frmEditObject<%# Eval("ObjectID") %>'].submit();" class="edit">EDIT</a>

This works great, EXCEPT for two things:

First, the first row's EDIT button throws the following JavaScript error:

Error: 'document.forms.frmEditObject1' is null or not an object.

I know its there because I can see it in the page source after the page loads.

Second, I have a custom footer with alphabet letters A - Z that allow the user to display only objects of one letter at a time. Like, they click on A and see Apple, Airplane, Angle, Aurora, etc. These links BREAK when I add form code to the GridView rows, and when you click on them, they throw this error:

Invalid postback or callback argument.  Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page.  For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them.  If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.

Here's what I think: I think that the form code I've inserted into the rows is interfering with the parent ASP.NET page form. So, when the page gets to the first row, it's already seen <form name="aspnetForm"> and now it's seeing <form id="frmEditObject1"> and it's getting confused. Then, it sees the </form> in my first row, and afterwards everything is fine (all the subsequent rows work), but, this breaks the aspnetForm, and so my alphabet links at the bottom, which are postbacks, also break.

Whew, long post.

Anyhow, what's the solution for this problem? Is it even correct to embed HTML forms in a GridView, or is there a different way I should be doing this?
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

>>Is it even correct to embed HTML forms in a GridView, or is there a different way I should be doing this?
No, not really.  the ASP.Net model allows for one form with runat=server tag...and it's all you should really need...

what is your dynamic form doing?
                    <form id="frmEditObject<%# Eval("ObjectID") %>" action="editObject.aspx" method="POST">
                    <input type="hidden" name="ObjectID" value="<%# Eval("ObjectID") %>" />

does editObject.aspx do some processing based on the ObjectID?
Why can't you just do the processing on the same page?
CMES-ITAuthor Commented:
The form should take the user to the editObject.aspx page that I've already created. This GridView only displays some basic info - Object Name, Object ID, etc. the editObject.aspx page allows the user to edit all of the objects' properties, about 50. There are multiple ways to get to the editObject.aspx page, and it's already somewhat complicated itself, so I don't want to embed all of it's functionality in this GridView page.

What I want is a list of the objects, each in a row, with basic information, and a button that says "Edit" and goes to the edit page, passing the ObjectID, which doesn't seem like it should be a big deal. I don't really care how I accomplish that functionality, as long as the two pages stay separate, so if there's a better way than embedding forms, please let me know.
>>What I want is a list of the objects, each in a row, with basic information, and a button that says "Edit" and goes to the edit page, passing the ObjectID

How does the editObject.aspx page catch the ObjectID variable?
querystring, session, request("ObjectID") etc...
Build an E-Commerce Site with Angular 5

Learn how to build an E-Commerce site with Angular 5, a JavaScript framework used by developers to build web, desktop, and mobile applications.

CMES-ITAuthor Commented:
It does a Request("ObjectID").

CMES-ITAuthor Commented:
I can use a built-in object, and use the PostBackURL behavior to change where the form goes, but then I don't know a good way to get the ObjectID to the new page.

For instance:

            <asp:TemplateField HeaderText="&#160;">
                    <asp:LinkButton ID="btnChooseObject" runat="server" CssClass="edit" PostBackUrl="editObject.aspx">EDIT</asp:LinkButton>
                    <input type="hidden" name="ObjectID" value="<%# Eval("ObjectID") %>" />

That would work fine, except that it doesn't have a way of posting a unique ObjectID to the editObject.aspx page. For instance, if there are 5 objects in the GridView, with IDs from 1 to 5, the value of the hidden ObjectID field posted to the editObject.aspx page will be "1,2,3,4,5" instead of a single value.

If we could overcome that hurdle, then I could work within the constraints of the single-form model.
CMES-ITAuthor Commented:
For instance, one solution to that might be to have a radio button for each GridView row, and then put a "Submit" button at the bottom of the page, but that adds an extra click to everything.

Another solution might be to make the Edit button be a link, where the objectID is passed via the Query String. But that's a little less secure, and a lot less elegant.

I know there needs to be a way to do this with a single form-based button. I'm just too new to .NET to know the solution.
sorry...I haven't had time to work up an example for you...but this can be done using a linkbutton in your templatefield instead of the "forms"...the linkbutton renders as an html link, but it gives you codebehind access "onclick" event to which, you would do a server.transfer to your editObject.aspx page.
Using server.transfer retains the variables on the gridview page and passes the same variables to the edit page...which lets you continue using request("...")
also..your objectid (if it is a primary key from the database) you can use the datakey property to pass the value...
sorry...all that might not make sense...lol...but maybe it's enough keywords for you to look into until I can work up a basic example?
google things like:
"gridview linkbutton"
"asp.net server.transfer"
"gridview datakeys"

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
CMES-ITAuthor Commented:
I've solved this in a much easier manner than all that. It's not the most elegant... but it works.

Here's what I did:

At the top of the form, I added this:

    <input type="hidden" name="ObjectID" value="" />
    <asp:LinkButton ID="lbRedirect" runat="server" PostBackUrl="editObject.aspx" />

For the Edit Button field, in the GridView, I have this:

            <asp:TemplateField HeaderText="&#160;" >
                    &nbsp;<a href="javascript: editObject(<%# Eval("ObjectID") %>);" class="edit">EDIT</a>

Then, I added this JavaScript at the bottom of the page:
    <script language="JavaScript" type="text/javascript">
        function editObject(intObjectID) {
            theForm.ObjectID.value = intObjectID;
            WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions('lbRedirect', '', false, '', 'editObject.aspx', false, true));
    // -->

I started with having the LinkButton be in the GridView, and then trying to have the JavaScript trigger the LinkButton using the Click() command, but for some reason, I couldn't get JavaScript to find it via getElementById or otherwise. So, I just looked in the code to see the structure of Microsoft's PostBack code, and added it to my JavaScript code. I tried to do the whole thing without the LinkButton, but that object is required for some reason, and even though I'm not using it, it has to be on the page for the PostBack to work.

I'm closing this out, but I'll give you the points for helping me.

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.