代码之家  ›  专栏  ›  技术社区  ›  DDNL

如何使用FluentValidation为嵌套对象设置验证

  •  0
  • DDNL  · 技术社区  · 1 年前

    我在API中使用FluentValidation,我已经创建了四个验证器。第一个用于订单级验证,第二个用于订单细节级验证,另外两个用于对订单细节的提取和转移操作。

    我可以打电话给 OrderValidator 从应用程序,如下所示:

    var validator = new OrderValidator();
    foreach (var order in orders)
    {
        var vResult = validator.Validate(order);
    }
    

    上面的代码适用于 订单验证器 以及 OrderDetailValidator 。但是,它不适用于 WithdrawInfoValidator TransferInfoValidator 因为我还没有申报 提款信息验证器 然而

    问题是如何设置 提款信息验证器 OrderDetailValidator

    这是我的模型

    public class Order
    {
       
        public string AdvisorCode { get; set; }
        public string AccountNo { get; set; }
        public string AccountType { get; set; }
        public List<OrderDetail> Details { get; set; }
    }
    
    public class OrderDetail
    {
        public int GroupNo { get; set; }
        public int SubOrderNo { get; set; }
        public string OrderType { get; set; }
        public string FundSource { get; set; }
        public string ProductCode { get; set; }
        public string Currency { get; set; }
        public decimal Amount { get; set; }
        public decimal Units { get; set; }
        public string DivOption { get; set; }
        public int? SellAll { get; set; }
        public WithdrawInfo WithdrawInfo { get; set; }
    }
    
    public class WithdrawInfo
    {
        public string WithdrawMode { get; set; }
        public string WDCurrency { get; set; }
        public decimal WDAmount { get; set; }
        public TransferInfo TransferInfo { get; set; }
    }
    
    public class TransferInfo
    {
        public string BankName { get; set; }
        public string AccountNo { get; set; }
        public string Branch { get; set; }
        public string AccHolderName { get; set; }
        public string SwiftCode { get; set; }
        public string IntBankName { get; set; }
        public string IntSwiftCode { get; set; }
        public string OtherInfoOrAddress { get; set; }
    }
    
    public class OrderErrorReference
    {
        public string OrderType { get; set; }
        public int GroupNo { get; set; }
        public int SubOrderNo { get; set; }
    }
    

    这是我的验证器

    public class OrderValidator : AbstractValidator<Order>
    {
    
        public OrderValidator()
        {
            RuleFor(m => m.AdvisorCode)
                .NotEmpty()
                .WithMessage(
                    "AdvisorCode field cannot be empty."
                    );
    
           
            RuleForEach(m => m.Details)
                .SetValidator(new OrderDetailValidator())
                .When(m => m.Details != null);
    
        }
    }
    
    public class OrderDetailValidator : AbstractValidator<OrderDetail>
    {
        public OrderDetailValidator()
        {
            RuleFor(m => m.GroupNo)
                .Cascade(CascadeMode.Stop)
                .NotEmpty().WithMessage(
                    "GroupNo field cannot be empty."
                ).WithState(m => new OrderErrorReference
                {
                    GroupNo = m.GroupNo,
                    SubOrderNo = m.SubOrderNo,
                    OrderType = m.OrderType
                })
                .Must(m => m > 0)
                .WithMessage(
                    "GroupNo must be greater than zero."
                    ).WithState(m => new OrderErrorReference
                    {
                        GroupNo = m.GroupNo,
                        SubOrderNo = m.SubOrderNo,
                        OrderType = m.OrderType
                    });          
    
        }
    }
    
    public class WithdrawInfoValidator : AbstractValidator<WithdrawInfo>
    {
        public WithdrawInfoValidator(OrderDetail orderDetail)
        {
            RuleFor(m => m.WithdrawMode)
                .Cascade(CascadeMode.Stop)
                .Must(mode => mode == "TT" || mode == "QC")
                .When(m => m.WithdrawMode != null)
                .WithMessage(
                    "Withdraw Mode must be either \"NA\"=No Withdrawal, \"TT\"=Telegraphic Transfer or \"QC\"=Quick Check Deposit."
                    ).WithState(m => new OrderErrorReference
                    {
                        GroupNo = orderDetail.GroupNo,
                        SubOrderNo = orderDetail.SubOrderNo,
                        OrderType = orderDetail.OrderType
                    })
                .NotEmpty()
                .WithMessage(
                    "The WithdrawMode field cannot be empty."
                    ).WithState(m => new OrderErrorReference
                    {
                        GroupNo = orderDetail.GroupNo,
                        SubOrderNo = orderDetail.SubOrderNo,
                        OrderType = orderDetail.OrderType
                    });
    
            
    
            RuleFor(m => m.TransferInfo)
                .Must(info => info != null)
                .When(m => m.WithdrawMode == "TT" || m.WithdrawMode == "QC")
                .WithMessage(
                    "TransferInfo cannot be empty if WithdrawMode is \"TT\" or \"QC\""
                    ).WithState(m => new OrderErrorReference
                    {
                        GroupNo = orderDetail.GroupNo,
                        SubOrderNo = orderDetail.SubOrderNo,
                        OrderType = orderDetail.OrderType
                    })
                .SetValidator(m => new TransferInfoValidator(orderDetail))
                .When(m => m.WithdrawMode == "TT" || m.WithdrawMode == "QC");
        }
    }
    
    public class TransferInfoValidator : AbstractValidator<TransferInfo>
    {
        public TransferInfoValidator(OrderDetail orderDetail)
        {
    
            RuleFor(m => m.OtherInfoOrAddress)
                  .NotEmpty()
                  .When(m => orderDetail.WithdrawInfo.WithdrawMode == "TT")
                  .WithMessage(
                      "OtherInfoOrAddress field cannot be empty if WithdrawMode is TT."
                      ).WithState(m => new OrderErrorReference
                      {
                          GroupNo = orderDetail.GroupNo,
                          SubOrderNo = orderDetail.SubOrderNo,
                          OrderType = orderDetail.OrderType
                      });
        }
    }
    

    我已经尝试了很多方法,但都没有成功。

    1 回复  |  直到 1 年前
        1
  •  1
  •   Yong Shun    1 年前

    您应该声明 WithdrawInfo 通过提供 WithdrawInfoValidator 具有的实例 orderDetail 对象

    public class OrderDetailValidator : AbstractValidator<OrderDetail>
    {
        public OrderDetailValidator()
        {
            ...        
                    
            RuleFor(m => m.WithdrawInfo)
                .SetValidator(m => new WithdrawInfoValidator(m));
    
        }
    }