2010-04-05 9 views
6

Esto está funcionando, pero ¿cómo?¿Cómo recuerda asp.net MVC mis valores incorrectos en la devolución de datos?

que tienen una acción de controlador para un mensaje:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(Person person) 
{ 
    bool isvalid = ModelState.IsValid; 
    etc. 

El objeto persona tiene una fecha de nacimiento propiedad, tipo DateTime. Cuando ingreso algunos datos no válidos en el formulario, diga 'blabla', que obviamente no es una fecha y hora válida, llena todas las (otras) propiedades de persona con los datos correctos y la propiedad de fecha de nacimiento con un nuevo DateTime en blanco. El bool isvalid tiene el valor 'falso'. Hasta ahora todo bien.

Entonces puedo hacer esto:

return View(p); 

y en la vista tengo esto:

<%= Html.TextBox("BirthDate", String.Format("{0:g}", Model.BirthDate)) %> 
<%= Html.ValidationMessage("BirthDate", "*") %> 

hormiga no se trata de: i espera que el modelo de contener el nuevo DateTime, en blanco porque yo no No ingrese ningún dato nuevo. Segundo, cuando la Vista muestre algo, debe ser un DateTime, porque Model.BirthDate no puede contener nada más que un DateTime. Pero para mi sorpresa, ¡muestra un cuadro de texto con el valor 'blabla'! (y el rojo * detrás de él)

Lo que por supuesto es bueno porque el usuario puede ver lo que escribió mal, pero ¿cómo puede esa cadena (blabla) transferirse a la Vista en un campo Fecha y hora?

EDITAR: La información de ModelState me ayudó mucho aquí. También noto que en MVC 2, cuando crea su propia plantilla para Html.EditorFor() tiene que implementar este comportamiento usted mismo. he creado un

DateTime.ascx 

en la vista de carpeta// shared/EditorTemplates, y allí tuve que comprobar si había un error de ModelState para este valor de la propiedad, y si es así, mostrar los datos no válidos en lugar de los datos del modelo.

Así que en la vista utilizo este:

<%= Html.LabelFor(model => model.DateOfBirth) %> 

y en el DateTime.ascx yo uso esto:

<% 
bool invalidData = false; 
string propertyName = ViewData.ModelMetadata.PropertyName; 

ModelState ms = ViewData.ModelState[propertyName]; 
if (ms != null) 
{ 
    invalidData = ms.Errors.Count > 0; 
} 
string valueToshow = invalidData ? ViewData.ModelState[propertyName].Value.AttemptedValue : String.Format("{0:g}", Model); 
%> 
<input class="text-box single-line" id="<%= propertyName %>" name="<%= propertyName %>" type="text" value="<%= valueToshow %>" /> 

Respuesta

10

ModelState sostiene KeyValuePairs para cada elemento de la forma donde la clave es el nombre del campo y el valor es lo que pones en el campo. Luego los Html Helpers miran en ModelState y si no especificas explícitamente un valor, extraerán el valor de ModelState.

+0

Gracias, ahora los ayudantes no hicieron más que analizar el valor en el modelo. – Michel

4

El valor previamente ingresado se almacena en el Estado del modelo. Cuando tiene un error en el formulario, el ayudante extrae el valor del ModelState en lugar de utilizar los valores del modelo o los que se suministran específicamente (debajo del capó, si no proporciona un valor explícito, se utilizará el modelo por defecto). valor si hay uno cuando no hay errores).

+0

+1 por la respuesta, Keith fue un poco más rápido, espero que no te importe marcarlo como respuesta – Michel

+0

Creo que esta respuesta es correcta, y Keith no está exactamente en lo cierto. La respuesta de Keith indica que ModelState se usa si no especifica explícitamente un valor; esta respuesta indica que ModelState se usa si hay un error, ya sea que se especifique explícitamente o no un valor. El patrón para llamar al controlador GET después del controlador POST cuando hay un Error de modelo, solo funciona porque los datos de la vista de modelo de modelo siempre anulan todo lo que codifica en el controlador GET. –

1

Tenía un código en la 'devolución de datos' que eliminaría códigos promocionales no válidos y capitalizaría la respuesta. Incluso si actualiza el modelo con el nuevo valor, no se mostrará porque el valor de ModelState tiene prioridad (como otros ya han respondido).

<%= Html.TextBox("PromoCode", Model.PromoCodes) %> 

Pero si usted tiene un caso en el que esto estaba sucediendo y no desea que el valor antiguo persistió lo que necesita hacer esto:

ModelState.Remove("PromoCode"); 

o explícitamente establece el valor nuevo en ModelState (probablemente el mejor enfoque):

ModelState.SetModelValue("PromoCode", 
     new ValueProviderResult(newValue, newValue, CultureInfo.CurrentCulture)); 
+0

+1 para la adición. – Michel

Cuestiones relacionadas