IValidatableObject vs Single Responsibility

12

Мне нравится точка расширяемости MVC, позволяющая представлениям моделей реализовывать IValidatableObject и добавлять настраиваемую проверку.

Я стараюсь поддерживать свои контроллеры стройными, используя этот код в качестве единственной логики проверки:

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

Например, модель представления входа в систему реализует IValidatableObject, получает объект ILoginValidator посредством внедрения конструктора:

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

Кажется, что Ninject, внедрение экземпляров в модели представлений, на самом деле не является обычной практикой, может быть даже анти-паттерном?

Это хороший подход? Есть ли лучший?

Борис Янков
источник
Если вы хотите проверить в отдельном объекте, попробуйте FluentValidation. См. Fluentvalidation.codeplex.com/wikipage?title=mvc .
rmac
+1 Отличная идея внедрить отдельный класс Validator, который решает мою проблему, когда я должен получить доступ к информации базы данных для проверки!
Magnattic

Ответы:

7

Лично мне ваш дизайн кажется чистым.

IValidatableObject означает, что модель представления обеспечит некоторую проверку, которая не может быть обеспечена простыми атрибутами - введением реального средства проверки, который будет вызывать службы / базы данных / что угодно, что поддерживает ваш дизайн в чистоте и гарантирует, что вы не нарушаете принцип единой ответственности - модели представления ответственный, по существу, за передачу данных и проверку данных, которые передаются (будь то через атрибуты или IValidatableObject или оба).

David_001
источник
4

Наличие выделенного объекта для проверки гарантирует, что вы действительно соблюдаете SRP - что в любом случае уже имело место, поскольку для модели представления является типичной обязанностью проверять свои данные.

Что касается внедрения экземпляров в модели представления, я не вижу в этом ничего плохого. Там практически нет предела тому, что может быть введено во что.

guillaume31
источник
3

Вместо внедрения ILoginValidator в конструктор виртуальной машины вы можете использовать ValidationContext (который является аргументом для IValidatableObject.Validate ()), чтобы получить свой Validator.

public IEnumerable<ValidationResult> Validate(ValidationContext vc)
{

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

}
Келли
источник