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

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

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

测试应用

有帮助吗?

解决方案 3

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

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

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

其他提示

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

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

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

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

如果没有针对它的SERIOUS参数,我会选择1。

一些可能的选择:

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

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

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

偶然的机会,你有没试过?无论何时以任何方式清理列表,都要这样做。

document.getElementById("listbox").selectedIndex = -1;

它抱怨,因为列表中的所选项目在呈现时不在列表中。考虑通过AJAX使用PageMethods将数据恢复到表单而不是PostBack。或者使用非输入控件来保存数据 - 就像您在列表元素之间来回移动的无序列表一样。您可以将GUID放在list元素中的隐藏span中,如果需要,可以在其中获取它们。

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

<select runat="server" id="myList" multiple="true" />

您可以覆盖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);
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top