ModelState.AddModelError - Wie kann ich einen Fehler hinzufügen, der nicht für eine Eigenschaft gilt?

188

Ich checke meine Datenbank ein, Create(FooViewModel fvm){...}um festzustellen, ob die fvm.prop1und fvm.prop2bereits in dieser Kombination vorhanden sind. Wenn ja, möchte ich dem Modellstatus einen Fehler hinzufügen und dann die gesamte Ansicht zurückgeben. Ich habe es versucht:

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

... aber ich bekomme keine Anzeige von Fehlern in der Html.ValidationSummary, wo ich annehme, dass sie erscheinen würden. Ich habe den Verdacht, dass "Model" nicht der richtige Schlüssel ist, aber ich konnte nichts a la Google finden.

Scott Baker
quelle

Antworten:

328

Ich bin schließlich auf ein Beispiel für die Verwendung gestoßen, nach der ich gesucht habe - um dem Modell im Allgemeinen einen Fehler zuzuweisen, anstatt einer seiner Eigenschaften, wie Sie es normalerweise nennen:

ModelState.AddModelError(string key, string errorMessage);

Verwenden Sie jedoch eine leere Zeichenfolge für den Schlüssel:

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

Die Fehlermeldung wird <%: Html.ValidationSummary() %>wie erwartet angezeigt.

Scott Baker
quelle
21
In diesem Fall denke ich: Warum gibt es keine Methode wie ModelState.AddError(errorMessage)oder ModelState.AddGlobalError(errorMessage)... es wäre intuitiv und einfacher herauszufinden, wie eine Fehlermeldung hinzugefügt werden kann, die nicht mit den Eigenschaften eines Modells zusammenhängt.
Rubens Mariuzzo
@Rubens: Stimmt, aber Sie können eine solche Methode einfach mit Erweiterungsmethoden hinzufügen.
Johnny5
2
Sie können den Fehler auch mit@Html.ValidationMessage(string.Empty)
Ben Foster
Der Schlüssel ist die Eigenschaft Ihres Modells, die an die Ansicht gebunden ist - das hat den Fehler -, nur um klar zu sein.
Niico
1
Die ValidationSummaryErrors(bool excludePropertyErrors)Überladung zeigt alle Validierungsfehler an, wenn das Argument falsch ist, oder nur nicht eigenschaftsspezifische (key = "") Fehler, wenn das Argument wahr ist.
Suncat2000
26

Sie können den Modellfehler für jede Eigenschaft Ihres Modells hinzufügen. Ich schlage vor, wenn nichts mit dem Erstellen einer neuen Eigenschaft zu tun hat.

Als Beispiel prüfen wir, ob die E-Mail bereits in der Datenbank verwendet wird, und fügen den Fehler der E-Mail-Eigenschaft in der Aktion hinzu. Wenn ich die Ansicht zurückgebe, wissen sie, dass ein Fehler vorliegt, und wie sie mithilfe von angezeigt werden

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

und

ModelState.AddModelError("Email", Resources.EmailInUse);
VinnyG
quelle
1
Dies scheint in meinem Fall nicht intuitiv zu sein. Ich überprüfe, ob eine bestimmte Kombination von col1 und col2 bereits in der Datenbank vorhanden ist. Daher scheint es nicht richtig zu sein, die IsDuplicateOfAnotherRow-Eigenschaft in meinem ViewModel zu haben. Es stellt sich heraus, dass Sie Ihrem Modell einen Fehler hinzufügen können - siehe meine Antwort.
Scott Baker
1
Gibt es eine Möglichkeit, die Zeichenfolge "E-Mail" für AddModelError abzurufen, ohne eine fragile Literalzeichenfolge zu verwenden? Wie (m=>m.email).SomeMagicToString()?
Snekse
Ich denke nicht, du musst mit magischer Schnur gehen ... nicht die beste, aber immer noch eine gute Lösung
VinnyG
4
Der nameofin C # 6.0 kommende Operator löst dieses Problem mit magischen Zeichenfolgen. msdn.microsoft.com/en-us/magazine/dn802602.aspx
RJ Cuthbertson
3

Das Einfügen der Modellpunkt-Eigenschaft in Zeichenfolgen hat bei mir funktioniert: ModelState.AddModelError("Item1.Month", "This is not a valid date");

Chris
quelle
2
Das würde zwar einen ungültigen Monat in Ihrer Benutzeroberfläche anzeigen, löst aber nicht das ursprüngliche Problem.
Scott Baker
2
Das ursprüngliche Problem besteht darin, nicht zu verstehen, was "Schlüssel" in der Methode darstellt. Dies gibt Aufschluss darüber, wie "key" funktioniert. Daher ist es gut zu wissen, dass key nicht nur ein Eigenschaftsname sein muss, sondern auch auf verschachtelte Eigenschaften oder den speziellen Wert String.Empty verweisen kann.
Triynko