IValidatableObject vs Single Responsibility

12

Mir gefällt der Extnesibility Point von MVC, mit dem Ansichtsmodelle IValidatableObject implementieren und benutzerdefinierte Validierungen hinzufügen können.

Ich versuche, meine Controller schlank zu halten, wobei dieser Code die einzige Validierungslogik ist:

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

Ein Anmeldeansichtsmodell implementiert beispielsweise IValidatableObject und ruft das ILoginValidator-Objekt über die Konstruktorinjektion ab:

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

Es scheint, dass Ninject, das Injizieren von Instanzen in Ansichtsmodelle, keine gängige Praxis ist, vielleicht sogar ein Anti-Pattern ist?

Ist das ein guter Ansatz? Gibt es eine bessere?

Boris Yankov
quelle
Wenn Sie die Validierung in einem separaten Objekt durchführen möchten, versuchen Sie es mit FluentValidation. Siehe fluentvalidation.codeplex.com/wikipage?title=mvc .
rmac
+1 Tolle Idee, eine separate Validator-Klasse einzufügen, die mein Problem löst, wenn ich zur Validierung auf Datenbankinformationen zugreifen muss!
Magnattic

Antworten:

7

Persönlich scheint mir Ihr Design sauber.

IValidatableObject bedeutet, dass das Ansichtsmodell eine Validierung bereitstellt, die nicht durch einfache Attribute bereitgestellt werden kann - durch Injizieren des echten Validators, der Dienste / Datenbanken / alles aufruft, was Ihr Design sauber hält und sicherstellt, dass Sie nicht gegen das Prinzip der einmaligen Verantwortung verstoßen - View Models are Verantwortlich im Wesentlichen für die Übertragung von Daten und die Validierung der übertragenen Daten (ob über Attribute oder IValidatableObject oder beides).

David_001
quelle
4

Ein dediziertes Objekt für die Validierung garantiert, dass Sie SRP tatsächlich einhalten - was ohnehin schon der Fall war, da es eine typische Verantwortung eines Ansichtsmodells ist, seine Daten zu validieren.

Was das Injizieren von Instanzen in Ansichtsmodelle angeht, kann ich daran nichts falsches erkennen. Es gibt praktisch keine Grenzen, was in was injiziert werden kann.

guillaume31
quelle
3

Anstatt den ILoginValidator in Ihren VM-Konstruktor einzufügen, können Sie den ValidationContext (der das Argument für IValidatableObject.Validate () ist) verwenden, um den Validator abzurufen.

public IEnumerable<ValidationResult> Validate(ValidationContext vc)
{

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

}
Kelly
quelle