【问题标题】:FluentValidation usage in AspNetMvc n-tier projectAspNetMvc n 层项目中的 FluentValidation 使用
【发布时间】:2018-10-12 21:59:54
【问题描述】:

我有一个多层项目。层数如下:

  • 商务
  • 数据访问
  • 实体
  • 核心
  • 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);
    }
}

我在核心层有一个类用于验证。

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

我正在使用 FluentValidate 方法在业务层中执行验证。

但是当涉及到 MvcWebUI 层时,我被卡住了。根据FluentValidation documentation,我需要给实体类应用一个属性如下:

[Validator(typeof(PersonValidator))]

但是由于业务层引用了实体层,所以无法到达实体层中的CategoryValidator类。 (圈出参考)

我该如何解决这个问题? 我是否错误地创建了图层? 或者我应该在 Web 层中再次将实体定义为模型? 请帮帮我。

【问题讨论】:

    标签: asp.net-mvc fluentvalidation


    【解决方案1】:

    首先,您可能不应该直接在 UI 中公开您的实体,因此我建议您在那里创建新模型并专门为它们编写验证器。

    假设连接正确,这种方法意味着验证器会在 MVC 应用程序中的 HTTP POST 期间自动触发,并且模型状态会自动更新为错误列表。

    我广泛使用这种方法,尽管在调用内部 API 的 MVC 应用程序中。

    在我的大多数情况下,MVC 客户端会验证模型,如果它通过检查,然后在使用 Automapper 映射的 DTO/服务/实体模型之后调用 API 或服务层。

    MVC 验证通常很简单,会检查必填字段、长度等。

    API 会再次进行验证,但它会在实体上进行验证,这一次会更深入,因为它会检查重复项、无效的实体状态等。

    我想补充的最后一条评论。我不会对验证错误抛出异常。 UI 应该使用 ModelState 并且服务层返回一个结果,客户端知道如何合并回 ModelState,因此任何一种情况都会导致用户得到一个很好的错误列表来处理。

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      通常你有两种方法来执行验证:

      1. 验证视图模型(在大多数情况下使用)
      2. 内部业务实体验证(最常与 1-st 一起使用)

      对于第一点,您验证放置在您的 Web 项目中的视图模型(在客户端和服务器上)。在这种情况下,您也应该在 Web 项目中放置 视图模型验证器[Validator(typeof(PersonValidator))] 属性用于链接动作的视图模型参数和动作本身以在动作执行之前执行验证。如文档中所述:

      在内部,FluentValidation 的 MVC 集成使用验证器工厂来了解如何确定应该使用哪个验证器来验证特定类型。默认情况下,FluentValidation 附带一个 AttributedValidatorFactory,它允许您将验证器链接到它验证的类型,方法是装饰类以使用标识其相应验证器的属性进行验证。

      如果您想验证业务模型(第 2 点),而不是/不仅仅是查看模型,您需要将 实体验证器 放置到业务项目并将它们注册到您的 IoC 容器中 (@987654321 @with 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);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-03-09
        • 2012-08-25
        • 2011-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多