拦截流利验证

时间:2020-04-30 16:42:19

标签: servicestack fluentvalidation

我们正在使用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. 创建一个辅助方法(在基类中的a中)以拦截初始的“ RuleFor”,该方法在前面添加了.When()子句,但这不能正常工作,因为需要有效的验证。最后
  2. 拦截PreValidation中的调用,但是我只能基于整个类进行拦截,而不能基于规则进行拦截
  3. 添加了一个扩展方法以应用于每个规则的末尾(如示例所示),但是我无法访问初始表达式以检查是否应映射该字段-因此我需要再次传递它。
  4. li>

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

谢谢

1 个答案:

答案 0 :(得分:2)

当我需要共享Fluent验证逻辑时,我会使用扩展方法,下面是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();
        });
    }
}