5

我创建了一个包含两个列表框和一些按钮的项目交换器控件,这些按钮允许我在两个列表之间交换项目。交换是使用javascript完成的。我还在列表中上下移动项目。基本上,当我将项目移动到右侧的列表框时,我将元素(GUID)的数据键存储在隐藏字段中。在回发时,我只是从现场读取 GUID。一切正常,但在回发时,我得到以下异常:

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

我准备了一个测试应用程序。您所要做的就是下载存档并运行项目。在网页上选择 3 个项目,按全部添加,然后将第三个元素上移一级,然后点击“按钮”。错误会出现。关闭事件验证是绝对不能接受的。任何人都可以帮助我,我已经花了两天时间没有找到解决方案。

测试应用

4

7 回答 7

3

问题是列表的保存视图状态和回发时收到的数据不匹配。事件验证问题很可能只是由于这种方法而可能出现的问题之一。webforms 的架构不允许这种用途,而且这种方法很可能会出现更多问题,即使您成功避免了事件验证问题。您有几种选择:

1) 最简单的是在服务器上执行交换逻辑,而不是使用 javascript。这样,在回发之间将保留视图状态,并且多次往返服务器的额外开销可能不是问题。

2)如果到服务器的多次往返是一个问题,请编写一个服务器控件来处理它自己的视图状态。这当然是一种非常吸引人的方法。

3) 一种中间方法可能是使用两个简单的 html 列表(只需编写 html 标记而不使用 asp.net 控件)并在客户端从 javascript 维护隐藏字段中的 id 列表。在回发时,只需解析隐藏字段并提取 id 忽略 html 列表。

如果没有严重的反对意见,我会选择 1。

于 2008-10-17T19:08:16.463 回答
1

几个可能的选择:

  • 如果可能,请禁用两个列表上的 ViewState。如果没有 ViewState,服务器将不知道原始值是什么,因此不会出错。使用这种方法,您将需要重新填充列表(由于缺少 ViewState),并且可能需要手动跟踪选择 - 或者需要在 OnInit 阶段填充列表。

  • 关闭事件验证(如果可以)

  • 在服务器端完全填充两个列表,并根据需要使用客户端脚本 (javascript) 从两个列表中删除条目。

于 2008-10-18T04:52:03.850 回答
0

它抱怨是因为列表中的选定项目在呈现时不存在于列表中。考虑通过 AJAX 使用 PageMethods 将数据返回到表单而不是 PostBack。或者使用非输入控件来保存数据——比如你在列表元素之间来回移动的无序列表。您可以将 GUID 放在列表元素内的隐藏跨度中,如果需要,您可以在其中获取它们。

于 2008-10-17T17:59:07.710 回答
0

第一种选择会带来相当大的开销。我已经定义了我自己的从列表框类派生的自定义列表框控件,并执行了 loadpostback 数据的覆盖:

public class CustomListBox : ListBox
{
    protected override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
    {
        return true;
    }
}

在我的用户控件中使用它而不是常规列表框解决了问题,但是我的方法是否存在任何风险?

于 2008-10-17T19:26:20.683 回答
0

碰巧,你已经试过了吗?每当您以任何方式弄乱列表时,请执行此操作。

document.getElementById("listbox").selectedIndex = -1;
于 2008-10-18T21:19:37.193 回答
0

或者,您可以使用服务器端 HtmlSelect 代替 ListBox 来解决事件验证问题。最重要的是,您可以保留大部分代码隐藏(即列表填充逻辑与 ListBox 相同)。

<select runat="server" id="myList" multiple="true" />
于 2011-11-22T05:26:07.097 回答
0

您可以覆盖 Render 事件以使用两个列表框注册所有可能的列表框项目。这样,无论将哪些项目移动到哪里,验证都在期待它们。

protected override void Render(HtmlTextWriter writer)
{
  foreach (DictionaryEntry entry in ColumnConfig) {          
    Page.ClientScript.RegisterForEventValidation(lstbxColumnsToExport.UniqueID,(string)entry.Key);
    Page.ClientScript.RegisterForEventValidation(lstbxNonExportColumns.UniqueID,(string)entry.Key);
  }
  base.Render(writer);
}
于 2015-11-19T17:42:28.820 回答