使用FluentValidation验证互斥字段

8

我正在尝试使用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");

这个过程对另外两个日期也是重复的。正如所预期的那样,这会为每个匹配规则生成一条消息。
还涉及其他规则,是否有一种方法可以执行其他规则,但在这三个规则中的第一个失败?我看到可以全局设置 CascadeMode.StopOnFirstFailure ,但我希望这三个规则之外的其他规则像当前一样工作。

1
将这三条规则合并为一个 .Custom(...) 规则。 - Maarten
3个回答

6

我决定走另外一条路线。它看起来很优雅,但只有在代码审查通过时才能知道。

我创建了一个新属性。

    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");

你能否将 RuleFor(...) 调用中选择属性值的 lambda 表达式替换为返回包含三个日期的列表的 lambda 表达式?这样就可以删除额外的属性了。 - Maarten
昨天我第一次使用FluentValidation,尝试了几种方法都失败了,但是这个方法可行。我喜欢模型可以轻松更新涉及的日期这一点。 - dalevross

4

对于所有3个值的简单规则是使用异或运算符。不需要额外的属性。如果要强制至少一个值有值,请删除unless。

 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");

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接