Как пройти валидацию событий при редактировании списка выбора из JavaScript

У меня есть два списка выбора на моем сайте 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;

Конечно, это может испортить даже проверку, как только я отправлю форму обратно на сервер (будь то путем отправки или в виде PostBack от некоторых других элементов формы с AutoPostBack="true").

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

Теперь у меня нет ресурсов и бюджета, чтобы полностью переделать весь дизайн страницы, поэтому: Каков самый быстрый и простой способ изменить выпадающий список, который не означает, что я должен переписать все это?

Чтобы значения, добавленные через JavaScript, распознавались моим файлом CodeBehind при отправке формы?

3 ответа

Решение

Хорошо, вот еще один вариант для вас. Вы можете добавить эти элементы в свои списки, используя 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);

Последнее замечание: этот фрагмент кода, вероятно, не будет выполнять эту работу за вас. Возможно, вам придется изменить способ хранения новых элементов в строке, поэтому разделение / разбор также изменится. Вам даже могут понадобиться разные строки для отображения элемента списка и его фактического значения. Но я верю, что вы поняли основную идею.

У вас есть несколько вариантов.

Во-первых, вы можете переписать свой код так, чтобы на стороне сервера генерировались все возможные элементы для DropDownList а затем в вашем JavaScript удалите ненужные элементы вместо добавления новых.

Второй вариант - создать собственный класс, производный от System.Web.UI.WebControls.DropDownList, Класс должен содержать один метод, показанный ниже. Важным моментом является то, что ваш пользовательский класс не будет иметь System.Web.UI.SupportsEventValidationAttribute добавил к этому - так DropDownList Базовые методы автоматически пропустят проверку события. Теперь замените использование от <asp:dropdownlist> к вашему методу.

Если вы не можете изменить код.aspx (или у вас есть тонна выпадающих списков для замены), вы можете использовать отображение тегов в своей конфигурации.

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>

Вы можете отключить ViewState полностью для DropDownList,

<asp:dropdownlist id="abc" runat="server" EnableViewState="false"></asp:dropdownlist>

К вашему вопросу обновление:

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

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