嵌套属性的FluentValidation消息

时间:2016-10-10 09:37:40

标签: asp.net validation fluentvalidation

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

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的客户端验证期间,我仍然有一个默认的val消息:“'Id'不能为空”。如何从验证器将其更改为我的字符串?

5 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:2)

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

因此完整的代码可能看起来像这样

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

因此,您仍然会有两个验证器,一个用于类A,另一个用于类B,然后将验证类B

文档指出:

  

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

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

谢谢

答案 2 :(得分:2)

一个相当老的问题,但对于后代来说-您可以使用子验证器,也可以按照官方文档https://fluentvalidation.net/start#complex-properties

中的说明内联定义子规则。

答案 3 :(得分:1)

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

在常见的情况下,我们有一个具有N层的应用程序, 在ASP.net层中,要验证View ModelsDTOsCommands(例如,以实现快速失败验证),只需启用ImplicitlyValidateChildProperties,就像@StevenYates所说的那样:

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

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

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

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

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


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

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

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

答案 4 :(得分:0)

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