ModelState.AddModelError - Comment puis-je ajouter une erreur qui ne concerne pas une propriété?

190

Je vérifie ma base de données Create(FooViewModel fvm){...}pour voir si fvm.prop1et fvm.prop2existe déjà dans cette combinaison; si tel est le cas, je souhaite ajouter une erreur à l'état du modèle, puis renvoyer la vue entière. J'ai essayé:

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

... mais je n'obtiens aucun affichage des erreurs dans le Html.ValidationSummary, où je suppose qu'elles apparaîtront. Je soupçonne que "Model" n'est pas la bonne clé, mais je n'ai rien trouvé à la Google.

Scott Baker
la source

Réponses:

333

Je suis finalement tombé sur un exemple d'utilisation que je recherchais - pour attribuer une erreur au modèle en général, plutôt qu'à l'une de ses propriétés, comme d'habitude, vous appelez:

ModelState.AddModelError(string key, string errorMessage);

mais utilisez une chaîne vide pour la clé:

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

Le message d'erreur se présentera dans le <%: Html.ValidationSummary() %>comme prévu.

Scott Baker
la source
25
Ce cas me fait réfléchir: pourquoi il n'y a pas de méthode comme ModelState.AddError(errorMessage)ou ModelState.AddGlobalError(errorMessage)... il serait intuitif et plus facile de savoir comment ajouter un message d'erreur non lié aux propriétés d'un modèle.
Rubens Mariuzzo
1
@Rubens: C'est vrai, mais vous pouvez facilement ajouter une telle méthode avec des méthodes d'extension.
Johnny5
2
Vous pouvez également afficher l'erreur en utilisant@Html.ValidationMessage(string.Empty)
Ben Foster
key étant la propriété de votre modèle liée à la vue - qui a l'erreur - juste pour être clair.
niico
2
La ValidationSummaryErrors(bool excludePropertyErrors)surcharge affichera toutes les erreurs de validation si son argument est faux ou seulement des erreurs non spécifiques à la propriété (clé = "") si son argument est vrai.
Suncat2000
26

Vous pouvez ajouter l'erreur de modèle sur n'importe quelle propriété de votre modèle, je suggère s'il n'y a rien de lié pour créer une nouvelle propriété.

À titre d'exemple, nous vérifions si l'e-mail est déjà utilisé dans DB et ajoutons l'erreur à la propriété Email dans l'action afin que lorsque je retourne la vue, ils sachent qu'il y a une erreur et comment l'afficher en utilisant

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

et

ModelState.AddModelError("Email", Resources.EmailInUse);
VinnyG
la source
1
Cela semble contre-intuitif dans mon cas - je vérifie si une combinaison particulière de col1 et col2 existe déjà dans la base de données, il ne semble donc pas correct d'avoir la propriété IsDuplicateOfAnotherRow sur mon ViewModel. Il s'avère que vous pouvez ajouter une erreur à votre modèle - voir ma réponse.
Scott Baker
1
Existe-t-il un moyen d'obtenir la chaîne "Email" pour AddModelError sans utiliser une chaîne littérale fragile? Comme (m=>m.email).SomeMagicToString()?
Snekse
Je ne pense pas, vous devez aller avec une corde magique ... pas la meilleure mais toujours une bonne solution
VinnyG
4
L' nameofopérateur entrant dans C # 6.0 résout ce problème de chaîne magique. msdn.microsoft.com/en-us/magazine/dn802602.aspx
RJ Cuthbertson
4

Mettre la propriété de point de modèle dans des chaînes a fonctionné pour moi: ModelState.AddModelError("Item1.Month", "This is not a valid date");

Chris
la source
2
Cela afficherait en effet un mois non valide dans votre interface utilisateur, mais cela ne résout pas le problème d'origine.
Scott Baker
2
Le problème original vient du fait de ne pas comprendre ce que «clé» représente dans la méthode. Cela met en lumière le fonctionnement de la "clé", il est donc bon de savoir que la clé ne doit pas être simplement un nom de propriété, mais peut également faire référence à des propriétés imbriquées ou à la valeur spéciale String.Empty.
Triynko