I have read a lot about the popular Invalid postback or callback argument error message.
I get this error if I rush the web page by clicking on any type of link/redirect (in this case an ASP LinkButton, but the same result occurs when using an ASP Button) before a web page GridView has finished data binding.
The data being bound is very large and, ideally, I should add paging to make it execute faster. However, besides the click, there is no additional data being modified, including any client scripts, so I am unsure why this error is occurring.
Full error:
Invalid postback or callback argument. Event validation is enabled using 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 don't want to disable event validation for security reasons and I know that the large DataBind operation is the reason for this but I don't know why.
I have also tried disabling the grid validation as a simple test but this did not solve the issue:
myGrid.ValidateRequestMode = ValidateRequestMode.Disabled
The LinkButton is not using PostBackUrl
and is instead using a Click event + Response.Redirect
(I removed all irrelevant code).
The LinkButton is also created before the DataBind takes place.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load Dim application As IApplication If Not IsPostBack Then application = Session("App") If application IsNot Nothing Then AddLinkButton("Test", "EntityPage", CommandType.PageLink) ShowData(application) End If End If End Sub Private Sub AddLinkButton(label As String, commandArgument As String, Optional command As CommandType = CommandType.Link) Dim linkBtn As New LinkButton() linkBtn.Text = label linkBtn.CssClass = "myLinkBtn" linkBtn.CommandName = command.ToString linkBtn.CommandArgument = commandArgument AddHandler linkBtn.Click, AddressOf LinkButton_Click panel.Controls.Add(linkBtn) End Sub Private Sub LinkButton_Click(ByVal sender As Object, ByVal e As EventArgs) Dim linkBtn As LinkButton = CType(sender, LinkButton) Select linkBtn.CommandName Case "Link" : Response.Redirect(linkBtn.CommandArgument, False) ' more cases + additional logic that I removed from the example End Select End Sub Friend Sub ShowData(application As IApplication) Dim entities As List(Of Entity) If Not IsPostBack Then entities = application.GetEntities() myGridView.DataSource = entities myGridView.DataBind() End If End Sub
Why do you think this is happening? And is there any way to possibly interrupt the data bind successfully?
EDIT: Also tried using Button instead of LinkButton, and using UseSubmitBehavior = True
, but same result.
2 Answers
Answers 1
I think this error is not because of large amount of data in GridView. This will Validates PostBack is from correct path/source which will be gone by setting EnableEventValidation="false"
in your page.
As you won't set EnableEventValidation="false"
then you can do something like this:
Place your GridView inside an UpdatePanel control and do
asp:AsyncPostBackTrigger
trigger for your GridView.<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:GridView ID="GridView1" runat="server"OnRowCommand="GridView1_RowCommand"> </asp:GridView> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="GridView1" /> </Triggers> </asp:UpdatePanel>
In your GridView add
RowCommand
event and place your LinkButton/Button code there, by checking correcte.CommandName == "LinkButtonCommandName"
and find your GridViewRow for other working.Protected Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As GridViewCommandEventArgs) Dim index As Integer = Convert.ToInt32(e.CommandArgument) Dim gvRow As GridViewRow = GridView1.Rows(index) // find GridView clicked row // find LinkButton from GridView row Dim LinkButton1 As LinkButton = CType(GridViewRow.FindControl("LinkButton1"), LinkButton) //... here some logic End Sub
Answers 2
You are on the wrong track: there is nothing wrong with your data nor its volume. What's wrong is this:
The LinkButton is also created before the DataBind takes place.
This is simply not enough. You need to create dynamic controls (such as your LinkButton) earlier in the page life cycle, because ASP.NET must do its magic and setup the ViewState
for the dynamic controls too. Note that creation of the ViewState
occurs earlier in the lifecycle than the Load
event. As stated on the MSDN, the PreInit
event is the right place to create or re-create dynamic controls. So you gonna need to get rid of the AddLinkButon
sub and add the following within your code behind file:
Private linkBtn As LinkButton ' Declare the LinkButton variable at a module level Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As EventArgs) Handles Me.PreInit linkBtn = New LinkButton() linkBtn.Text = "Test" linkBtn.CssClass = "myLinkBtn" linkBtn.CommandName = CommandType.PageLink.ToString linkBtn.CommandArgument = "EntityPage" AddHandler linkBtn.Click, AddressOf LinkButton_Click End Sub Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Init ' During Init all the controls have been created. ' During the PreInit event the "panel" control is unavailable. panel.Controls.Add(linkBtn) End Sub
And modify the load handler:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load Dim application As IApplication If Not IsPostBack Then application = Session("App") linkBtn.Visible = application IsNot Nothing If linkBtn.Visible Then ' Remove that next line ' AddLinkButton("Test", "EntityPage", CommandType.PageLink) ShowData(application) End If End If End Sub
0 comments:
Post a Comment