asp.net javascript listbox eventvalidation
APLICACIÓN DE PRUEBA

asp.net - Los elementos ListBox reorganizados con JavaScript causan errores de validación de eventos en la devolución de datos



eventvalidation (7)

He creado un control de intercambio de elementos que consta de dos cuadros de lista y algunos botones que me permiten intercambiar elementos entre las dos listas. El intercambio se hace usando javascript. También muevo elementos hacia arriba y hacia abajo en la lista. Básicamente, cuando muevo los elementos al cuadro de lista a la derecha, guardo las claves de datos de los elementos (GUID) en un campo oculto. En la devolución, simplemente leí los GUID del campo. Todo funciona bien pero en la devolución de datos, recibo la siguiente excepción:

No válido postback o argumento de devolución de llamada. La validación de eventos se habilita mediante la configuración o <% @ Page EnableEventValidation = "true"%> en una página. Por motivos de seguridad, esta función verifica que los argumentos para la devolución de datos o los eventos de devolución de llamada se originan en el control del servidor que los generó originalmente. Si los datos son válidos y esperados, utilice el método ClientScriptManager.RegisterForEventValidation para registrar la devolución de datos o los datos de devolución de llamada para la validación.

He preparado una aplicación de prueba. Todo lo que tienes que hacer es descargar el archivo y ejecutar el proyecto. En la página web, seleccione los 3 elementos, presione Agregar todo, luego mueva el tercer elemento un nivel y luego presione "Botón". El error aparecerá. Desactivar la validación de eventos no es aceptable. ¿Alguien puede ayudarme? He pasado dos días sin encontrar una solución.

APLICACIÓN DE PRUEBA


El problema es que el estado de la vista guardada de la lista y los datos recibidos en la devolución no coinciden. El problema de validación de eventos probablemente sea uno de los posibles problemas que pueden aparecer debido a este enfoque. La arquitectura de los formularios web no permite este tipo de usos y, lo más probable, habrá más problemas con este enfoque, incluso si logra evitar el problema de validación de eventos. Tienes varias alternativas:

1) Lo más simple es hacer la lógica de intercambio en el servidor en lugar de usar javascript. De esta forma, el estado de la vista se conservará entre las devoluciones y la sobrecarga adicional de múltiples viajes redondos al servidor podría no ser un problema.

2) Si los múltiples viajes redondos al servidor son un problema, escriba un control de servidor que maneje su propio estado de vista. Este es, por supuesto, un enfoque muy atractivo.

3) Un enfoque intermedio podría ser utilizar dos listas html simples (solo escriba las etiquetas html sin usar los controles asp.net) y mantenga en el lado del cliente una lista de id en un campo oculto. En la parte posterior de la publicación simplemente analiza el campo oculto y extrae la identificación ignorando las listas html.

Me gustaría ir con 1 si no hay argumentos GRAVES contra eso.


La primera opción traerá una sobrecarga considerable. Definí mi propio control de cuadro de lista personalizado derivado de la clase listbox y realicé una anulación de los datos de loadpostback:

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

El uso de este en lugar del cuadro de lista normal en mi control de usuario resolvió el problema, sin embargo, ¿hay algún riesgo asociado con mi enfoque?


Algunas posibles opciones:

  • Si es posible, deshabilite ViewState en las dos listas. Sin ViewState, el servidor no sabrá cuáles eran los valores originales y, por lo tanto, no generará errores. Con este enfoque, tendrá que volver a llenar las listas (debido a la falta de ViewState) y es posible que deba hacer un seguimiento de la selección manualmente, o deberá rellenar las listas durante la fase OnInit.

  • Desactiva la validación de eventos (si puedes)

  • Llenar ambas listas completamente en el lado del servidor y usar el script del lado del cliente (javascript) para eliminar entradas de las dos listas según sea necesario.


Por casualidad, ¿has intentado esto ya? Haga esto cada vez que ensucia con la lista de cualquier manera.

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


Se está quejando porque el elemento seleccionado en una lista no estaba presente en la lista cuando se procesó. Considere usar PageMethods a través de AJAX para regresar sus datos a su formulario en lugar de PostBack. O utilice controles que no sean de entrada para contener los datos, como las listas desordenadas a las que mueva los elementos de la lista de un lado a otro. Puede colocar los GUID en tramos ocultos dentro del elemento de la lista, donde puede acceder a ellos si es necesario.


Alternativamente, puede usar un HtmlSelect del lado del servidor en lugar de un ListBox para evitar el problema de validación del evento. Lo mejor de todo, es posible que pueda dejar intacta gran parte de su código subyacente (es decir, la lógica de población de la lista es la misma que la de ListBox).

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


Podría anular el evento Renderizar para registrar todos los elementos posibles del cuadro de lista con ambos listboxes. De esa forma, sin importar qué elementos se trasladen a dónde, la validación los está esperando.

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); }