嵌套属性的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
。我如何将它从验证器更改为我的字符串?
您可以通过使用嵌套对象的自定义验证器来实现这一点:
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
, DTOs
或Commands
的验证(例如实现快速失败验证),只需启用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;
});
}