GridView.DataBind调用期间的用户单击导致ArgumentException

时间:2017-09-15 11:14:41

标签: c# vb.net gridview

我已经阅读了很多关于流行的无效的回发或回调参数错误消息。

如果我在网页GridView完成数据绑定之前点击任何类型的链接/重定向(在这种情况下为ASP LinkBut​​ton,但在使用ASP按钮时会出现相同的结果),则会出现此错误

绑定的数据非常大,理想情况下,我应该添加分页以使其执行得更快。但是,除了单击之外,没有其他数据被修改,包括任何客户端脚本,因此我不确定为什么会发生此错误。

完整错误:

  

无效的回发或回调参数。使用配置或<%@ Page EnableEventValidation =“true”%>启用事件验证在一个页面中。出于安全考虑,此功能可验证回发或回调事件的参数是否来自最初呈现它们的服务器控件。如果数据有效且符合预期,请使用ClientScriptManager.RegisterForEventValidation方法注册回发或回调数据以进行验证。

出于安全原因,我不想禁用事件验证,我知道大型DataBind操作就是这个原因,但我不知道为什么。

我也试过禁用网格验证作为一个简单的测试,但这并没有解决问题:

myGrid.ValidateRequestMode = ValidateRequestMode.Disabled

LinkBut​​ton 使用PostBackUrl,而是使用Click事件+ Response.Redirect(我删除了所有不相关的代码)。

在DataBind发生之前还创建了LinkBut​​ton

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

为什么你认为这种情况发生了?有没有办法可能成功中断数据绑定?

编辑:还尝试使用Button代替LinkBut​​ton,并使用UseSubmitBehavior = True,但结果相同。

2 个答案:

答案 0 :(得分:3)

您走错了路:您的数据及其数量没有任何问题。这有什么不对:

  

LinkBut​​ton也是在DataBind发生之前创建的。

这还远远不够。您需要在页面生命周期的早期创建动态控件(例如LinkBut​​ton),因为ASP.NET必须发挥其魔力,并为动态控件设置ViewState。请注意,ViewState的创建发生在生命周期的早期,而不是Load事件。 As stated on the MSDNPreInit事件是创建或重新创建动态控件的正确位置。因此,您需要摆脱AddLinkButon sub并在代码后面的文件中添加以下内容:

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

修改加载程序:

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

答案 1 :(得分:1)

我认为这个错误不是因为GridView中有大量数据。这将验证PostBack是否来自正确的路径/来源,在您的页面中设置EnableEventValidation="false"将会消失。

由于你不会设置EnableEventValidation="false",你可以这样做:

  • 将GridView放在UpdatePanel控件中,并为GridView执行asp:AsyncPostBackTrigger触发器。

    <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>
    
  • 在GridView中添加RowCommand事件,并将LinkBut​​ton / Button代码放在​​那里,方法是检查正确的e.CommandName == "LinkButtonCommandName"并找到GridViewRow用于其他工作。

    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