Come ottenere tutti gli errori da ASP.Net MVC modelState?

Voglio ottenere tutti i messaggi di errore da modelState senza conoscere i valori chiave. Effettuare il looping per afferrare tutti i messaggi di errore che contiene ModelState.

Come posso fare questo?

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

Vedi anche Come ottengo la raccolta di errori di stato del modello in ASP.NET MVC? .

Utilizzando LINQ :

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

Basandosi sulla versione di LINQ, se vuoi unire tutti i messaggi di errore in una stringa:

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

Sono stato in grado di farlo usando un po ‘di 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; } 

Il metodo sopra riportato restituisce un elenco di errori di convalida.

Ulteriori letture:

Come leggere tutti gli errori da ModelState in ASP.NET MVC

Durante il debug, trovo utile mettere una tabella in fondo a ciascuna delle mie pagine per mostrare tutti gli errori 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)))

Come ho scoperto di aver seguito il consiglio nelle risposte date finora, è ansible ottenere eccezioni che si verificano senza che vengano impostati i messaggi di errore, quindi per cogliere tutti i problemi è necessario ottenere sia ErrorMessage che Exception.

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

o come metodo di estensione

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

E anche questo funziona:

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

Questo si sta espandendo sulla risposta di @Dunc. Vedi i commenti del documento XML

 // 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; } } 

Perchè nel caso qualcuno ne avesse bisogno, ho creato e usato la seguente class statica nei miei progetti

Esempio di utilizzo:

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

usings:

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

Classe:

 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(); } } 

Emettere solo i messaggi di errore non era sufficiente per me, ma questo ha fatto il trucco.

 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)); 

Nel caso in cui qualcuno voglia restituire il nome della proprietà Model per associare il messaggio di errore in una vista fortemente tipizzata.

  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); } } 

In questo modo puoi effettivamente colbind l’errore al campo che ha generato l’errore.

Utile per passare array di messaggi di errore a View, forse tramite Json:

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

Inoltre, ModelState.Values.ErrorMessage potrebbe essere vuoto, ma ModelState.Values.Exception.Message potrebbe indicare un errore.

Nella tua implementazione ti manca la class statica, questo dovrebbe essere.

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

piuttosto

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