IValidatableObject vs. Single Responsibility

12

Podoba mi się punkt rozszerzalności MVC, pozwalający modelom widoków na implementację IValidatableObject i dodanie niestandardowej weryfikacji.

Staram się, aby moje Kontrolery były szczupłe, ponieważ ten kod jest jedyną logiką sprawdzania poprawności:

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

Na przykład model widoku logowania implementuje IValidatableObject, pobiera obiekt ILoginValidator poprzez wstrzyknięcie konstruktora:

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

Wygląda na to, że Ninject, wstrzykiwanie instancji do modeli widoku nie jest tak naprawdę powszechną praktyką, może nawet być anty-wzorem?

Czy to dobre podejście? Czy jest lepszy?

Borys Jankow
źródło
Jeśli chcesz sprawdzić poprawność w oddzielnym obiekcie, spróbuj FluentValidation. Zobacz fluentvalidation.codeplex.com/wikipage?title=mvc .
rmac
+1 Świetny pomysł, aby wstrzyknąć oddzielną klasę walidatora, która rozwiązuje mój problem, w którym muszę uzyskać dostęp do informacji z bazy danych w celu sprawdzenia poprawności!
magnatyczny

Odpowiedzi:

7

Osobiście dla mnie twój projekt wydaje się czysty.

IValidatableObject oznacza, że ​​model widoku zapewni pewną walidację, której nie można zapewnić za pomocą prostych atrybutów - wstrzyknięcie prawdziwego walidatora, który wywoła usługi / bazy danych / cokolwiek, co utrzyma twój projekt w czystości i zapewni, że nie naruszysz zasady pojedynczej odpowiedzialności - modele widoków są odpowiedzialny zasadniczo za przesyłanie danych i sprawdzanie poprawności przesyłanych danych (niezależnie od tego, czy są to atrybuty, czy IValidatableObject, czy oba).

David_001
źródło
4

Posiadanie dedykowanego obiektu do sprawdzania poprawności gwarantuje, że rzeczywiście szanujesz SRP - co zresztą już miało miejsce, ponieważ typowym obowiązkiem modelu widoku jest sprawdzenie jego danych.

Jeśli chodzi o wstrzykiwanie instancji do modeli widoku, nie widzę w tym nic złego. Praktycznie nie ma ograniczeń co do tego, co można wstrzyknąć.

guillaume31
źródło
3

Zamiast wstrzykiwać ILoginValidator do konstruktora maszyny wirtualnej, możesz użyć ValidationContext (który jest argumentem funkcji IValidatableObject.Validate ()), aby uzyskać Validator.

public IEnumerable<ValidationResult> Validate(ValidationContext vc)
{

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

}
Kelly
źródło