我有一个具有复杂属性的类:
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'不能为空”。如何从验证器将其更改为我的字符串?
答案 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 Models
,DTOs
或Commands
(例如,以实现快速失败验证),只需启用ImplicitlyValidateChildProperties
,就像@StevenYates所说的那样:
services.AddMvc().AddFluentValidation(fv =>
{
fv.ImplicitlyValidateChildProperties = true;
});
启用此功能后,MVC的验证基础结构将递归地尝试自动为每个属性自动查找验证器,而不必使用SetValidator
指定子验证器。
恕我直言,这很棒,因为除了实用之外,它还可以防止我们忘记一些.SetValidator (...)
!
请注意,如果启用此行为,则不应使用SetValidator 子属性,否则验证器将执行两次。
但是,除此之外(或代替),如果您想在其他层(例如,域)中使用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;
});
}