Aspnetcore: IValidatableObject.Validate Appelé uniquement si les règles de validation définies par les attributs réussissent ?

Créé le 11 janv. 2017  ·  3Commentaires  ·  Source: dotnet/aspnetcore

Bonjour,

J'ai un objet avec une propriété [Required] -decorated qui implémente IValidatableObject . Pendant la liaison de modèle, si la propriété requise est null, la méthode Validate() n'est jamais appelée. Est-ce que Validate() n'est appelé que si la validation configurée par attribut réussit ?

Dans mon cas, si un utilisateur soumet un formulaire avec des erreurs de validation, il voit d'abord un message concernant le champ manquant. Ensuite, une fois cette erreur résolue et le formulaire soumis à nouveau, une liste d'erreurs supplémentaire leur est présentée, cette fois produite par Validate() . Existe-t-il un moyen de déclencher toutes les validations en même temps afin que l'utilisateur se voie présenter une liste de _toutes_ les erreurs nécessitant son attention lors de la première soumission du formulaire ?

Merci,
Ben

Versions : ASP.Net Core 1.1.0/.Net 4.6.1

Exemple de code

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

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

_Depuis le contrôleur :_

[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);
  }

  // ...
}

Si l'utilisateur ne remplit pas le champ requis, il verra un message d'erreur à ce sujet, mais il ne verra pas les autres messages d'erreur que Validate() pourrait ajouter.

Tous les 3 commentaires

Ce problème est fermé car il n'a pas été mis à jour depuis 3 mois.

Nous nous excusons si cela cause un inconvénient. Nous vous demandons si vous rencontrez toujours ce problème, veuillez enregistrer un nouveau problème avec des informations mises à jour et nous enquêterons.

Je rencontre également ce comportement dans Asp.Net Core 2.0, avec une bibliothèque référencée contenant un IValidatableObject ciblant .Net Standard 2.0.
Ce n'est que lorsque toutes les validations [Required] sont satisfaites que les validations personnalisées dans Validate() sont exécutées. En d'autres termes, je dois publier un objet sur mon contrôleur avec tous les champs obligatoires avant que quoi que ce soit d'autre ne soit signalé dans modelstate.
Le modelstate semble se soucier d'abord de l'exigence, puis de tout le reste. Je n'ai pas essayé d'autres attributs de validation standard comme [StringLength()] .

C'est un bug vraiment ennuyeux. Pourquoi le fermer ?

Il est difficile d'organiser les choses et de dire aux gens que les annotations de données fonctionnent, alors vous trouvez que IValidatableObject.Validate s'exécute comme ci-dessus. C'est un problème et cela DEVRAIT être rouvert.

En attendant, je dois traiter avec des programmeurs qui pensent que c'est une bonne programmation :
liste statique publiqueValidateUpdateDates (commande ICommand)
{
var newErrors = nouvelle 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."));
        }
Cette page vous a été utile?
0 / 5 - 0 notes