Элементы ListBox, переставленные с помощью JavaScript, вызывают ошибку проверки события при обратной передаче

StackOverflow https://stackoverflow.com/questions/212988

Вопрос

Я создал элемент управления для обмена элементами, состоящий из двух списков и нескольких кнопок, которые позволяют мне менять элементы между двумя списками.Замена выполняется с помощью javascript.Я также перемещаю элементы вверх и вниз по списку.По сути, когда я перемещаю элементы в поле списка справа, я сохраняю ключи данных элементов (GUID) в скрытом поле.При обратной отправке я просто считываю GUID из поля.Все работает отлично, но при обратной отправке я получаю следующее исключение:

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

Я подготовил тестовое приложение.Все, что вам нужно сделать, это загрузить архив и запустить проект.На веб-странице выберите 3 элемента, нажмите Добавить все, затем переместите третий элемент на один уровень выше и затем нажмите "Кнопка".Появится сообщение об ошибке.Отключение проверки событий ни в коем случае не приемлемо.Кто-нибудь может мне помочь, я потратил уже два дня, не находя решения.

ТЕСТОВОЕ ПРИЛОЖЕНИЕ

Это было полезно?

Решение 3

Первый вариант принесет значительные накладные расходы. Я определил свой собственный элемент управления listbox, полученный из класса listbox, и выполнил переопределение данных loadpostback:

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

Использование этого вместо обычного списка в моем пользовательском элементе управления решило проблему, однако есть ли риски, связанные с моим подходом?

Другие советы

Проблема в том, что сохраненное состояние просмотра списка и данные, полученные при обратной передаче, не совпадают. Проблема проверки события, скорее всего, является лишь одной из возможных проблем, которые могут возникнуть из-за этого подхода. Архитектура веб-форм не допускает такого использования, и, скорее всего, с этим подходом будет больше проблем, даже если вам удастся избежать проблемы проверки события. У вас есть несколько вариантов:

1) Самое простое - это сделать логику обмена на сервере вместо использования javascript. Таким образом, состояние представления будет сохраняться между обратными передачами, и дополнительные издержки нескольких обращений к серверу могут не представлять проблемы.

2) Если возникает проблема с многократными обращениями к серверу, напишите серверный элемент управления, который обрабатывает свое собственное состояние просмотра. Это, конечно, очень интересный подход.

3) Средним подходом может быть использование двух простых html-списков (просто напишите html-тэги без использования элементов управления asp.net) и сохранение на стороне клиента из javascript списка идентификаторов в скрытом поле. При обратной записи просто проанализируйте скрытое поле и извлеките идентификатор, игнорирующий HTML-списки.

Я бы пошел с 1, если нет серьезных аргументов против него.

Несколько возможных вариантов:

  • Если возможно, отключите ViewState в этих двух списках.Без ViewState сервер не будет знать, каковы были исходные значения, и, следовательно, не выдаст ошибку.При таком подходе вам нужно будет повторно заполнить списки (из-за отсутствия ViewState) и, возможно, потребуется отслеживать выбор вручную - или вам нужно будет заполнить списки на этапе OnInit.

  • Отключите проверку событий (если можете)

  • Полностью заполните оба списка на стороне сервера и используйте скрипт на стороне клиента (javascript) для удаления записей из двух списков по мере необходимости.

Случайно, ты уже пробовал это? Делайте это всякий раз, когда вы гадите со списком любым способом.

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

Жалуется, потому что выбранный элемент в списке не присутствовал в списке при его визуализации. Подумайте об использовании PageMethods через AJAX, чтобы вернуть ваши данные в форму вместо PostBack. Или используйте элементы управления без ввода для хранения данных - например, неупорядоченные списки, между которыми вы перемещаете элементы списка. Вы можете поместить GUID в скрытые области внутри элемента списка, где вы можете получить их в случае необходимости.

В качестве альтернативы вы можете использовать серверный 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