Comment obtenir la collection d'erreurs d'état du modèle dans ASP.NET MVC?

145

Comment obtenir la collection d'erreurs dans une vue?

Je ne souhaite pas utiliser le récapitulatif de validation Html Helper ou le message de validation. Au lieu de cela, je veux vérifier les erreurs et, le cas échéant, les afficher dans un format spécifique. Également sur les contrôles d'entrée, je souhaite rechercher une erreur de propriété spécifique et ajouter une classe à l'entrée.

PS J'utilise le moteur Spark View mais l'idée devrait être la même.

Alors j'ai pensé que je pourrais faire quelque chose comme ...

<if condition="${ModelState.Errors.Count > 0}">
  DispalyErrorSummary()
</if>

....and also...

<input type="text" value="${Model.Name}" 
       class="?{ModelState.Errors["Name"] != string.empty} error" />

....

Ou quelque chose comme ça.

METTRE À JOUR

Ma solution finale ressemblait à ceci:

<input type="text" value="${ViewData.Model.Name}" 
       class="text error?{!ViewData.ModelState.IsValid && 
                           ViewData.ModelState["Name"].Errors.Count() > 0}" 
       id="Name" name="Name" />

Cela n'ajoute la classe d'erreur css que si cette propriété a une erreur.

Ryan Montgomery
la source
1
Double
Michael Freidgeim

Réponses:

210
<% ViewData.ModelState.IsValid %>

ou

<% ViewData.ModelState.Values.Any(x => x.Errors.Count >= 1) %>

et pour une propriété spécifique ...

<% ViewData.ModelState["Property"].Errors %> // Note this returns a collection
Chad Moran
la source
1
la propriété ModelState est de type dictionnaire pour obtenir l'erreur pour transmettre le nom de clé ViewData.ModelState ["Name"]
concernant "ViewData.ModelState [" Propriété "]. Erreurs" cela lèverait-il une exception de référence nulle s'il n'y avait pas de clé avec le nom "Propriété"? serait-il préférable de vérifier d'abord la valeur null sur le ViewData.ModelState ["Propriété"] avant de lire les erreurs?
David Hollowell - MSFT
@DaveH Oui, vous devriez tout d'abord vérifier l'existence
Alex Lyman
61

Pour simplement obtenir les erreurs du ModelState, utilisez ce Linq:

var modelStateErrors = this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors);
Chris McKenzie
la source
2
cela lèverait-il une exception de référence nulle s'il n'y avait pas de clé avec le nom spécifié? serait-il préférable de vérifier d'abord la valeur null sur ViewData.ModelState [clé] avant de lire les erreurs?
David Hollowell - MSFT
5
Parce que nous commençons par itérer sur this.ModelState.Keys, je ne vois pas le potentiel d'une KeyNotFoundException. Je pense que ce chèque serait exagéré.
Chris McKenzie
28

Cela vous donnera une chaîne avec toutes les erreurs séparées par des virgules

string validationErrors = string.Join(",",
                    ModelState.Values.Where(E => E.Errors.Count > 0)
                    .SelectMany(E => E.Errors)
                    .Select(E => E.ErrorMessage)
                    .ToArray());
UshaP
la source
C'est la seule chose que j'ai trouvée dans toute cette liste qui imprime réellement les erreurs! Merci
Jamie
6

Merci Chad! Pour afficher toutes les erreurs associées à la clé, voici ce que j'ai trouvé. Pour une raison quelconque, l'assistant Html.ValidationMessage de base n'affiche que la première erreur associée à la clé.

    <%= Html.ShowAllErrors(mykey) %>

HtmlHelper:

    public static String ShowAllErrors(this HtmlHelper helper, String key) {
        StringBuilder sb = new StringBuilder();
        if (helper.ViewData.ModelState[key] != null) {
            foreach (var e in helper.ViewData.ModelState[key].Errors) {
                TagBuilder div = new TagBuilder("div");
                div.MergeAttribute("class", "field-validation-error");
                div.SetInnerText(e.ErrorMessage);
                sb.Append(div.ToString());
            }
        }
        return sb.ToString();
    }
Râteau36
la source
6

En rassemblant plusieurs réponses d'en haut, voici ce que j'ai fini par utiliser:

var validationErrors = ModelState.Values.Where(E => E.Errors.Count > 0)
    .SelectMany(E => E.Errors)
    .Select(E => E.ErrorMessage)
    .ToList();

validationErrorsfinit par être un List<string>qui contient chaque message d'erreur. À partir de là, il est facile de faire ce que vous voulez avec cette liste.

entrez la description de l'image ici

Casey Crookston
la source
2

Voici le VB.

Dim validationErrors As String = String.Join(",", ModelState.Values.Where(Function(E) E.Errors.Count > 0).SelectMany(Function(E) E.Errors).[Select](Function(E) E.ErrorMessage).ToArray())
MaylorTaylor
la source
0

Si vous ne savez pas quelle propriété a causé l'erreur, vous pouvez, à l'aide de la réflexion, boucler sur toutes les propriétés:

public static String ShowAllErrors<T>(this HtmlHelper helper) {
    StringBuilder sb = new StringBuilder();
    Type myType = typeof(T);
    PropertyInfo[] propInfo = myType.GetProperties();

    foreach (PropertyInfo prop in propInfo) {
        foreach (var e in helper.ViewData.ModelState[prop.Name].Errors) {
            TagBuilder div = new TagBuilder("div");
            div.MergeAttribute("class", "field-validation-error");
            div.SetInnerText(e.ErrorMessage);
            sb.Append(div.ToString());
        }
    }
    return sb.ToString();
}

Où T est le type de votre "ViewModel".

Gérard
la source