简体   繁体   English

仅当值不为空时,FluentValidation应用规则

[英]FluentValidation apply rule only if the value is not empty

I have the following extension method for FluentValidation : 我有以下FluentValidation扩展方法:

    public static IRuleBuilderOptions<T, string> MustHasLengthBetween<T>(this IRuleBuilder<T, string> rule, int min, int max)
    {
        return rule
            .Length(min, max).WithMessage(someCustomMessage);
    }

I want to apply this rule only if the property has something on it, if it's a null or empty string this rule shouldn't be verified. 我只想在属性上有内容时才应用此规则,如果它是nullempty字符串,则不应验证此规则。

In the calling validation class I can do like this: 在调用验证类中,我可以这样:

        RuleFor(a => a.SomeProperty)
            .MustHasLengthBetween(5, 10)
            .When(x => !String.IsNullOrEmpty(x.SomeProperty))

It works, but then I have to put this When call on every calling method. 它可以工作,但随后我必须在每个调用方法上都放置此When调用。 Is there any way to move the When call to the extension method? 有什么方法可以将When调用移至扩展方法吗?

Adding extension When builder below gives you access to the property value. 添加扩展When下面的构建器允许您访问属性值时。 You can re-use this with other validations, too. 您也可以将其与其他验证一起使用。

public static IRuleBuilderOptions<T, TProperty> When<T, TProperty>(this IRuleBuilderOptions<T, TProperty> rule, Func<T, TProperty, bool> predicate, ApplyConditionTo applyConditionTo = ApplyConditionTo.AllValidators)
{
    return rule.Configure(config => {
        config.ApplyCondition(ctx => predicate((T)ctx.Instance, (TProperty)ctx.PropertyValue), applyConditionTo);
    });
}

Test 测试

public class UnitTest1
{
    [Fact]
    public void Should_validate_length ()
    {
        var ok1 = new Model { MyProperty = null };
        var ok2 = new Model { MyProperty = "" };
        var ok3 = new Model { MyProperty = "55555" };
        var fail = new Model { MyProperty = "1" };

        var v = new ModelValidator ();

        v.ValidateAndThrow (ok1);
        v.ValidateAndThrow (ok2);
        v.ValidateAndThrow (ok3);

        Should.Throw<ValidationException> (() => v.ValidateAndThrow (fail));
    }

    public class Model
    {
        public string MyProperty { get; set; }
    }

    public class ModelValidator : AbstractValidator<Model>
    {
        public ModelValidator ()
        {
            RuleFor (x => x.MyProperty)
                .MustHaveLengthBetween (5, 10);
        }
    }
}

public static class Extensions
{
    public static IRuleBuilderOptions<T, string> MustHaveLengthBetween<T> (this IRuleBuilder<T, string> rule, int min, int max)
    {
        return rule
            .Length (min, max).WithMessage ("AGAGA")
            .When ((model, prop) => !string.IsNullOrEmpty (prop));
    }

    /// <summary>
    /// Predicate builder which makes the validated property available
    /// </summary>
    /// <param name="IRuleBuilderOptions<T"></param>
    /// <param name="rule"></param>
    /// <param name="predicate"></param>
    /// <param name="applyConditionTo"></param>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="TProperty"></typeparam>
    /// <returns></returns>
    public static IRuleBuilderOptions<T, TProperty> When<T, TProperty> (this IRuleBuilderOptions<T, TProperty> rule, Func<T, TProperty, bool> predicate, ApplyConditionTo applyConditionTo = ApplyConditionTo.AllValidators)
    {
        return rule.Configure (config =>
        {
            config.ApplyCondition (ctx => predicate ((T) ctx.Instance, (TProperty) ctx.PropertyValue), applyConditionTo);
        });
    }
}
public static IRuleBuilderInitial<T, string> MustHasLengthBetween<T>(this IRuleBuilder<T, string> rule, int min, int max)
        {
            return rule.Custom((obj, context) =>
            {
                if (!String.IsNullOrEmpty(obj) && (obj.Length < min || obj.Length > max))
                {
                    context.AddFailure("custom message");
                }
            });
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM