IValidatableObject vs responsabilité unique

12

J'aime le point d'extnesibilité de MVC, permettant aux modèles de vue d'implémenter IValidatableObject et d'ajouter une validation personnalisée.

J'essaie de garder mes contrôleurs allégés, ce code étant la seule logique de validation:

if (!ModelState.IsValid)
    return View(loginViewModel);

Par exemple, un modèle de vue de connexion implémente IValidatableObject, obtient l'objet ILoginValidator via une injection de constructeur:

public interface ILoginValidator
{
    bool UserExists(string email);
    bool IsLoginValid(string userName, string password);
}

Il semble que Ninject, l'injection d'instances dans les modèles de vue n'est pas vraiment une pratique courante, peut-être même un anti-modèle?

Est-ce une bonne approche? Y en a t-il un meilleur?

Boris Yankov
la source
Si vous souhaitez la validation dans un objet séparé, essayez FluentValidation. Voir fluentvalidation.codeplex.com/wikipage?title=mvc .
rmac
+1 Excellente idée d'injecter une classe Validator distincte, qui résout mon problème où je dois accéder aux informations de la base de données pour la validation!
magnattic

Réponses:

7

Personnellement, votre design me semble propre.

IValidatableObject signifie que le modèle de vue fournira une validation qui ne peut pas être fournie par de simples attributs - injectant le vrai validateur qui appellera les services / bases de données / tout ce qui maintient votre conception propre et vous assure de ne pas violer le principe de responsabilité unique - Les modèles de vue sont responsable, essentiellement, du transfert des données et de la validation des données qui sont transférées (que ce soit par le biais d'attributs ou IValidatableObject ou les deux).

David_001
la source
4

Avoir un objet dédié pour la validation garantit que vous respectez bien SRP - ce qui était déjà le cas de toute façon car c'est une responsabilité typique d'un modèle de vue de valider ses données.

En ce qui concerne l'injection d'instances dans les modèles de vue, je ne vois rien de mal à cela. Il n'y a pratiquement aucune limite à ce qui peut être injecté dans quoi.

guillaume31
la source
3

Au lieu d'injecter ILoginValidator dans votre constructeur de machine virtuelle, vous pouvez utiliser ValidationContext (qui est l'argument de IValidatableObject.Validate ()) pour obtenir votre validateur.

public IEnumerable<ValidationResult> Validate(ValidationContext vc)
{

var loginValidator = (ILoginValidator)vc.GetService(typeof(ILoginValidator));
return loginValidator.Validate();

}
Kelly
la source