【问题标题】:Fluent Validation - validate string after trimFluent Validation - 修剪后验证字符串
【发布时间】:2021-07-01 18:10:03
【问题描述】:

我正在使用http://fluentvalidation.codeplex.com/ 来验证一些域模型。

我有一个典型的场景,我想验证一个字符串,例如...

RuleFor(x => x.MyString).NotNull().NotEmpty().Length(2, 20).WithMessage("Please provide a string with a minium of 2 characters.");

...直到我创建一个单元测试,指定 MyString 属性的长度必须为 2-20 个字符 包括空格。

所以myObject.myString = "A" + new String(' ', 10); 应该验证失败。

我可以使用.Must(IsValidString) 完成所有这些工作,并自己将所有逻辑写在...

    private bool IsValidString(string myString)
    {
       if(String.IsNullOrEmpty(myString))
           return false;

       // Then work on myString.Trim()'ed value. 
    }

...但是我失去了所有可爱的流利验证!

显然我可以使用这种方法使我的单元测试通过,并且在我的小世界中所有人都会很高兴,但是我错过了一个技巧吗?

非常感谢。

【问题讨论】:

    标签: fluentvalidation


    【解决方案1】:

    使用Transform 在验证之前准备值:

    版本:9.5+

    Transform(i => i.InitialString, v => v?.Trim()).NotEmpty();
    

    版本:9.0 - 9.4:

    RuleFor(x => x.InitialString).Transform(v => v?.Trim()).NotEmpty();
    

    【讨论】:

      【解决方案2】:

      通过http://ilspy.net/ 稍微窥视一下 dll FluentValidation dll,我获得了制作以下 TrimmedLengthValidator 的灵感...

      public static class DefaultValidatorExtensions
          {
              public static IRuleBuilderOptions<T, string> TrimmedLength<T>(this IRuleBuilder<T, string> ruleBuilder, int min, int max)
              {
                  return ruleBuilder.SetValidator(new TrimmedLengthValidator(min, max));
              }
          }
      
      public class TrimmedLengthValidator : PropertyValidator, ILengthValidator, IPropertyValidator
          {
              public int Min { get; private set; }
              public int Max { get; private set; }
      
              public TrimmedLengthValidator(int min, int max)
                  : this(min, max, () => Messages.length_error)
              { }
      
              public TrimmedLengthValidator(int min, int max, Expression<Func<string>> errorMessageResourceSelector)
                  : base(errorMessageResourceSelector)
              {
                  this.Max = max;
                  this.Min = min;
      
                  if (max != -1 && max < min)
                      throw new ArgumentOutOfRangeException("max", "Max should be larger than min.");
              }
      
              protected override bool IsValid(PropertyValidatorContext context)
              {
                  if (context.PropertyValue == null)
                      return true;
      
                  int length = context.PropertyValue.ToString().Trim().Length;
      
                  if (length < this.Min || (length > this.Max && this.Max != -1))
                  {
                      context.MessageFormatter.AppendArgument("MinLength", this.Min).AppendArgument("MaxLength", this.Max).AppendArgument("TotalLength", length);
                      return false;
                  }
                  return true;
              }
          }
      

      ...这意味着我可以简单地将验证更改为:

      RuleFor(x => x.myString).NotEmpty().TrimmedLength(2, 20).WithMessage("Please provide a string with a minium of 2 characters.");
      

      摇滚吧!

      【讨论】:

      • 您可以通过将.NotNull() 调用删除为.NotEmpty() 调用来进一步减少验证代码。
      【解决方案3】:

      我对这个框架不是很熟悉,但是这样的东西有用吗? 您仍然可以保持大部分的流畅性,但是检查空格需要您编写自定义验证器(这很麻烦),或者使用谓词验证器

      RuleFor(x => x.MyString)
          .NotNull()
          .NotEmpty()
          .Length(2, 20)
              .WithMessage("Please provide a string with a minium of 2 characters.")
          .Must(myString => myString == Regex.Replace( myString, @"s", "" ))
      

      【讨论】:

      • 这不起作用,这是试图确保修剪后的长度完全相同,而是用空字符而不是空格字符替换所有 s。但在这两种情况下,这个答案都是错误的。它应该在修剪后验证长度
      【解决方案4】:
      RuleFor(x => x.myStringBefore).Transform(c => c.Trim()).NotEmpty();
      

      使用变换

      您可以使用修剪或子字符串...(转换后)流畅的验证允许 对转换后的值应用任何有效规则。

      【讨论】:

      • 当 myStringBefore 为空时,会从流畅的验证框架中抛出空引用异常。
      猜你喜欢
      • 2013-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-19
      • 1970-01-01
      • 2011-06-06
      • 2011-12-26
      相关资源
      最近更新 更多