ModelState.AddModelError: ¿cómo puedo agregar un error que no sea para una propiedad?

190

Estoy revisando mi base de datos en Create(FooViewModel fvm){...}para ver si el fvm.prop1y fvm.prop2ya existen en esa combinación; si es así, deseo agregar un error al modelo, luego devolver la vista completa. Lo intenté:

public ActionResult Create(FooViewModel fvm){
    if (ThatComboAlreadyExists(fvm)) {
      ModelState.AddModelError("Model", "There is already one like that");
      return View(fvm);
    }
}

... pero no se muestran errores en el Html.ValidationSummary, que es donde supongo que aparecerían. Tengo la sospecha de que "Modelo" no es la clave correcta, pero no he podido encontrar nada a la Google.

Scott Baker
fuente

Respuestas:

330

Eventualmente me topé con un ejemplo del uso que estaba buscando: asignar un error al Modelo en general, en lugar de una de sus propiedades, como de costumbre llama:

ModelState.AddModelError(string key, string errorMessage);

pero use una cadena vacía para la clave:

ModelState.AddModelError(string.Empty, "There is something wrong with Foo.");

El mensaje de error se presentará en la <%: Html.ValidationSummary() %>forma esperada.

Scott Baker
fuente
22
Este caso me hace pensar: por qué no hay un método como ModelState.AddError(errorMessage)o ModelState.AddGlobalError(errorMessage)... sería intuitivo y más fácil descubrir cómo agregar un mensaje de error no relacionado con las propiedades de ningún modelo.
Rubens Mariuzzo
@Rubens: es cierto, pero puede agregar fácilmente dicho método con métodos de extensión.
Johnny5
2
También puede mostrar el error usando@Html.ValidationMessage(string.Empty)
Ben Foster,
La clave es la propiedad de su modelo vinculada a la vista, que tiene el error, solo para que quede claro.
niico
1
La ValidationSummaryErrors(bool excludePropertyErrors)sobrecarga mostrará todos los errores de validación si su argumento es falso o solo errores no específicos de la propiedad (clave = "") si su argumento es verdadero.
Suncat2000
26

Puede agregar el error de modelo en cualquier propiedad de su modelo, sugiero que si no hay nada relacionado con la creación de una nueva propiedad.

Como ejemplo, verificamos si el correo electrónico ya está en uso en DB y agregamos el error a la propiedad Correo electrónico en la acción para que cuando regrese la vista, sepan que hay un error y cómo mostrarlo usando

<%: Html.ValidationSummary(true)%>
<%: Html.ValidationMessageFor(model => model.Email) %>

y

ModelState.AddModelError("Email", Resources.EmailInUse);
VinnyG
fuente
1
Esto parece contradictorio en mi caso: estoy verificando si ya existe una combinación particular de col1 y col2 en la base de datos, por lo que no parece correcto tener la propiedad IsDuplicateOfAnotherRow en mi ViewModel. Resulta que puede agregar un error a su modelo; vea mi respuesta.
Scott Baker
1
¿Hay alguna manera de obtener la cadena "Correo electrónico" para AddModelError sin usar una cadena literal frágil? Al igual que (m=>m.email).SomeMagicToString()?
Snekse
No lo creo, tienes que ir con una cuerda mágica ... no es la mejor pero sigue siendo una buena solución
VinnyG
44
El nameofoperador que viene en C # 6.0 resuelve este problema de cadena mágica. msdn.microsoft.com/en-us/magazine/dn802602.aspx
RJ Cuthbertson
3

Poner la propiedad del punto modelo en cadenas funcionó para mí: ModelState.AddModelError("Item1.Month", "This is not a valid date");

Chris
fuente
2
De hecho, eso mostraría un Mes no válido en su IU, pero no resuelve el problema original.
Scott Baker
2
El problema original proviene de no entender qué "clave" representa en el método. Esto arroja algo de luz sobre cómo funciona la "clave", por lo que es bueno saber que la clave no tiene que ser solo un nombre de propiedad, sino que también puede referirse a propiedades anidadas o al valor especial String.Empty.
Triynko