2009-05-07 23 views
5

Tengo un problema que aparece en un formulario que intento publicar. En el escenario donde el formulario no se valida, tomo la ruta estándar de llamar al ModelState.AddModelError() y luego devolver un resultado de Vista.ASP.Net MVC ModelState/Html.TextBox postback issue

Lo que pasa es que los helpers HTML * se supone que recogen el valor publicado al renderizar y me doy cuenta de que mis campos de texto SÓLO lo hacen si los incluyo en la lista de parámetros de la acción de devolución, que shouldn No se requiere ver, ya que algunos formularios tienen demasiados campos para querer enumerarlos todos como parámetros.

Mi código de acción es más o menos:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult EditDataDefinition(long? id, string name) 
{ 
    var dataDefinition = ... 

    // do some validation stuff 
    if (!ModelState.IsValid) 
    { 
     // manually set checkbox fields via ViewData seeing as this STILL doesn't work in MC 1.0 :P 
     // ... 
     return View(dataDefinition); 
    } 

} 

Ahora, DataDefinition (que es un LINQ a entidad SQL) tiene un campo MinVolume, que se maneja en la vista por esta línea:

Minimum: <%= Html.TextBox("MinVolume", null, new { size = 5 })%> 

Sin embargo, cuando la vista se representa después de una validación fallida de ModelState, el valor escrito en la página original que publicamos no se conserva A MENOS QUE lo incluya como parámetro en el método de devolución de datos. Literalmente, puedo "resolver el problema" al hacer esto:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult EditDataDefinition(long? id, string name, string minVolume) 

Por alguna razón que forzará el valor del campo para ser preservado. Esto me parece estúpido porque mi formulario tiene mucho más valor que eso y no debería tener que agregar un parámetro solo para ese campo.

¿Alguna idea?

Respuesta

4

Podría ser que su código:

<%= Html.TextBox("MinVolume", null, new { size = 5 })%> 

..has la null como valor predeterminado de parámetro? Tal vez si cambia el null al Model.MinVolume persistirá el valor. De esta manera:

<%= Html.TextBox("MinVolume", Model.MinVolume, new { size = 5 })%> 

No estoy seguro de si su acción devuelve el valor MinVolume en el modelo Tho.Si lo hace, lo anterior debería funcionar. De lo contrario, es posible que deba refactorizar la acción un poco.

+0

No, se especifica que null especifica que el contexto del modelo existente se debe usar para consultar el valor. La especificación de MinVolume es explícita y obligaría a usar ese valor en lugar de lo que se envió anteriormente. –

+0

Incorrecto. Especificando MinVolume busca ViewDataDoctionary y luego ModelStateDictionary para publicaciones posteriores. Entonces, si Model.MinVolume es decir 5 edición de núcleo, entonces la especificación de MinVolume colocará 5 en el TextBox. Luego, si se realiza una publicación (digamos valor 3) pero no es válida, TextBox mostrará 3 la segunda ronda. ¿Lo has probado? Por lo general, especifica nulo en una vista 'Nuevo' o 'Crear' para que la publicación inicial muestre vacío en el campo, y las publicaciones subsiguientes conserven el valor ingresado. –

+0

Esta es exactamente la manera en que yo también lo hago y siempre funciona. Nunca vi en ninguna parte que tengas que especificar null. Un enlace a donde viste eso sería bueno. – sirrocco

3

¿Cuál es la clave que está utilizando cuando establece el valor en el estado del modelo por error? El código que establece el parámetro de valor para un cuadro de texto se ve así:

Porción relevante del downloaded framework code.

string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string)); 
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : valueParameter), isExplicitValue); 

Como puede ver si existe el valor de intento, lo usará, pero solo si la misma clave está disponible.

Sé que esto funciona porque tengo una acción que no toma parámetros y obtiene los valores directamente del ValueProvider y usa AddModelError para indicar errores de validación. Estoy seguro de que los valores en mis TextBoxes se conservan.

EDIT: Para que los valores se conserven, deben estar asociados con el modelo de alguna manera. Una forma de hacerlo es agregarlos a la lista de parámetros. Otra forma es usar UpdateModel (con los nombres de los parámetros en la lista blanca o no en la lista blanca). Una tercera forma es agregar el parámetro explícitamente al modelo como en la respuesta de @ Jenea. Como el ayudante solo saca del estado del modelo, debe estar ahí para que se retengan los valores. No mira la propiedad Forma del pedido.

+0

Ese campo no se valida en absoluto, no necesita estar en esta etapa. Por lo tanto, es solo un "espectador inocente" en la forma y espera tener su nuevo valor preservado si uno de los otros campos no se comporta por sí mismo y, por lo tanto, hace que la forma se represente por segunda vez. –

+0

Me pregunto, de repente, si estoy asumiendo incorrectamente que ModelState debería tratar de preservar todos los campos que tienen nombres que coinciden con el Modelo. ¿Tal vez solo preserve los campos que se pasan a través de la lista de parámetros o se mencionan a través de AddModelError? Si ese es el caso, parece algo estúpido ya que, por supuesto, quiero preservar todo en la forma, no solo casos específicos. Por otra parte, MVC aún no conserva adecuadamente los campos de casillas de verificación de todos modos ... –

0

Según entiendo que la solución es:

[Transaction] 
[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult EditDataDefinition(int id, FormCollection form) 
{ 
    T itemToUpdate = repository.Get(id); 
    UpdateModel(itemToUpdate, form.ToValueProvider()); 

    if (itemToUpdate.IsValid()) 
    { 
     repository.SaveOrUpdate(itemToUpdate); 
     return Json(ValidationResultToJson(itemToUpdate.ValidationResults())); 
    } 

    repository.DbContext.RollbackTransaction(); 
    return Json(ValidationResultToJson(itemToUpdate.ValidationResults())); 
} 

buena suerte!

6

Oh man Acabo de mejorar el diseño de mi aplicación. El problema ocurre porque tiene una validación personalizada (yo también). Hay que añadir, después de

ModelState.AddModelError() 

este

ModelState.SetModelValue("MinVolume", ValueProvider["MinVolume"]); 

Teniendo en cuenta que tiene que ser

Mimum:<%=Html.Textbox("MinVolume")%> 

Aún no está seguro de por qué funciona, pero funcionó para mí.

+0

oooh ... ¡esta podría ser la respuesta! lo comprobaré en la mañana cuando llegue al trabajo. Gracias. –

+2

Funciona porque agrega el valor al modelo, del cual el ayudante extrae los valores. Usar UpdateModel también funcionaría, que es lo que uso y por qué se conservan los valores de mi cuadro de texto. – tvanfosson

0

Otra solución es si escribe a la vista:

<%var minVolume=Request["MinVolume"]??"";%> 
<%=Html.Textbox("MinVolume",minVolume,new {size=5})%> 
0

favor refiérase a este artículo para ver diferentes maneras de manejar la devolución de datos en ASP.NET MVC

link text

+0

Buen artículo para el principiante. –

Cuestiones relacionadas