使用FluentValidation验证互斥字段

时间:2015-03-31 19:14:18

标签: c# fluentvalidation

我正在尝试使用FluentValidation验证三个字段中只有一个具有值。

RuleFor(x => x.Date1)
            .Must(x => !x.HasValue)
            .When(x => x.Date2.HasValue || x.Date3.HasValue)
            .WithMessage("Select only one of Date 1, Date 2 and Date 3");

其他2个日期重复此操作。正如预期的那样,这会产生匹配的每条规则的消息。

还有其他规则,所以有没有办法执行其他规则,但在这三个中的第一个失败?我已经看到了我可以在全球范围内设置 CascadeMode.StopOnFirstFailure 的地方,但我希望这三个规则之外的其他规则能够像现在一样工作。

3 个答案:

答案 0 :(得分:5)

我决定沿着另一条路走下去。它感觉很优雅,但我知道它是否通过了代码审查。

我创建了一个新属性

    public IEnumerable<DateTime?> MutuallyExclusiveDates
    {
        get
        {
            return new List<DateTime?>()
            {
                Date1,
                Date2,
                Date3
            };

        }
    }

然后我添加了这条规则

 RuleFor(x => x.MutuallyExclusiveDates)
            .Must(x => x.Count(d => d.HasValue) <= 1)
            .WithMessage("Select only one of Date 1, Date 2 and Date 3");

答案 1 :(得分:1)

我会使用像

这样的东西
RuleFor(x => x).Must(ValidateDates).WithName("something");

<snip/>

private bool ValidateDates(SomeRequest request)
{
   //perform logic and return true/false;
}

ValidateDates方法中,您可以访问完整的请求。

有关使用Must进行复杂验证的更多示例,请查看此帖子 - http://nodogmablog.bryanhogan.net/2015/04/complex-model-validation-using-fluent-validation/

答案 2 :(得分:0)

使用xor对所有3个简单的规则。无需额外的属性。除非您要强制至少一个具有一个值,否则将其删除。

 RuleFor(x => x).Cascade(CascadeMode.StopOnFirstFailure)
     .Must(x => (x.date1.HasValue ^ x.date2.HasValue) ^ x.date3.HasValue)
     .Unless(x => !x.date1.HasValue && !x.date2.HasValue && !x.date3.HasValue)
     .WithMessage("Select only one of Date 1, Date 2 and Date 3");