Validation de ViewModel pour une liste

J’ai la définition de vue suivante

public class AccessRequestViewModel { public Request Request { get; private set; } public SelectList Buildings { get; private set; } public List Persons { get; private set; } } 

Donc, dans ma demande, il doit y avoir au moins une personne pour une demande d’access. Quelle approche pourriez-vous utiliser pour valider? Je ne veux pas que cette validation se produise dans mon contrôleur, ce qui serait simple à faire. Le seul choix est-il un atsortingbut de validation personnalisé?

Edit: Effectue actuellement cette validation avec FluentValidation (jolie bibliothèque!)

 RuleFor(vm => vm.Persons) .Must((vm, person) => person.Count > 0) .WithMessage("At least one person is required"); 

Si vous utilisez des annotations de données pour effectuer une validation, vous pouvez avoir besoin d’un atsortingbut personnalisé:

 public class EnsureOneElementAtsortingbute : ValidationAtsortingbute { public override bool IsValid(object value) { var list = value as IList; if (list != null) { return list.Count > 0; } return false; } } 

et alors:

 [EnsureOneElement(ErrorMessage = "At least a person is required")] public List Persons { get; private set; } 

ou pour le rendre plus générique:

 public class EnsureMinimumElementsAtsortingbute : ValidationAtsortingbute { private readonly int _minElements; public EnsureMinimumElementsAtsortingbute(int minElements) { _minElements = minElements; } public override bool IsValid(object value) { var list = value as IList; if (list != null) { return list.Count >= _minElements; } return false; } } 

et alors:

 [EnsureMinimumElements(1, ErrorMessage = "At least a person is required")] public List Persons { get; private set; } 

Personnellement, j’utilise FluentValidation.NET au lieu des annotations de données pour effectuer la validation car je préfère la logique de validation impérative au lieu du déclaratif. Je pense que c’est plus puissant. Donc, ma règle de validation ressemblerait simplement à ceci:

 RuleFor(x => x.Persons) .Must(x => x.Count > 0) .WithMessage("At least a person is required"); 

Un autre moyen possible de gérer les validations de comptage pour les membres de la collection d’object de modèle de vue consiste à avoir une propriété calculée renvoyant la collection ou le nombre de listes. Un RangeAtsortingbute peut ensuite être appliqué comme dans le code ci-dessous pour appliquer la validation du compte:

 [Range(minimum: 1, maximum: Int32.MaxValue, ErrorMessage = "At least one item needs to be selected")] public int ItemCount { get { return Items != null ? Items.Length : 0; } } 

Dans le code ci-dessus, ItemCount est un exemple de propriété calculée sur un modèle de vue en cours de validation et Items est un exemple de propriété de collection de membres dont le nombre est en cours de vérification. Dans cet exemple, au moins un élément est appliqué au membre de la collection et la limite maximale est la valeur maximale qu’un entier peut prendre, ce qui est, pour la plupart des raisons pratiques, illimité. Le message d’erreur sur l’échec de la validation peut également être défini via le membre ErrorMessage du RangeAtsortingbute dans l’exemple ci-dessus.

La réponse de Darin est bonne mais la version ci-dessous vous donnera automatiquement un message d’erreur utile.

 public class MinimumElementsAtsortingbute : ValidationAtsortingbute { private readonly int minElements; public MinimumElementsAtsortingbute(int minElements) { this.minElements = minElements; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var list = value as IList; var result = list?.Count >= minElements; return result ? ValidationResult.Success : new ValidationResult($"{validationContext.DisplayName} requires at least {minElements} element" + (minElements > 1 ? "s" : ssortingng.Empty)); } } 

Usage:

  [MinimumElements(1)] public List Customers {get;set} [MinimumElements(2)] public List
Addresses {get;set}

Message d’erreur:

  • Les clients exigent au moins 1 élément
  • Les adresses nécessitent au moins 2 éléments

Vous avez deux choix ici, soit créer un atsortingbut de validation personnalisé et en décorer la propriété, soit vous pouvez faire en sorte que votre ViewModel implémente l’interface IValidatableObject (qui définit une méthode de validation).

J’espère que cela t’aides 🙂

Le code suivant fonctionne dans asp.net core 1.1.

 [Required, MinLength(1, ErrorMessage = "At least one item required in work order")] public ICollection Items { get; set; } 

Ce serait très propre et élégant d’avoir une validation personnalisée. Quelque chose comme ça:

 public class AccessRequestViewModel { public Request Request { get; private set; } public SelectList Buildings { get; private set; } [AtLeastOneItem] public List Persons { get; private set; } } 

Ou [MinimumItems(1)] .

Une approche pourrait consister à utiliser un constructeur privé et une méthode statique pour renvoyer une instance de l’object.

 public class AccessRequestViewModel { private AccessRequesetViewModel() { }; public static GetAccessRequestViewModel (List persons) { return new AccessRequestViewModel() { Persons = persons, }; } public Request Request { get; private set; } public SelectList Buildings { get; private set; } public List Persons { get; private set; } } 

En utilisant toujours l’usine pour instancier votre ViewModel, vous pouvez vous assurer qu’il y aura toujours une personne.

Ce n’est probablement pas idéal pour ce que vous voulez, mais cela fonctionnerait probablement.