Использование FluentValidation в проекте n-уровня AspNetMvc - PullRequest
0 голосов
/ 28 сентября 2018

У меня многоуровневый проект.Уровни следующие:

  • Бизнес
  • DataAccess
  • Объекты
  • Core
  • MvcWebUI

У меня есть класс Category на уровне сущности:

public class Category : IEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
}

У меня также есть класс CategoryValidator на бизнес-уровне:

public class CategoryValidator : AbstractValidator<Category>
{
    public CategoryValidator(IEnumerable<Category> categories)
    {
        RuleFor(x => x.Name).NotEmpty().MaximumLength(50);
    }
}

У меня есть класс на уровне Core для проверки,

public class ValidatorTool
{
    public static void FluentValidate(IValidator validator, object entity)
    {
        var result = validator.Validate(entity);
        if (result.Errors.Any())
            throw new ValidationException(result.Errors);
    }
}

Я выполняю проверку на уровне Business с помощью метода FluentValidate.

Но я застрял, когда дело дошло до слоя MvcWebUI.Согласно документации FluentValidation , мне нужно применить атрибут к классу сущностей следующим образом:

[Validator(typeof(PersonValidator))]

Но поскольку бизнес-уровень ссылается на слой сущностей, я не могу добраться доКласс CategoryValidator в слое сущностей.(ссылка на кружок)

Как я могу решить эту проблему?Я создал слои неправильно?Или я должен снова определить сущности как модель в веб-слое?Пожалуйста, помогите мне.

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

Во-первых, вы, вероятно, не должны показывать свои сущности непосредственно в пользовательском интерфейсе, поэтому я рекомендую вам создать новые модели и написать валидаторы специально для них.

Предполагая, что это правильно подключено, этот подход означает, что валидаторы автоматически запускаются во время HTTP POST в приложении MVC, а состояние модели автоматически обновляется со списком ошибок.

Я используюэтот подход широко, хотя в приложениях MVC, которые вызывают внутренний API.

В большинстве моих случаев клиент MVC проверяет модель и, если он проходит проверки, затем вызывает API или сервисный уровень с моделью DTO / service / entity, которая сопоставляется с Automapper.

Проверка MVC обычно невелика и проверяет наличие обязательных полей, длин и т. Д.

API выполняет проверку еще раз, но делает это на объекте и в этот раз идет гораздо глубже, так как проверяет наличие дубликатов., недействительное состояние объекта и т. д.

Последний комментарий, который я хотел бы добавить.Я бы не бросил исключения на ошибки валидации.Пользовательский интерфейс должен использовать ModelState, а сервисный уровень возвращает результат, который клиент знает, как слить обратно в ModelState, поэтому любой сценарий приводит к тому, что пользователи получают хороший список ошибок, с которыми им приходится иметь дело.

Надеюсь, это поможет!

0 голосов
/ 01 октября 2018

Как правило, у вас есть 2 способа выполнить проверку:

  1. Проверка моделей просмотра (используется в большинстве случаев)
  2. Проверка внутренних бизнес-объектов (которая чаще всего используется с 1-й)

Для 1-й точки вы проверяете модели представления (на клиенте и сервере), которые размещены в вашем веб-проекте.В этом случае вы должны поместить просмотр валидаторов модели также в веб-проект.Атрибут [Validator(typeof(PersonValidator))] необходим для связывания параметра модели представления действия и самого действия для проверки перед выполнением действия.Как и в документации:

Внутренне, интеграция FluentValidation с MVC использует фабрику валидаторов, чтобы знать, как определить, какой валидатор должен использоваться для валидации определенного типа.По умолчанию FluentValidation поставляется с AttributedValidatorFactory, который позволяет вам связать валидатор с типом, который он проверяет, декорировав класс для валидации с атрибутом, который идентифицирует его соответствующий валидатор.

Если вы хотитедля проверки бизнес-моделей (2-й пункт), а не только для просмотра моделей, вам необходимо поместить средства проверки сущностей в бизнес-проект и зарегистрировать их в контейнере IoC ( пример с помощью Castle)Windsor) и измените инструмент проверки следующим образом:

public class ValidatorTool
{
    public static void FluentValidate<T>(IContainer container, T entity) // replace IContainer with your actual container interface name
    {
        var validator = container.Resolve<IValidator<T>>();
        var result = validator.Validate(entity);
        if (result.Errors.Any())
            throw new ValidationException(result.Errors);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...