Неверный аргумент обратной передачи или обратного вызова (HiddenField и container Visible=false)

Я не нашел ответов, соответствующих моим обстоятельствам, поэтому я публикую ответ на вопрос, надеясь, что он поможет другим.

Я получаю ошибку

Неверный аргумент обратной передачи или обратного вызова. Проверка события включена с использованием в конфигурации или <% @ Page EnableEventValidation = "true"%> на странице. В целях безопасности эта функция проверяет, что аргументы для событий обратной передачи или обратного вызова исходят от серверного элемента управления, который первоначально их представил. Если данные действительны и ожидаемы, используйте метод ClientScriptManager.RegisterForEventValidation, чтобы зарегистрировать данные обратной передачи или обратного вызова для проверки.

   at System.Web.UI.ClientScriptManager.ValidateEvent(String uniqueId, String argument)
   at System.Web.UI.Control.ValidateEvent(String uniqueID, String eventArgument)
   at System.Web.UI.WebControls.HiddenField.LoadPostData(String postDataKey, NameValueCollection postCollection)
   at System.Web.UI.WebControls.HiddenField.System.Web.UI.IPostBackDataHandler.LoadPostData(String postDataKey, NameValueCollection postCollection)
   at System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

У меня есть ListView, связанный с данными (с несколькими строками 100 с), с кнопками в каждой строке. Кнопки приносят всплывающее окно. Во всплывающем окне есть выпадающие списки и другие элементы управления, выполняющие асинхронные обратные передачи. Мне нужно убедиться, что я делаю асинхронные обратные вызовы, чтобы избежать обновления моей большой таблицы.

Я получаю сообщение об ошибке, когда нажимаю кнопку в одной строке, а затем изменяю выпадающий список внутри всплывающего окна, которое запускает обратную передачу (выбранный элемент изменен). Boom.

Вот разметка для уменьшенного образца, без всплывающих окон и JavaScript вообще! Это все еще показывает проблему. Дважды нажмите на кнопку в строке, чтобы получить ошибку.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestPopupAsynchPostback.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="scriptMgr" runat="server" ScriptMode="Debug" EnablePartialRendering="true"
            EnableScriptGlobalization="true" EnableScriptLocalization="true" EnablePageMethods="true"/>
        <asp:ObjectDataSource ID="ListDataSource" runat="server" SelectMethod="List" TypeName="TestPopupAsynchPostback.Default" />
        <asp:Label runat="server" ID="PageLabel"></asp:Label>
        <asp:ListView ID="EL" runat="server" DataSourceID="ListDataSource" OnItemDataBound="EntityList_OnItemDataBound">
            <LayoutTemplate>
                <table border="1">
                    <tr id="itemPlaceholder" runat="server" enableviewstate="false">
                    </tr>
                </table>
            </LayoutTemplate>
            <ItemTemplate>
                <tr runat="server" id="DefaultRow" enableviewstate="false">
                    <td>
                        <asp:Label ID="Lbl" runat="server" EnableViewState="false" />
                    </td>
                    <td>
                        <button runat="server" type="button" id="ReportingButton" enableviewstate="false" onserverclick="ReportingButton_OnClick" causesvalidation="false">click</button>
                    </td>
                </tr>
                <%-- Fix part 1: Change SpecialRow  visible = true--%>
                <tr runat="server" id="SpecialRow" visible="false" enableviewstate="false">
                    <td>
                        <asp:Label ID="Lbl2" runat="server" EnableViewState="false" />
                        <asp:HiddenField runat="server" ID="fn_hid" />
                    </td>
                </tr>
            </ItemTemplate>
        </asp:ListView>
    </form>
</body>
</html>

Вот код позади:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace TestPopupAsynchPostback
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            ScriptManager sm = ScriptManager.GetCurrent(Page);
            PageLabel.Text = DateTime.UtcNow.ToString() + " IsPostBack:" + IsPostBack + " IsInAsyncPostBack:" + (sm == null ? "" : sm.IsInAsyncPostBack.ToString());
        }

        protected override void Render(HtmlTextWriter writer)
        {
            ScriptManager sm = ScriptManager.GetCurrent(this.Page);
            if (sm != null)
            {
                foreach (ListViewDataItem row in EL.Items)
                {
                    HtmlButton reportingButton = row.FindControl("ReportingButton") as HtmlButton;
                    if (reportingButton != null)
                        sm.RegisterAsyncPostBackControl(reportingButton);
                }
            }
            base.Render(writer);
        }

        public IList<string> List()
        {
            return (new string[] { "ONE", "TWO"}).ToList();
        }

        protected void ReportingButton_OnClick(object sender, EventArgs e)
        {
            //Do something useful here, for now, just a postback event
        }

        protected void EntityList_OnItemDataBound(object sender, ListViewItemEventArgs e)
        {
            Label lbl = e.Item.FindControl("Lbl") as Label;
            Label lbl2 = e.Item.FindControl("Lbl2") as Label;
            lbl.Text = lbl2.Text = e.Item.DataItem.ToString();

            HtmlTableRow specialRow = e.Item.FindControl("SpecialRow") as HtmlTableRow;
            if (e.Item.DataItemIndex%2 == 0)
            {
                HiddenField fn_hid = e.Item.FindControl("fn_hid") as HiddenField;
                fn_hid.Value = "test1";
                specialRow.Visible = true;
            }
            //Fix part 2: set SpecialRow Visible = false in code behind
            //else
            //    specialRow.Visible = false;
        }
    }
}

1 ответ

Решение

Первоначально я думал, что мой javascript был виноват, поскольку я изменяю вещи с ним. Однако процесс создания образца страницы помог мне найти проблему.

Оказывается, это не имеет никакого отношения к JavaScript или всплывающему окну. Это связано с HiddenField, содержащимся внутри TR HtmlControl (серверный элемент управления asp.net) с Visible=false IN MARKUP. Затем я использую код, чтобы установить Visible=true, когда мне нужно в событии OnItemDataBound.

Вот что вызывает у меня ошибку: кажется, что поскольку контейнер (TR SpecialRow) имеет видимость = ложь, я думаю, что-то не отображается. Затем я захожу в OnItemDataBound, решаю, что эта строка должна быть показана, и устанавливаю Visible=true и устанавливаю значение моего HiddenField. Boom. Если я удалю разметку для скрытого поля и не установлю его значение, не произойдет сбоя. Так что это не только видимость TR самостоятельно, но и HiddenField.

Мое исправление: не устанавливайте Visible = false в разметке и меняйте OnItemDataBound на Visible = false, когда это необходимо.

Другими словами: я по умолчанию скрывал вещи в разметке и использовал код, чтобы показать их. Я изменил это вокруг и по умолчанию показываю вещи в разметке и скрываю их, используя код позади.

Я добавил исправление в разметку и код выше.

Другие вопросы по тегам