Как пройти валидацию событий при редактировании списка выбора из 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>
К вашему вопросу обновление:
Это очень сильно меняет вопрос. Ответ на новый вопрос здесь: Неверный аргумент обратной передачи или обратного вызова. Проверка события включена с помощью '