¿Cómo obtener todos los errores de ASP.Net MVC modelState?

Quiero obtener todos los mensajes de error del modeloState sin conocer los valores clave. Looping para captar todos los mensajes de error que contiene el ModelState.

¿Cómo puedo hacer esto?

 foreach (ModelState modelState in ViewData.ModelState.Values) { foreach (ModelError error in modelState.Errors) { DoSomethingWith(error); } } 

Consulte también ¿Cómo obtengo la colección de errores de estado del modelo en ASP.NET MVC? .

Usando LINQ :

 IEnumerable allErrors = ModelState.Values.SelectMany(v => v.Errors); 

Basándose en la versión de LINQ, si desea unir todos los mensajes de error en una cadena:

 string messages = string.Join("; ", ModelState.Values .SelectMany(x => x.Errors) .Select(x => x.ErrorMessage)); 

Pude hacer esto usando un pequeño LINQ,

 public static List GetErrorListFromModelState (ModelStateDictionary modelState) { var query = from state in modelState.Values from error in state.Errors select error.ErrorMessage; var errorList = query.ToList(); return errorList; } 

El método anterior devuelve una lista de errores de validación.

Otras lecturas :

Cómo leer todos los errores de ModelState en ASP.NET MVC

Durante la depuración, me parece útil poner una tabla en la parte inferior de cada una de mis páginas para mostrar todos los errores de ModelState.

  @foreach (var item in ViewContext.ViewData.ModelState) { if (item.Value.Errors.Any()) {  } } 
@item.Key @((item.Value == null || item.Value.Value == null) ? "" : item.Value.Value.RawValue) @(string.Join("; ", item.Value.Errors.Select(x => x.ErrorMessage)))

Como descubrí haber seguido el consejo en las respuestas dadas hasta ahora, puede obtener excepciones sin mensajes de error, por lo tanto, para detectar todos los problemas, realmente necesita obtener el ErrorMessage y la excepción.

 String messages = String.Join(Environment.NewLine, ModelState.Values.SelectMany(v => v.Errors) .Select( v => v.ErrorMessage + " " + v.Exception)); 

o como un método de extensión

 public static IEnumerable GetErrors(this ModelStateDictionary modelState) { return modelState.Values.SelectMany(v => v.Errors) .Select( v => v.ErrorMessage + " " + v.Exception).ToList(); } 

Y esto también funciona:

 var query = from state in ModelState.Values from error in state.Errors select error.ErrorMessage; var errors = query.ToArray(); // ToList() and so on... 

Esto se expande con la respuesta de @Dunc. Ver los comentarios de xml doc

 // ReSharper disable CheckNamespace using System.Linq; using System.Web.Mvc; public static class Debugg { ///  /// This class is for debugging ModelState errors either in the quick watch /// window or the immediate window. /// When the model state contains dozens and dozens of properties, /// it is impossible to inspect why a model state is invalid. /// This method will pull up the errors ///  /// modelState ///  public static ModelError[] It(ModelStateDictionary modelState) { var errors = modelState.Values.SelectMany(x => x.Errors).ToArray(); return errors; } } 

Por si acaso alguien lo necesita, hice y uso la siguiente clase estática en mis proyectos

Ejemplo de uso:

 if (!ModelState.IsValid) { var errors = ModelState.GetModelErrors(); return Json(new { errors }); } 

Usos:

 using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Mvc; using WebGrease.Css.Extensions; 

Clase:

 public static class ModelStateErrorHandler { ///  /// Returns a Key/Value pair with all the errors in the model /// according to the data annotation properties. ///  ///  ///  /// Key: Name of the property /// Value: The error message returned from data annotation ///  public static Dictionary GetModelErrors(this ModelStateDictionary errDictionary) { var errors = new Dictionary(); errDictionary.Where(k => k.Value.Errors.Count > 0).ForEach(i => { var er = string.Join(", ", i.Value.Errors.Select(e => e.ErrorMessage).ToArray()); errors.Add(i.Key, er); }); return errors; } public static string StringifyModelErrors(this ModelStateDictionary errDictionary) { var errorsBuilder = new StringBuilder(); var errors = errDictionary.GetModelErrors(); errors.ForEach(key => errorsBuilder.AppendFormat("{0}: {1} -", key.Key,key.Value)); return errorsBuilder.ToString(); } } 

La salida solo de los mensajes de error no fue suficiente para mí, pero fue el truco.

 var modelQuery = (from kvp in ModelState let field = kvp.Key let state = kvp.Value where state.Errors.Count > 0 let val = state.Value.AttemptedValue ?? "[NULL]" let errors = string.Join(";", state.Errors.Select(err => err.ErrorMessage)) select string.Format("{0}:[{1}] (ERRORS: {2})", field, val, errors)); Trace.WriteLine(string.Join(Environment.NewLine, modelQuery)); 

En caso de que alguien quiera devolver el nombre de la propiedad del modelo para enlazar el mensaje de error en una vista fuertemente tipada.

  List Errors = new List(); foreach (KeyValuePair modelStateDD in ViewData.ModelState) { string key = modelStateDD.Key; ModelState modelState = modelStateDD.Value; foreach (ModelError error in modelState.Errors) { ErrorResult er = new ErrorResult(); er.ErrorMessage = error.ErrorMessage; er.Field = key; Errors.Add(er); } } 

De esta forma, puede vincular el error con el campo que arrojó el error.

Útil para pasar una matriz de mensajes de error a Ver, quizás a través de Json:

 messageArray = this.ViewData.ModelState.Values.SelectMany(modelState => modelState.Errors, (modelState, error) => error.ErrorMessage).ToArray(); 

Además, ModelState.Values.ErrorMessage puede estar vacío, pero ModelState.Values.Exception.Message puede indicar un error.

En su implementación le falta Clase estática, esto debería ser.

 if (!ModelState.IsValid) { var errors = ModelStateErrorHandler.GetModelErrors(this.ModelState); return Json(new { errors }); } 

más bien

 if (!ModelState.IsValid) { var errors = ModelState.GetModelErrors(); return Json(new { errors }); }