【问题标题】:Intercepting Fluent Validation拦截 Fluent 验证
【发布时间】:2020-08-15 02:50:19
【问题描述】:

我们正在使用 fluentvalidation(带有服务堆栈)来验证我们的请求 DTO。我们最近扩展了我们的框架以接受“PATCH”请求,这意味着我们现在需要仅在补丁包含正在验证的字段时应用验证。

我们已经使用了这样的扩展方法:

       RuleFor(dto => dto.FirstName).Length(1,30)).WhenFieldInPatch((MyRequest dto)=>dto.FirstName);
       RuleFor(dto => dto.MiddleName).Length(1,30)).WhenFieldInPatch((MyRequest dto)=>dto.MiddleName);
       RuleFor(dto => dto.LastName).Length(1,30)).WhenFieldInPatch((MyRequest dto)=>dto.LastName);

这意味着我们可以对 POST/PUT 或 PATCH 运行相同的验证。

我一直在寻找一种连接到流式验证框架的方法,例如我们不需要在验证的每一行上复制 .WhenFieldInPatch() 规则,但还没有找到一个好的方法这样做。

我尝试了以下方法:

  1. 创建一个辅助方法(在基类中)拦截初始“RuleFor”,该方法在前面添加了 .When() 子句,但这不起作用,因为流畅的验证需要 .When()最后
  2. 在 PreValidation 中拦截调用,但我只能基于整个类进行拦截,而不是逐个规则地进行拦截
  3. 添加扩展方法以应用于每个规则的末尾(根据示例),但我无法访问初始表达式以检查是否应映射该字段 - 所以我需要再次传递它。李>

我是错过了什么,还是在尝试不可能的事情?

谢谢

【问题讨论】:

    标签: servicestack fluentvalidation


    【解决方案1】:

    当我需要共享 Fluent Validation Logic 时,我会使用扩展方法,这里是 shared Extension methods for TechStacks 的示例,例如:

    public static class ValidatorUtils
    {
        public static bool IsValidUrl(string arg) => Uri.TryCreate(arg, UriKind.Absolute, out _);
        public static string InvalidUrlMessage = "Invalid URL";
    
        public static IRuleBuilderOptions<T, string> OptionalUrl<T>(
            this IRuleBuilderInitial<T, string> propertyRule)
        {
            return propertyRule
                .Length(0, UrlMaxLength)
                .Must(IsValidUrl)
                .When(x => !string.IsNullOrEmpty(x as string))
                .WithMessage(InvalidUrlMessage);
        }
    }
    

    还有some examples 分享它们的地方:

    public class CreatePostValidator : AbstractValidator<CreatePost>
    {
        public CreatePostValidator()
        {
            RuleSet(ApplyTo.Post, () =>
            {
                RuleFor(x => x.Url).OptionalUrl();
            });
        }
    }
    
    public class UpdatePostValidator : AbstractValidator<UpdatePost>
    {
        public UpdatePostValidator()
        {
            RuleSet(ApplyTo.Put, () =>
            {
                RuleFor(x => x.Url).OptionalUrl();
            });
        }
    }
    

    【讨论】:

    • 谢谢!我们确实使用了扩展方法。在这种情况下,我需要构建初始规则,然后是提供特定逻辑的实际验证器,最后添加一个 .When() 。如果我将 .When() 放在构建初始规则的扩展方法中(或提供 RuleFor() 的新实现),流式验证框架会忽略我在 When() 之后添加的任何规则,因此它不适合这个用例。我可以创建一个扩展方法,将其添加到正在验证的每个字段(在添加任何特定逻辑之后),但希望不那么突兀。
    • @DavidHiblen 那是因为 when 是一个谓词,也许你可以通过将自定义委托传递给你的 ext 方法来进一步自定义它,否则看Fluent Validation docs on their support for Custom Validators
    • 再次感谢。我已经更新了最初的问题,以表明我不相信扩展方法可以解决问题(并希望使它更清楚)。自定义验证器也不让我访问用于创建初始表达式的规则,因此仍然意味着更改我认为的所有当前验证器。我怀疑可能只需要咬紧牙关并在整个过程中添加扩展方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-05
    • 2012-06-18
    相关资源
    最近更新 更多