嵌套属性的FluentValidation消息

本文关键字:消息 FluentValidation 属性 嵌套 | 更新日期: 2023-09-27 18:12:23

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

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。我如何将它从验证器更改为我的字符串?

嵌套属性的FluentValidation消息

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

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

这里还有另一种选择。在Startup类中配置FluentValidation时,可以设置以下configuration.ImplicitlyValidateChildProperties = true;

完整的代码看起来像这样

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

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

文档说明:

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

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

这是一个很老的问题,但对于下一代来说-您可以使用子验证器或像官方文档中描述的那样内联定义子规则:https://fluentvalidation.net/start#complex-properties

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

在常见的情况下,我们有一个N层的应用程序,在ASP.net层,对于View Models, DTOsCommands的验证(例如实现快速失败验证),只需启用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

您可以使用ChildRules方法:

public class AValidator : AbstractValidator<A>
{
    public AValidator()
    {
        RuleFor(x => x.Prop)
            .ChildRules(x => x.RuleFor(b => b.Id))
            .NotEmpty()
            .WithMessage("Please ensure you have selected the A object");
    }
}
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;
            });
    }