具有依赖规则的 FluentValidation 自定义验证程序

FluentValidation custom validator with dependent rules

提问人:Robin 提问时间:11/7/2023 更新时间:11/7/2023 访问量:28

问:

我想为具有特定验证规则的各种字段提供一个自定义验证器,这样我就不必重复代码。在此示例中,我想要一个用于电子邮件字段。我有验证帮助程序方法,可以检查基本的东西,比如它是否是一封有效的电子邮件,但也执行一些域检查。

我首先做的是在字段上制定一个规则,然后像这样调用我的自定义验证器:.NotNull()

RuleFor(dto => dto.Upn).NotNull().EmailMustBeValid();

但这没有用。当 upn 为 null 时,它会为其生成错误代码,但仍会触发我的自定义验证程序。帮助程序方法假定字符串为空,而不是 null。我可以为此建立检查,而且我有。但是我不希望有两个错误代码说同样的话,因为电子邮件是空的。我也不想放弃规则,将所有规则放在我的自定义验证器或帮助程序方法中。.NotNull()

我接下来尝试的是:

RuleFor(x => x.Upn).NotNull().NotEmpty().DependentRules(() => {
                RuleFor(x => x.Upn).EmailMustBeValid();
            });

这奏效了,但它损害了可读性。我还从中删除了规则,以使示例更小。但加在一起,它可能会变得相当大。.WithMessage()

然后,我尝试将所有这些封装在我的自定义验证器中,但似乎我无法在自定义验证器中使用依赖规则?我似乎丢失了传递的参数。我的自定义验证器与依赖规则的代码是:

public static IRuleBuilderOptions<T, string> EmailMustBeValid<T>(this IRuleBuilder<T, string> ruleBuilder)
    {
        return ruleBuilder.NotNull()
            .DependentRules(() =>
            {
                ruleBuilder.Must(email => IsValidEmail(email));
            });
    }

当它到达该方法时,email 参数仍为 null,但仍会调用该方法。所以从属规则似乎不起作用?IsValidEmail

我也尝试使用该条件,但这些条件似乎也无法在带有规则构建器的自定义验证器中工作。When

我认为我唯一的选择是在验证器本身上使用依赖规则,并且必须在需要的地方重复它,这是否正确?我希望有一种适当的方法可以将这个逻辑封装在我的自定义验证器中。

我看到的另一种解决方案是将此逻辑复制到我的方法中,并放弃使用诸如 and 之类的规则,但我不确定这是否是解决问题的正确方法。IsValidEmailNotNull()NotEmpty()

C# 验证 FluentValidation

评论


答:

0赞 Robin 11/7/2023 #1

好的,似乎我错过了文档中的一部分。我设法通过级联模式更改来修复它。

我现在的验证器代码:

public TestValidator()
    {
        RuleFor(dto => dto.Upn).Cascade(CascadeMode.Stop)
            .NotNull().WithMessage("Not null triggered")
            .EmailMustBeValid();
    }

还有我的自定义验证器代码:

public static IRuleBuilderOptions<T, string> EmailMustBeValid<T>(this IRuleBuilder<T, string> ruleBuilder)
    {
        return ruleBuilder
            .Must(email => IsValidEmail(email))
            .WithMessage(ValidationErrorCode.UpnValidationFailed.ToString());
    }

这似乎工作正常,由于某种原因,我无法让它与类级联模式一起使用,但这对我有用。

我确实通过使用RuleLevelCascadeMode = CascadeMode.Stop;