如何在从JavaScript编辑选择列表时传递事件验证

时间:2013-02-26 09:46:43

标签: c# asp.net .net html-select eventvalidation

我的ASP.NET站点中有两个选择列表,由服务器填充一些元素。

// .aspx
<asp:dropdownlist id="abc" runat="server"></asp:dropdownlist>
<asp:dropdownlist id="def" runat="server"></asp:dropdownlist>

// .aspx.cs
abc.Items.Add(new ListItem("element1", "value1"));
def.Items.Add(new ListItem("element1", "value1"));

由于现在解释的原因太复杂,我还需要使用JavaScript修改选择列表的选项,添加一些值。

// In the <head> of the .aspx page
var abcList = document.getElementById("abc");
var defList = document.getElementById("def");
var newAbcElement = new Option("element2", "value2", false, false);
var newDefElement = new Option("element2", "value2", false, false);
abcList.options[abcList.length] = newAbcElement;
defList.options[defList.length] = newDefElement;

当然,只要我将表单发送回服务器(通过提交或作为带有AutoPostBack="true"的其他表单元素的PostBack),这将会破坏甚至验证。

  

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

现在,我没有足够的资源和预算来彻底检修整个页面设计,所以:最快最简单更改下拉列表的方法是什么并不意味着我必须改写整个事情?

因此,在提交表单时,我的CodeBehind文件会识别通过JavaScript添加的值吗?

3 个答案:

答案 0 :(得分:1)

您可以完全停用ViewState的{​​{1}}。

DropDownList

问题更新:

这改变了很多问题。这里回答了新问题:Invalid postback or callback argument. Event validation is enabled using '<pages enableEventValidation="true"/>'

答案 1 :(得分:1)

您有几个选择。

首先,您可以重写代码,以便服务器端为DropDownList生成所有可能的项目,然后在JavaScript中删除不需要的项目,而不是添加新项目。

第二个选项是创建从System.Web.UI.WebControls.DropDownList派生的自定义类。该类应包含下面显示的一种方法。重要的是,您的自定义类不会添加System.Web.UI.SupportsEventValidationAttribute - 因此DropDownList基本方法将自动跳过事件验证。现在将<asp:dropdownlist>的用法替换为您的方法。

如果您无法修改.aspx代码(或者您需要更换大量的下拉列表),则可以在配置中使用tag mapping

namespace Project.MyWebControls
{
    public class MyDropDownList : System.Web.UI.WebControls.DropDownList
    { 
        protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
        {
            if (base.LoadPostData(postDataKey, postCollection))
                return true;

            // this means that the value selected was not present in the .Items collection
            string[] values = postCollection.GetValues(postDataKey);
            if (values == null || values.Length == 0)
                return false;

            // add the value to the Items collection so that it can be processed later on.
            this.Items.Add(new ListItem("Custom value created by JavaScript", values[0]));
            this.SetPostDataSelection(this.Items.Count - 1);
        }
    }
}

请注意,根据您的代码,您可能希望在呈现之前从Items集合中删除这些自定义值。

.aspx文件的示例:

<%@ Register TagPrefix="my" Namespace="Project.MyWebControls" Assembly="Project" %>
<my:MyDropDownList runat="server" ...></my:MyDropDownList>

答案 2 :(得分:1)

好的,这里还有一个选项。您可以使用AsyncPostBackTrigger将这些项添加到列表中。

隐藏的某些字段:

<asp:TextBox ID="newItemsForAbc" runat="server" style="display:none;"></asp:TextBox>
<asp:TextBox ID="newItemsForDef" runat="server" style="display:none;"></asp:TextBox>
<asp:Button ID="addNewItems" runat="server" OnClick="addNewItems_Click"
  style="display:none;" />

更新小组:

<asp:UpdatePanel runat="server" ID="UpdatePanel" UpdateMode="Conditional">
   <ContentTemplate>
     <asp:dropdownlist id="abc" runat="server"></asp:dropdownlist>
     <asp:dropdownlist id="def" runat="server"></asp:dropdownlist>
   </ContentTemplate>
   <Triggers>
     <asp:AsyncPostBackTrigger ControlID="addNewItems" EventName="Click" />
   </Triggers>
 </asp:UpdatePanel>

用于执行异步回发的JS函数:

<script type="text/javascript"> function UpdateStuff(value1, value2)
{
   var abcItems = document.getElementById("<%= newItemsForAbc.ClientID %>");
   var defItems = document.getElementById("<%= newItemsForDef.ClientID %>");
   abcItems.value=value1;
   defItems.value=value2;
   __doPostBack("<%= addNewItems.ClientID %>","");
}
</script>

处理按钮点击的服务器端功能:

protected void addNewItems_Click(object sender, EventArgs e)
{
    string[] n1 = newItemsForAbc.Text.Split(';');
    string[] n2 = newItemsForDef.Text.Split(';');

    foreach(string i in n1)
    {
         abc.Items.Add(new ListItem(i, i));
    }

    foreach(string i in n2)
    {
         def.Items.Add(new ListItem(i,i));
    } 
}

更新您的列表:

var newAbcElements = "Element1;Element2;Element3";
var newDefElements = "Element4;Element5";
UpdateStuff(newAbcElements, newDefElements);

最后说明: 这段代码可能不会为你完成这项工作。您可能需要更改在字符串中存储新项目的方式,因此拆分/解析也会发生变化。您甚至可能需要不同的字符串来显示列表项及其实际值。但我相信你会得到基本的想法。