【问题标题】:FluentValidation message for nested properties嵌套属性的 FluentValidation 消息
【发布时间】:2016-10-10 09:37:40
【问题描述】:

我有一个具有复杂属性的类:

public class A
{
    public B Prop { get; set; }
}

public class B
{
    public int Id { get; set; }
}

我添加了一个验证器:

public class AValidator : AbstractValidator<A>
{
    public AValidator()
    {
        RuleFor(x => x.A.Id)
            .NotEmpty()
            .WithMessage("Please ensure you have selected the A object");            
    }
}

但是在A.Id 的客户端验证期间,我仍然有一条默认验证消息:'Id' must not be empty。如何从验证器将其更改为我的字符串?

【问题讨论】:

  • 这似乎是not supported。建议的替代方法是使用平面视图模型并避免对象嵌套
  • 这是受支持的,具体取决于您想在哪里使用验证器。在下面查看我的答案。

标签: c# asp.net validation fluentvalidation


【解决方案1】:

您可以通过对嵌套对象使用自定义验证器来实现此目的:

public class AValidator : AbstractValidator<A>
{
    public AValidator()
    {
        RuleFor(x => x.B).NotNull().SetValidator(new BValidator());
    }

    class BValidator : AbstractValidator<B>
    {
        public BValidator()
        {
            RuleFor(x => x.Id).NotEmpty().WithMessage("Please ensure you have selected the B object");
        }
    }
}

public class A
{
    public B B { get; set; }
}

public class B
{
    public int Id { get; set; }
}

【讨论】:

    【解决方案2】:

    这里有一个替代选项。在 Startup 类中配置 FluentValidation 时,您可以设置以下 configuration.ImplicitlyValidateChildProperties = true;

    所以完整的代码可能看起来像这样

    services
        .AddMvc()
        .AddFluentValidation(configuration =>
            {
                ...
                configuration.ImplicitlyValidateChildProperties = true;
                ...
            })
    

    所以您仍然有两个验证器,一个用于A 类,一个用于B 类,然后将验证B 类。

    文档说明:

    如果可以找到匹配的验证器,是否应隐式验证子属性。默认情况下这是 false,您应该使用 SetValidator 连接子验证器。

    因此将其设置为 true 意味着将验证子属性。

    【讨论】:

    • 这很有趣,你知道如何进行单元测试吗?
    • 我会对如何将它与规则集合并感兴趣。当您的嵌套对象将被验证时,如何定义有效的验证规则集?
    【解决方案3】:

    相当老的问题,但对于后代 - 您可以使用子验证器或内联定义子规则,如官方文档中所述:https://fluentvalidation.net/start#complex-properties

    【讨论】:

      【解决方案4】:

      这取决于您想在哪里使用验证器:

      在常见的场景中,我们有一个 N 层的应用程序, 在 ASP.net 层,对于View ModelsDTOsCommands 的验证(例如实现快速失败验证),只需启用ImplicitlyValidateChildProperties,正如@StevenYates 所说:

      services.AddMvc().AddFluentValidation(fv => 
      {
          fv.ImplicitlyValidateChildProperties = true;
      });
      

      启用此功能后,不必使用 SetValidator 指定子验证器,MVC 的验证基础结构将递归地尝试自动为每个属性自动查找验证器。

      恕我直言,这很棒,因为除了实用之外,它还可以防止我们忘记一些.SetValidator (...)

      请注意,如果启用此行为,则不应使用 SetValidator 对于子属性,否则验证器将被执行两次。

      文档:https://docs.fluentvalidation.net/en/latest/aspnet.html#implicit-vs-explicit-child-property-validation


      但是,除此之外(或取而代之),如果您想在其他层(例如 Domain)中使用 FluentValidation,您需要使用 SetValidator(...) 方法,如 @t138 所说,例如:

      RuleFor(customer => customer.Address).SetValidator(new AddressValidator());
      

      文档:https://docs.fluentvalidation.net/en/latest/start.html#complex-properties

      【讨论】:

        【解决方案5】:
        public class A
        {
            public B B { get; set; }
        }
        
        public class B
        {
            public int Id { get; set; }
        }
        
        public class AValidator : AbstractValidator<A>
        {
            public AValidator()
            {
                RuleFor(x => x.B).NotNull().SetValidator(new BValidator());
            }
        
            class BValidator : AbstractValidator<B>
            {
                public BValidator()
                {
                    RuleFor(x => x.Id).NotEmpty().WithMessage("message ....");
        
                }
            }
        }
        
        ----------------------------------------------------------------------
          public void ConfigureServices(IServiceCollection services)
           {
                  
                    services.AddControllers().AddFluentValidation(fv =>
                    {
                        fv.RegisterValidatorsFromAssemblyContaining<Startup>();
                        fv.ImplicitlyValidateChildProperties = true;
                    });
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-26
          • 2012-08-19
          • 1970-01-01
          • 2014-09-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多