Je souhaite obtenir tous les messages d'erreur de modelState sans connaître les valeurs clés. En boucle pour récupérer tous les messages d'erreur que contient ModelState.
Comment puis-je faire ceci?
foreach (ModelState modelState in ViewData.ModelState.Values) {
foreach (ModelError error in modelState.Errors) {
DoSomethingWith(error);
}
}
Voir aussi Comment obtenir la collection d'erreurs d'état de modèle dans ASP.NET MVC? .
Utilisation de LINQ :
IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);
En vous appuyant sur la version de LINQ, si vous souhaitez réunir tous les messages d'erreur en une seule chaîne:
string messages = string.Join("; ", ModelState.Values
.SelectMany(x => x.Errors)
.Select(x => x.ErrorMessage));
J'ai pu faire cela en utilisant un peu LINQ,
public static List<string> GetErrorListFromModelState
(ModelStateDictionary modelState)
{
var query = from state in modelState.Values
from error in state.Errors
select error.ErrorMessage;
var errorList = query.ToList();
return errorList;
}
La méthode ci-dessus renvoie une liste d'erreurs de validation.
Lectures supplémentaires:
Comment lire toutes les erreurs de ModelState dans ASP.NET MVC
Lors du débogage, il est utile de placer un tableau au bas de chacune de mes pages pour afficher toutes les erreurs ModelState.
<table class="model-state">
@foreach (var item in ViewContext.ViewData.ModelState)
{
if (item.Value.Errors.Any())
{
<tr>
<td><b>@item.Key</b></td>
<td>@((item.Value == null || item.Value.Value == null) ? "<null>" : item.Value.Value.RawValue)</td>
<td>@(string.Join("; ", item.Value.Errors.Select(x => x.ErrorMessage)))</td>
</tr>
}
}
</table>
<style>
table.model-state
{
border-color: #600;
border-width: 0 0 1px 1px;
border-style: solid;
border-collapse: collapse;
font-size: .8em;
font-family: arial;
}
table.model-state td
{
border-color: #600;
border-width: 1px 1px 0 0;
border-style: solid;
margin: 0;
padding: .25em .75em;
background-color: #FFC;
}
</style>
Comme j'ai découvert après avoir suivi les conseils donnés dans les réponses données jusqu'à présent, vous pouvez obtenir des exceptions sans définir de message d'erreur. Par conséquent, pour résoudre tous les problèmes, vous devez obtenir à la fois le message ErrorMessage et l'exception.
String messages = String.Join(Environment.NewLine, ModelState.Values.SelectMany(v => v.Errors)
.Select( v => v.ErrorMessage + " " + v.Exception));
ou comme méthode d'extension
public static IEnumerable<String> GetErrors(this ModelStateDictionary modelState)
{
return modelState.Values.SelectMany(v => v.Errors)
.Select( v => v.ErrorMessage + " " + v.Exception).ToList();
}
Si quelqu'un souhaite renvoyer la propriété Name of the Model pour lier le message d'erreur dans une vue fortement typée.
List<ErrorResult> Errors = new List<ErrorResult>();
foreach (KeyValuePair<string, ModelState> 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 cette façon, vous pouvez réellement lier l’erreur au champ qui l’a renvoyée.
Ceci s'étend sur la réponse de @Dunc. Voir les commentaires de la doc xml
// ReSharper disable CheckNamespace
using System.Linq;
using System.Web.Mvc;
public static class Debugg
{
/// <summary>
/// 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
/// </summary>
/// <param name="modelState">modelState</param>
/// <returns></returns>
public static ModelError[] It(ModelStateDictionary modelState)
{
var errors = modelState.Values.SelectMany(x => x.Errors).ToArray();
return errors;
}
}
Pour juste au cas où quelqu'un en aurait besoin, j'ai créé et utilisé la classe statique suivante dans mes projets
Exemple d'utilisation:
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
{
/// <summary>
/// Returns a Key/Value pair with all the errors in the model
/// according to the data annotation properties.
/// </summary>
/// <param name="errDictionary"></param>
/// <returns>
/// Key: Name of the property
/// Value: The error message returned from data annotation
/// </returns>
public static Dictionary<string, string> GetModelErrors(this ModelStateDictionary errDictionary)
{
var errors = new Dictionary<string, string>();
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();
}
}
Afficher uniquement les messages d'erreur eux-mêmes ne me suffisait pas, mais cela a suffi.
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));
Et ça marche aussi:
var query = from state in ModelState.Values
from error in state.Errors
select error.ErrorMessage;
var errors = query.ToArray(); // ToList() and so on...
Utile pour passer un tableau de messages d'erreur à View, peut-être via Json:
messageArray = this.ViewData.ModelState.Values.SelectMany(modelState => modelState.Errors, (modelState, error) => error.ErrorMessage).ToArray();
De plus, ModelState.Values.ErrorMessage
peut être vide, mais ModelState.Values.Exception.Message
peut indiquer une erreur.
Je ne sais pas que c'est le problème dans mon cas, parfois je reçois un message dans la section ErrorMessage de ModelState et parfois dans le message d'exception de l'erreur ModelState.
Par conséquent, j'ai créé une méthode qui peut traiter les deux scénarios. J'espère que cela aidera tout le monde ici ..
public static string GetErrorMessageFromModelState(ModelStateDictionary modelState)
{
string errorMessage = string.Empty;
try
{
string[] errorMessageList = (from m in modelState
where m.Value.Errors.Count > 0
select string.Join(", ", m.Value.Errors.Select(x =>
!string.IsNullOrEmpty(x.ErrorMessage) ? x.ErrorMessage : !string.IsNullOrEmpty(x.Exception.Message) ?
x.Exception.Message.Split('\'').Length > 0 ? x.Exception.Message.Split('\'')[1].ToString() : m.Key.Split('.').Length > 1 ?
m.Key.Split('.')[1] : m.Key.Split('.')[0] : m.Key.Split('.')[0]))).ToArray();
errorMessage = string.Format("Error in Field(s): " + string.Join(", ", errorMessageList) + " {0} required.", (errorMessageList.Count() > 1 ? "are" : "is"));
}
catch (Exception ex)
{
errorMessage = ex.Message;
if (ex.InnerException != null)
errorMessage += Environment.NewLine + ex.InnerException;
}
return errorMessage;
}
Dans votre implémentation, il vous manque Classe statique, cela devrait être.
if (!ModelState.IsValid)
{
var errors = ModelStateErrorHandler.GetModelErrors(this.ModelState);
return Json(new { errors });
}
plutôt
if (!ModelState.IsValid)
{
var errors = ModelState.GetModelErrors();
return Json(new { errors });
}