¿Alguien puede darme una definición sucinta del papel de ModelState en Asp.net MVC (o un enlace a uno)? En particular, necesito saber en qué situaciones es necesario o deseable llamar ModelState.Clear()
.
Un poco abierto eh ... lo siento, creo que podría ayudar si les digo lo que estoy haciendo en realidad:
Tengo una acción de edición en un controlador llamado "Página". Cuando veo por primera vez el formulario para cambiar los detalles de la página, todo se carga bien (enlazando a un objeto "MyCmsPage"). Luego hago clic en un botón que genera un valor para uno de los campos del objeto MyCmsPage ( MyCmsPage.SeoTitle
). Genera bien y actualiza el objeto y luego devuelvo el resultado de la acción con el objeto de página recién modificado y espero <%= Html.TextBox("seoTitle", page.SeoTitle)%>
que se actualice el cuadro de texto relevante (renderizado usando ) ... pero lamentablemente muestra el valor del modelo anterior que se cargó.
Lo he solucionado usando, ModelState.Clear()
pero necesito saber por qué / cómo ha funcionado, así que no lo estoy haciendo a ciegas.
PageController:
[AcceptVerbs("POST")]
public ActionResult Edit(MyCmsPage page, string submitButton)
{
// add the seoTitle to the current page object
page.GenerateSeoTitle();
// why must I do this?
ModelState.Clear();
// return the modified page object
return View(page);
}
Aspx:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyCmsPage>" %>
....
<div class="c">
<label for="seoTitle">
Seo Title</label>
<%= Html.TextBox("seoTitle", page.SeoTitle)%>
<input type="submit" value="Generate Seo Title" name="submitButton" />
</div>
fuente
Respuestas:
Creo que es un error en MVC. Hoy luché con este problema durante horas.
Dado este:
La vista se renderiza con el modelo original, ignorando los cambios. Entonces pensé, tal vez no me gusta que use el mismo modelo, así que intenté así:
Y aún así, la vista se reproduce con el modelo original. Lo extraño es que cuando pongo un punto de interrupción en la vista y examino el modelo, tiene el valor cambiado. Pero el flujo de respuesta tiene los valores antiguos.
Finalmente descubrí el mismo trabajo que tú hiciste:
Funciona como se esperaba.
No creo que esto sea una "característica", ¿verdad?
fuente
Actualizar:
View()
de una acción POST. Utilice PRG en su lugar y redirija a un GET si la acción es un éxito.View()
acción de POST, hágalo para la validación del formulario y hágalo de la forma en que MVC está diseñado utilizando los ayudantes integrados. Si lo hace de esta manera, no debería necesitar usar.Clear()
ModelState
ya que no debería usarlo de todos modos.Respuesta anterior:
ModelState en MVC se usa principalmente para describir el estado de un objeto modelo en gran parte con relación a si ese objeto es válido o no. Este tutorial debería explicar mucho.
En general, no debería necesitar borrar ModelState, ya que el motor MVC lo mantiene. Borrarlo manualmente puede causar resultados no deseados al intentar cumplir con las mejores prácticas de validación de MVC.
Parece que está intentando establecer un valor predeterminado para el título. Esto debe hacerse cuando se crea una instancia del objeto modelo (capa de dominio en algún lugar o en el objeto mismo - ctor sin parámetros), en la acción de obtención de modo que baje a la página la primera vez o completamente en el cliente (a través de ajax o algo así) para que parezca que el usuario lo ingresó y regresa con la colección de formularios publicados. De alguna manera, su enfoque de agregar este valor al recibir una colección de formularios (en la acción POST // Editar) está causando este comportamiento extraño que podría resultar en que
.Clear()
parezca que funciona para usted. Créame, no querrá usar el claro. Pruebe una de las otras ideas.fuente
Si desea borrar un valor para un campo individual, la siguiente técnica me resultó útil.
Nota: Cambie "Clave" por el nombre del campo que desea restablecer.
fuente
Bueno, el ModelState básicamente mantiene el estado actual del modelo en términos de validación, mantiene
ModelErrorCollection: representa los errores cuando el modelo intenta vincular los valores. ex.
o como un parámetro en ActionResult
ValueProviderResult : contiene los detalles sobre el intento de enlace con el modelo. ex. AttemptedValue, Culture, RawValue .
El método Clear () debe usarse con precaución porque puede dar lugar a resultados inesperados. Y perderá algunas propiedades agradables del ModelState como AttemptedValue, esto es utilizado por MVC en segundo plano para volver a llenar los valores del formulario en caso de error.
fuente
Tuve una instancia en la que quería actualizar el modelo de un formulario enviado y no quería 'Redirigir a la acción' por motivos de rendimiento. Los valores anteriores de los campos ocultos se conservaban en mi modelo actualizado, ¡lo que causaba todo tipo de problemas!
Algunas líneas de código pronto identificaron los elementos dentro de ModelState que quería eliminar (después de la validación), por lo que los nuevos valores se usaron en el formulario: -
fuente
Bueno, parece que muchos de nosotros hemos sido mordidos por esto, y aunque la razón por la que esto sucede tiene sentido, necesitaba una forma de asegurarme de que se mostrara el valor en mi modelo, y no en ModelState.
Algunos han sugerido
ModelState.Remove(string key)
, pero no es obvio quékey
debería ser, especialmente para los modelos anidados. Aquí hay un par de métodos que se me ocurrieron para ayudar con esto.El
RemoveStateFor
método tomará unModelStateDictionary
, un modelo y una expresión para la propiedad deseada y la eliminará.HiddenForModel
se puede usar en su Vista para crear un campo de entrada oculto usando solo el valor del Modelo, eliminando primero su entrada ModelState. (Esto podría expandirse fácilmente para los otros métodos de extensión de ayuda).Llame desde un controlador como este:
o desde una vista como esta:
Se usa
System.Web.Mvc.ExpressionHelper
para obtener el nombre de la propiedad ModelState.fuente
Quería actualizar o restablecer un valor si no se validaba del todo y encontré este problema.
La respuesta fácil, ModelState.Remove, es ... problemática ... porque si estás usando ayudantes realmente no conoces el nombre (a menos que sigas la convención de nomenclatura). A menos que tal vez cree una función que tanto su asistente personalizado como su controlador puedan usar para obtener un nombre.
Esta función debería haberse implementado como una opción en el asistente, donde de forma predeterminada no hace esto, pero si desea que se vuelva a mostrar la entrada no aceptada, simplemente puede decirlo.
Pero al menos ahora entiendo el problema;).
fuente
Remove()
la clave correcta.Lo tengo al final. Mi ModelBinder personalizado que no se estaba registrando y hace esto:
Entonces, algo que estaba haciendo el enlace del modelo predeterminado debe haber causado el problema. No estoy seguro de qué, pero mi problema al menos está solucionado ahora que se está registrando mi carpeta de modelos personalizados.
fuente
Generalmente, cuando se encuentra luchando contra un marco de prácticas estándar, es hora de reconsiderar su enfoque. En este caso, el comportamiento de ModelState. Por ejemplo, cuando no desee el estado del modelo después de una POST, considere una redirección al archivo get.
EDITADO para responder al comentario cultural:
Esto es lo que uso para manejar una aplicación MVC multicultural. Primero, las subclases del controlador de ruta:
Y así es como conecto las rutas. Después de crear las rutas, antepongo mi subagente (example.com/subagent1, example.com/subagent2, etc.) y luego el código de cultura. Si todo lo que necesita es la cultura, simplemente elimine el subagente de los controladores de ruta y las rutas.
fuente
Bueno, esto pareció funcionar en mi página de Razor y ni siquiera hizo un viaje de ida y vuelta al archivo .cs. Esta es la vieja forma html. Puede ser útil.
fuente