This article has been localized into German by the community.
Benutzerdefinierte Modellvalidierung
Wenn Sie jemals der Meinung sind, dass die in den vorherigen Artikeln beschriebenen integrierten Überprüfungsmethoden nicht ausreichen, bietet ASP.NET MVC die Möglichkeit, Ihre eigene Überprüfungslogik zu implementieren. Es mag viele Gelegenheiten geben, in denen dies eine gute Idee ist, aber Sie sollten natürlich zuerst sicherstellen, dass es nicht bereits eine einfachere, integrierte Alternative gibt, wie die Option [RegularExpression], die große Flexibilität anbietet.
Vor diesem Hintergrund ist es wirklich nicht so schwierig, Ihre eigene Validierungslogik zu implementieren. Es gibt verschiedene Möglichkeiten, dies zu tun. Lassen Sie uns also beide untersuchen. In den letzten Artikeln, in denen wir die WebUser-Klasse eingeführt haben, werden wir unsere vorherigen Beispiele erweitern. Wir fügen eine Birthday-Eigenschaft hinzu und führen dann eine benutzerdefinierte Überprüfung durch.
Benutzerdefinierte Validierung mit ValidationAttribute
Wenn Sie eine Validierung ähnlich der eingebauten Art wünschen, bei der Sie Ihren Eigenschaften "DataAnnotations" hinzufügen können (z.B.: [Required] oder [EmailAddress]), können Sie einfach eine Klasse erstellen und lassen Sie sie vom ValidationAttribute erben. Überschreiben Sie anschließend einfach die Methode IsValid() und schreiben Sie Ihre eigene Logik.
In unserem Beispiel habe ich der IsValid() -Methode eine ziemlich einfache (und vielleicht etwas alberne) Validierung hinzugefügt, um Ihnen die Möglichkeiten zu zeigen. Einiges davon hätte mit der [Range] -Validierung erledigt werden können, aber nicht alles, und das ist das Schöne an der benutzerdefinierten Validierung - Sie können so viel Logik hinzufügen, wie Sie benötigen. Sie können auch einzelne Fehlermeldungen für jede Ihrer Prüfungen zurückgeben, wie in meinem Beispiel:
public class WebUserBirthdayValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
DateTime birthday = (DateTime)value;
if(birthday.Year < 1900)
return new ValidationResult("Surely you are not THAT old?");
if(birthday.Year > 2000)
return new ValidationResult("Sorry, you're too young for this website!");
if(birthday.Month == 12)
return new ValidationResult("Sorry, we don't accept anyone born in December!");
return ValidationResult.Success;
}
}
Wie Sie sehen, führen wir mehrere Überprüfungen durch und geben eine neue Instanz der Klasse ValidationResult zurück, wenn sie übereinstimmt. Wenn keines von beiden zutrifft, können wir davon ausgehen, dass wir einen gültigen Wert haben, sodass wir das Ergebnis ValidationResult.Success zurückgeben. Das Anwenden dieser Überprüfungslogik auf die Birthday -Eigenschaft unserer WebUser -Klasse ist so einfach wie das Verwenden eines der integrierten Überprüfungsmechanismen:
public class WebUser
{
// Other properties here...
[WebUserBirthdayValidationAttribute]
public DateTime Birthday { get; set; }
}
Wenn Sie es testen möchten, benötigen Sie lediglich einen Controller, der die GET- und POST-Anforderung verarbeitet, sowie eine Ansicht mit einem FORMULAR, um die Eigenschaft wie folgt zu bearbeiten:
public class ValidationController : Controller
{
[HttpGet]
public IActionResult CustomValidation()
{
return View();
}
[HttpPost]
public IActionResult CustomValidation(WebUser webUser)
{
if(ModelState.IsValid)
return Content("Thank you!");
else
return View(webUser);
}
}
@model HelloMVCWorld.Models.WebUser
@using(var form = Html.BeginForm())
{
<div>
@Html.LabelFor(m => m.Birthday)
@Html.TextBoxFor(m => m.Birthday)
@Html.ValidationMessageFor(m => m.Birthday)
</div>
<input type="submit" value="Submit" />
}
Herzlichen Glückwunsch, Sie haben jetzt eine benutzerdefinierte Validierungslogik für eine Ihrer Eigenschaften implementiert.
Einer der wirklich coolen Vorteile dieses Ansatzes ist, dass Ihre Validierungslogik nicht unbedingt an ein bestimmtes Modell gebunden ist - anstatt Ihre Klasse WebUserBirthdayValidationAttribute aufzurufen, hätten Sie sie auch einfach BirthdayValidationAttribute nennen können und wird in allen geburtstagsbezogenen Eigenschaften Ihres Projekts wiederverwendet. Auf der anderen Seite werden Sie in Situationen geraten, in denen es absolut sinnvoll ist, Ihre Validierungslogik mit Ihrem Modell zu verknüpfen. Wie dies funktioniert, erfahren Sie im nächsten Abschnitt dieses Artikels.
Benutzerdefinierte Validierung mit IValidatableObject
Als Alternative zu dem Ansatz, den wir gerade gesehen haben, als wir eine maßgeschneiderte Version des ValidationAttribute implementiert haben, können wir unser Model die IValidatableObject -Schnittstelle implementieren lassen. Auf diese Weise können wir die für die benutzerdefinierte Validierung erforderliche Logik direkt in der Modell (Klasse) validieren, anstatt eine neue Klasse zu implementieren. Dies ist umso sinnvoller, wenn die Validierungslogik, die Sie hinzufügen möchten, mehr als eine Eigenschaft betrifft, da die Validierung jetzt nicht mehr an eine einzelne, bestimmte Eigenschaft gebunden ist.
Die IValidatableObject-Schnittstelle verfügt nur über eine einzige Methode: Validate(). Es sollte die gesamte erforderliche Logik enthalten, die nicht über die integrierten Mechanismen auf Ihre Eigenschaften angewendet werden kann. Sie können also weiterhin die reguläre und die benutzerdefinierte Validierung kombinieren. Wir haben genau das in dieser neuen Klasse mit dem Namen WebUserValidatable getan (beachten Sie jedoch, dass der Klassenname nicht das Wort "Validatable" oder etwas Ähnliches enthalten muss - Sie können es immer noch so nennen, wie Sie möchten):
public class WebUserValidatable : IValidatableObject
{
[Required(AllowEmptyStrings = true, ErrorMessage = "You must enter a value for the First Name field!")]
[StringLength(25, ErrorMessage = "The First Name must be no longer than 25 characters!")]
public string FirstName { get; set; }
[Required(ErrorMessage = "You must enter a value for the Last Name field!")]
[StringLength(50, MinimumLength = 3, ErrorMessage = "The Last Name must be between 3 and 50 characters long!")]
public string LastName { get; set; }
public DateTime Birthday { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if(this.Birthday.Year < 1900)
yield return new ValidationResult("Surely you are not THAT old?", new[] { "Birthday" });
if(this.Birthday.Year > 2000)
yield return new ValidationResult("Sorry, you're too young for this website!", new[] { "Birthday" });
if(this.Birthday.Month == 12)
yield return new ValidationResult("Sorry, we don't accept anyone born in December!", new[] { "Birthday" });
}
}
Sie werden zwei Dinge bemerken: Die Logik, die ich verwende, ist im Grunde die gleiche wie in unserem Beispiel mit dem ValidationAttribute, aber es gibt auch ein paar Unterschiede. Erstens müssen wir nichts zurückgeben, wenn die Validierung erfolgreich ist. Zweitens geben wir jetzt den Namen der Eigenschaft (oder der Eigenschaften, falls mehrere vorhanden sind) an, die für die Fehlermeldung relevant sind, in diesem Fall Geburtstag. Der Grund ist ganz einfach: Wenn die Validierung nicht mehr an eine bestimmte Eigenschaft gebunden ist, kann das Framework über "DataAnnotations" nicht wissen, auf welche Eigenschaft sich der Fehler beziehen soll, sodass wir diese Informationen bereitstellen. Dies ermöglicht es uns, die Art der Validierung, die mehrere Eigenschaften umfasst, wie folgt durchzuführen:
if((this.Birthday.Month == 12) && (this.FirstName != "Santa"))
yield return new ValidationResult("Sorry, to be born in December, we require that your first name is Santa!", new[] { "Birthday", "FirstName" });
Das Beispiel ist völlig albern, aber eine nette Demonstration, wie einfach Sie eine oder mehrere Ihrer Validierungsprüfungen für mehrere Eigenschaften durchführen können. Wenn Sie in Ihrem Markup für jeden der Felder individuelle Fehlermeldungen haben, wird die generierte Fehlermeldung nun an beide Felder angehängt.
Wenn Sie dies in Aktion sehen möchten, fügen Sie Ihrem Projekt einfach Controller-Logik und eine passende Ansicht mit FORM hinzu:
public class ValidationController : Controller
{
[HttpGet]
public IActionResult CustomValidation()
{
return View();
}
[HttpPost]
public IActionResult CustomValidation(WebUserValidatable webUser)
{
if(ModelState.IsValid)
return Content("Thank you!");
else
return View(webUser);
}
}
@model HelloMVCWorld.Models.WebUserValidatable
@using(var form = Html.BeginForm())
{
<div>
@Html.LabelFor(m => m.FirstName)
@Html.TextBoxFor(m => m.FirstName)
@Html.ValidationMessageFor(m => m.FirstName)
</div>
<div>
@Html.LabelFor(m => m.LastName)
@Html.TextBoxFor(m => m.LastName)
@Html.ValidationMessageFor(m => m.LastName)
</div>
<div>
@Html.LabelFor(m => m.Birthday)
@Html.TextBoxFor(m => m.Birthday)
@Html.ValidationMessageFor(m => m.Birthday)
</div>
<input type="submit" value="Submit" />
}
Zusammenfassung
Das Implementieren einer eigenen benutzerdefinierten Überprüfungslogik in Ihrem ASP.NET MVC-Projekt ist sehr einfach. Es gibt zwei Methoden, eine, die direkt mit einer bestimmten Eigenschaft verknüpft ist, und eine, die direkt mit dem Modell verknüpft ist, sodass Sie mehrere Eigenschaften gleichzeitig validieren können.