Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TemplateField button causing GridView Invalid Postback

Ok, so I've got a template field in a gridview that contains just a simple button...

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Administration.aspx.cs"     
Inherits="Administration" %>
<%@ Register TagPrefix="ajaxToolkit" Namespace="AjaxControlToolkit" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">    
    <title>Keywords Administration</title>
</head>
<body class="popupbody">
<form id="form1" runat="server">
    <ajaxToolkit:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server" EnablePartialRendering="true" CombineScripts="false"></ajaxToolkit:ToolkitScriptManager>

    <asp:Label ID="AddLabel" runat="server">Add a Keyword</asp:Label>
    <br />
    <asp:TextBox ID="AddTextBox" runat="server" />
    <asp:Button ID="AddButton" Text="Add" runat="server" OnClick="AddKeyword_Click" />

    <asp:GridView ID="KeywordsGridView" AllowPaging="false" AutoGenerateColumns="false" BackColor="white"
        GridLines="None" HeaderStyle-CssClass="Table_Header" RowStyle-CssClass="Table_Style" 
        OnRowDataBound="RowBound" runat="server">
        <Columns>
            <asp:TemplateField>
                <ItemTemplate>
                    <asp:Button runat="server" />
                </ItemTemplate>
            </asp:TemplateField>
            <asp:BoundField DataField="References" SortExpression="References" HeaderText="Total References" />
            <asp:BoundField DataField="Keyword" SortExpression="Keyword" HeaderText="Keyword" />
        </Columns>
    </asp:GridView>
</form>
</body>
</html>

Whenever I click the button I get the 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. 

I've found a decent amount of articles referencing this issue, including a couple on SO, for example...

Invalid postback or callback argument. Event validation is enabled using '<pages enableEventValidation="true"/>'

and...

Invalid postback or callback argument

I might just be misunderstanding, but as far as I can tell they don't really help me. How do I get this to go away without setting enableEventValidation="false"?

EDIT Posted all the code for my page.

like image 938
Carter Avatar asked Jun 03 '10 17:06

Carter


2 Answers

I know this post is old, but I also had this problem recently. After checking the how the code was generated for the asp:ButtonField and also for the asp:Button that I have added in an ItemTemplate I discovered quite a big difference:

asp:ButtonField: input type="button" onclick="javascript:__doPostBack('ctl00$ctl00$cphMain$cphContent$gvEmails','SendFromBatch$0')" value="Continue">

asp:Button: input id="ctl00_ctl00_cphMain_cphContent_gvEmails_ctl02_btnCont" type="submit" onclick="FreezeScreen('Emails are being sent...');" value="Continue" name="ctl00$ctl00$cphMain$cphContent$gvEmails$ctl02$btnCont">

The Type was the problem! So, after i changed the UseSubmitBehavior from "Submit" to "False" I did not get the error anymore.

EDIT: I recently wanted to change from the normal btns to imgBtns so that I can save some space and also make the gridview nicer :D. Of course I had the same problem popping up and the imagebtn does not have UseSubmitBehavior property, so I started looking after a solution.

Found the following (The code below is in a UserControl).

1) Bind in !IsPostBack

2) Register the usercontrol itself in the Render

and everything works just as planned - no validation errors.

    protected void Page_Load(object sender, EventArgs e)
    {
        OnLoadingEvent(new EventArgs());

        if (!Page.IsPostBack)
        {
            gvEmails.DataSource = odsEmails;
            try
            {
                gvEmails.DataBind();
            }
            catch (Exception)
            {
            }
        }

        if (!writeText) divWriteEmail.Visible = false;
    }

    protected override void Render(HtmlTextWriter writer)
    {
        Page.ClientScript.RegisterForEventValidation(this.UniqueID);

        base.Render(writer);
    }

EDIT: I was playing around with the code above and asked myself, what if you actually need to rebing your objectdatasource - what happens then? Well the code above will not work if you rebind in the page load, because the gridview will be rebound again when you click a btn in the gridview's row and it will not be recognized as being generated on the server. Fair and square, but how to avoid this behaviour? Well... i figured out a way, maybe not the best but it does the trick.

Actually, you do not want to rebind the gridview when you click a btn on the gv's row... but how do we know that since the page load method is first called? Well, actually i do not want to rebind the gridview if the select param of the object data source do not change. So, I keep the select param of the objectDataSource in the session view and I rebind my gridview only when one of them changes - this behaviour is only during the PageLoad event. In order to see latest rows i click refresh and get the latest rows with no problem and at the moment i click a gvRow btn, the error dissapears.

To make all of this happen you have to

  1. Directly call the .Select() of the object data source
  2. Catch the OnSelecting event from the datasource, save the select param set the e.Cancel = true
  3. Check if the select param are different and then bind the gridview and this time when catching the OnSelecting you have to set e.Cancel = false in order to retrieve the data from the DB - only one time.

Hope this helps!

like image 123
JJschk Avatar answered Nov 18 '22 16:11

JJschk


This fellow found a solution to a similar problem (scroll down to about the 4th comment), which was to set unique id's for the GridView buttons.

like image 43
DOK Avatar answered Nov 18 '22 17:11

DOK