Aspnetcore: IValidatableObject.Validate wird nur aufgerufen, wenn attributdefinierte Validierungsregeln erfolgreich sind?

Erstellt am 11. Jan. 2017  ·  3Kommentare  ·  Quelle: dotnet/aspnetcore

Hallo,

Ich habe ein Objekt mit einer [Required] -decorated-Eigenschaft, die IValidatableObject implementiert. Wenn die erforderliche Eigenschaft während der Modellbindung null ist, wird die Methode Validate() des Objekts nie aufgerufen. Wird Validate() nur aufgerufen, wenn die attributkonfigurierte Validierung erfolgreich ist?

Wenn ein Benutzer in meinem Fall ein Formular mit Validierungsfehlern abschickt, wird ihm zuerst eine Meldung über das fehlende Feld angezeigt. Sobald dieser Fehler behoben und das Formular erneut gesendet wurde, wird ihnen eine zusätzliche Fehlerliste angezeigt – diesmal von Validate() . Gibt es eine Möglichkeit, alle Validierungen gleichzeitig auszulösen, sodass dem Benutzer beim ersten Absenden des Formulars eine Liste mit _allen_ Fehlern angezeigt wird, die seine Aufmerksamkeit erfordern?

Danke,
Ben

Versionen: ASP.Net Core 1.1.0/.Net 4.6.1

Beispielcode

public class Import : IValidatableObject
{
  [Required]
  public IFormFile File { get; set; }

  public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { /* ... */ }
  //...
}

_Vom Controller:_

[HttpPost, ActionName("Index")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> IndexPost()
{
  var model = new ViewModels.Import();

  var bindingResult = await TryUpdateModelAsync(model, "", i => i.StartDate, i => i.EndDate, i => i.ImportTypeId, i => i.File);
  if (!bindingResult || ModelState.ValidationState != ModelValidationState.Valid) {
    return View(model);
  }

  // ...
}

Wenn der Benutzer das erforderliche Feld nicht ausfüllt, wird eine entsprechende Fehlermeldung angezeigt, jedoch nicht die anderen Fehlermeldungen, die Validate() möglicherweise hinzufügt.

Alle 3 Kommentare

Dieses Problem wird geschlossen, da es seit 3 ​​Monaten nicht aktualisiert wurde.

Wir entschuldigen uns, wenn dies zu Unannehmlichkeiten führt. Falls dieses Problem weiterhin auftritt, bitten wir Sie, ein neues Problem mit aktualisierten Informationen zu melden und wir werden es untersuchen.

Ich erlebe dieses Verhalten auch in Asp.Net Core 2.0, mit einer referenzierten Bibliothek, die ein IValidatableObject auf .Net Standard 2.0 abzielt.
Erst wenn alle [Required] Validierungen erfüllt sind, werden die benutzerdefinierten Validierungen in Validate() ausgeführt. Mit anderen Worten, ich muss ein Objekt mit allen erforderlichen Feldern an meinen Controller senden, bevor etwas anderes in modelstate gemeldet wird.
Das modelstate scheint sich zuerst um das Erforderliche zu kümmern, dann um alles andere. Ich habe andere Standardvalidierungsattribute wie [StringLength()] nicht ausprobiert.

Das ist wirklich ein nerviger Bug. Warum schließen?

Es ist schwer, Dinge zu entwerfen und den Leuten zu sagen, dass Datenanmerkungen funktionieren, dann finden Sie, dass IValidatableObject.Validate wie oben beschrieben ausgeführt wird. Es ist ein Problem und dies SOLLTE wieder geöffnet werden.

Inzwischen habe ich es mit Programmierern zu tun, die das für gute Programmierung halten:
öffentliche statische ListeValidateUpdateDates(ICommand-Befehl)
{
var newErrors = neue Liste();

        var validator = new DataAnnotationsValidator();
        var results = new List<ValidationResult>();
        var isValid = validator.TryValidate(command, out results);

        if (!(command is UpdatePromotionCommand cpc))
            return newErrors;

        newErrors.AddRange(ValidateDatesAreValidFormat(cpc));

        if (
          !string.IsNullOrEmpty(cpc.PurchasePeriodStart)
          && !string.IsNullOrEmpty(cpc.PurchasePeriodEnd)
          && DateTime.TryParse(cpc.PurchasePeriodStart, out DateTime purchasePeriodStartDate)
          && DateTime.TryParse(cpc.PurchasePeriodEnd, out DateTime purchasePeriodEndDate)
          && purchasePeriodStartDate > purchasePeriodEndDate
        )
        {
            newErrors.Add(new ECError("Purchase Period End cannot be before Purchase Period Start."));
        }

        if (
          !string.IsNullOrEmpty(cpc.ClaimPeriodStart)
          && !string.IsNullOrEmpty(cpc.ClaimPeriodEnd)
          && DateTime.TryParse(cpc.ClaimPeriodStart, out DateTime claimPeriodStartDate)
          && DateTime.TryParse(cpc.ClaimPeriodEnd, out DateTime claimPeriodEndDate)
          && claimPeriodStartDate > claimPeriodEndDate
        )
        {
            newErrors.Add(new ECError("Claim Period End cannot be before Claim Period Start."));
        }
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen