Skip to content

FluentValidation 验证框架

验证


            // 创建验证器
            var validator = new CustomerValidator();

            // 进行验证
            var result = await validator.ValidateAsync(customer).ConfigureAwait(false);
            this.SendLog($@"验证结果:{result.IsValid}");

            // 能验证流程传递一些参数
            var context = new ValidationContext<Customer>(customer) { RootContextData = { [@"data"] = new object() } };
            var validationResult = await validator.ValidateAsync(context).ConfigureAwait(false);

            // 进行验证,如果有错误,直接抛出异常
            await validator.ValidateAndThrowAsync(customer).ConfigureAwait(false);

            // 指定 options 参数,比如指定只验证指定的规则集
            await validator.ValidateAsync(customer, options => options.IncludeRuleSets(@"sales").ThrowOnFailures())
                .ConfigureAwait(false);

验证规则


        public class CustomerValidator : AbstractValidator<Customer>
        {
            public CustomerValidator()
            {
                // 可以设置只有一项不符合规则就停止验证, 也可以只设置至某条规则 
                this.CascadeMode = CascadeMode.Stop;

                // 一般的验证规则 
                this.RuleFor(x => x.Surname).NotEmpty().WithMessage(@"{PropertyName}, 值为 {PropertyValue} 不能为空");
                this.RuleFor(x => x.Forename).NotEmpty().WithMessage(@"姓不能为空");
                this.RuleFor(x => x.Address).NotEmpty().WithMessage(@"地址不能为空");
                this.RuleFor(x => x.Products).NotEmpty().WithMessage(@"未设置产品");

                // 针对数组内容,设置验证规则 , 并且可以使用 where 进行条件判断
                this.RuleForEach(x => x.Products).Where(it => it.Name == "skip").NotNull().WithMessage(@"无效的产品信息");

                // 设置复杂对象的验证器 
                var productValidator = new ProductValidator(); // 比如 ProductValidator : AbstractValidator<Product>
                this.RuleForEach(x => x.Products).NotNull().SetValidator(productValidator);

                // 设置规则集, 可以只验证指定规则集的规则。验证时使用 options.IncludeRuleSets 指定规则集
                this.RuleSet(
                    "sales",
                    () => { this.RuleFor(x => x.Discount).LessThanOrEqualTo(0).WithMessage(@"折扣不能小于0"); });

                // 设置达到指定条件时才验证,使用 when 进行指定
                this.When(
                    x => x.Discount > 10,
                    () => { this.RuleFor(x => x.Products).Must(it => it.Count >= 10).WithMessage(@"产品数据必须大于 10"); });

                // 使用 DependentRules 指定前置验证条件,只有前置验证通过后,才进行此条规则验证
                this.RuleFor(it => it.Surname).MinimumLength(10)
                    .WithMessage(@"名称长度必须大于  10, 当前 {PropertyValue} 长度 {TotalLength}")
                    .DependentRules(() => this.RuleFor(it => it.Address));

                // 获取通过 ValidationContext 中的 RootContextData 传入的一些参数
                this.RuleFor(it => it.Surname).Custom(
                    (it, context) =>
                        {
                            var data = context.ParentContext.RootContextData[@"data"];
                        });

                // 设置并调用扩展规则
                public static IRuleBuilderOptions<T, IList<TElement>> ListMustContainFewerThan<T, TElement>(this IRuleBuilder<T, IList<TElement>> ruleBuilder, int num)
                {
                    return ruleBuilder.Must(list => list.Count < num).WithMessage("The list contains too many items");
                }
                this.RuleFor(it => it.Products).ListMustContainFewerThan(10).WithMessage(@"产品数据必须大于  10");

                // 使用自定义规则实现一些复杂的验证规则 , NamePropertyValidator : PropertyValidator 
                this.RuleFor(it => it.Surname).SetValidator(new NamePropertyValidator());
            }

            protected override bool PreValidate(ValidationContext<Customer> context, ValidationResult result)
            {
                // 在验证前进行数据校验,返回 true 才进行下一步的验证
                if (context.InstanceToValidate == null)
                {
                    result.Errors.Add(new ValidationFailure(string.Empty, @"请设置有效对象"));
                    return false;
                }

                return base.PreValidate(context, result);
            }
        }

与其它框架整合

https://www.xcode.me/post/5849#

https://docs.fluentvalidation.net/en/latest/index.html