针对多个属性的 FluentValidation 规则

我有一个 FluentValidator,它有多个属性,比如 zip 和 County 等。我想创建一个规则,该规则接受两个属性,就像 RuleFor 构造一样

public class FooArgs
{
public string Zip { get; set; }
public System.Guid CountyId { get; set; }
}


public class FooValidator : AbstractValidator<FooArgs>
{
RuleFor(m => m.CountyId).Must(ValidZipCounty).WithMessage("wrong Zip County");
}

这是可行的,但是我希望将 Zip 和 County 都传递给 rue 以进行验证。实现这一目标的最佳方法是什么?

58774 次浏览

有一个 Must重载,它还为您提供了 FooArgs对象文档 给你。它允许您像下面这样轻松地将两个参数都传递到方法中:

RuleFor(m => m.CountyId).Must((fooArgs, countyId) =>
ValidZipCounty(fooArgs.Zip, countyId))
.WithMessage("wrong Zip County");

只是碰到了这个老问题,我想我有一个更简单的答案。通过将参数简化为 RuleFor,您可以轻松地将整个对象传递到自定义验证规则中。

RuleFor(m => m).Must(fooArgs =>
ValidZipCounty(fooArgs.Zip, fooArgs.countyId))
.WithMessage("wrong Zip County");

如果 ValidZipCountry方法是验证器的本地方法,并且您可以将其签名更改为采用 FooArgs,那么代码简化为

RuleFor(m => m).Must(ValidZipCounty).WithMessage("wrong Zip County");

唯一的缺点是结果验证错误中的 PropertyName将是一个空字符串。这可能会给您的验证显示代码带来问题。但是并不清楚错误属于哪个属性,是 ContryId还是 Zip,所以这是有意义的。

那么:

RuleFor(m => new {m.CountyId, m.Zip}).Must(x => ValidZipCounty(x.Zip, x.CountyId))
.WithMessage("Wrong Zip County");

在我的示例中,如果另一个属性不为空,我需要根据需要标记一个属性(下面的示例中为 x.RequiredProperty)(下面的示例中为 x.ParentProperty)。我最终使用了 When语法:

RuleFor(x => x.RequiredProperty).NotEmpty().When(x => x.ParentProperty != null);

或者,如果你对一个常用的 when 子句有一个以上的规则,你可以这样写:

When(x => x.ParentProperty != null, () =>
{
RuleFor(x => x.RequiredProperty).NotEmpty();
RuleFor(x => x.OtherRequiredProperty).NotEmpty();
});

When语法的定义如下:

/// <summary>
/// Defines a condition that applies to several rules
/// </summary>
/// <param name="predicate">The condition that should apply to multiple rules</param>
/// <param name="action">Action that encapsulates the rules.</param>
/// <returns></returns>
public IConditionBuilder When (Func<T, bool> predicate, Action action);