【问题标题】:User clicks during a GridView.DataBind call causes ArgumentException在 GridView.DataBind 调用期间用户单击会导致 ArgumentException
【发布时间】:2017-09-15 11:14:40
【问题描述】:

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

如果我在网页 GridView 完成数据绑定之前通过单击任何类型的链接/重定向(在本例中为 ASP LinkBut​​ton,但使用 ASP 按钮时会出现相同的结果)来加速网页,我会收到此错误.

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

完全错误:

回发或回调参数无效。使用配置或页面中的 启用事件验证。出于安全目的,此功能验证回发或回调事件的参数是否源自最初呈现它们的服务器控件。如果数据有效且符合预期,请使用 ClientScriptManager.RegisterForEventValidation 方法注册回发或回调数据以进行验证。

出于安全原因,我不想禁用事件验证,并且我知道大型 DataBind 操作是导致此问题的原因,但我不知道为什么。

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

myGrid.ValidateRequestMode = ValidateRequestMode.Disabled

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

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

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,但结果相同。

【问题讨论】:

  • 如果你想创建一个链接,只需创建一个链接(!)(a-tag)并且不要使用链接按钮。 Linkbutton 将导致回发发生,link-tag 不会。此处不需要回发,因为您只希望用户跟随指向另一个页面的链接。 Postback会将整个页面回传到服务器进行解析,耗时/效率低,这里不需要。
  • @Esko 可以做到这一点,同时还允许我运行“LinkBut​​ton_Click”事件处理程序吗?
  • 恐怕不行,在您的示例中,除了重定向之外,您没有做任何其他事情,在此之前需要做什么?
  • @Esko 我删除了 LinkBut​​ton_Click 中的一些代码。通常有更多的 select-case 语句和额外的逻辑,所以它是必需的。
  • 那恐怕链接不够用。您可以使用 javascript/ajax 执行逻辑,或更改其他逻辑。但这似乎只是解决数据绑定过大的真正问题的绷带。分页/过滤数据难道不会让用户更友好吗?

标签: c# vb.net gridview


【解决方案1】:

您走错了路:您的数据和数量都没有问题。这是怎么回事:

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

这根本不够。您需要在页面生命周期的早期创建动态控件(例如您的 LinkBut​​ton),因为 ASP.NET 必须发挥它的魔力并为动态控件设置 ViewState。请注意,ViewState 的创建在生命周期中比Load 事件更早发生。 As stated on the MSDNPreInit 事件是创建或重新创建动态控件的正确位置。所以你需要去掉 AddLinkButon 子并在你的代码隐藏文件中添加以下内容:

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

【讨论】:

  • 今天刚回到工作岗位,很抱歉延迟回复。那个你很!工作:)
【解决方案2】:

我认为这个错误不是因为 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
    

【讨论】:

  • 感谢您的建议。它没有解决问题,但值得一试。由于数据量大,当我试图离开页面时,GridView 会不断渲染数据,这就是为什么我认为网格是问题所在。
  • 您可以像在 RowCommand 中一样处理 LinkBut​​ton,这样可以避免出现此错误。
  • 我试过了,但按下按钮时“RowCommand”不会触发。 LinkBut​​ton 不在 GridView 内,点击页面上的任何链接导致的任何重定向都会触发此操作。
  • 我已经编辑过了,你可以从GridViewRow找到你的LinkBut​​ton
  • @Asif.Ali 不。虽然它对于提高页面性能和用户体验很有用,但它根本不是当前问题的解决方案,因为事件验证也在回调中执行。看我的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-02
  • 2023-03-17
  • 1970-01-01
  • 2015-09-30
  • 1970-01-01
  • 2013-12-18
相关资源
最近更新 更多