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?


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).


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.


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();

}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.