如何使用Fluent Validation实现依赖多独立规则的验证
解决方案
要实现RuleA(UserIdExists)和RuleB(OrderIdExists)独立验证,RuleC(OrderBelongsToUser)仅在两者均通过时执行的需求,你可以通过WhenAsync(异步场景)控制RuleC的执行时机,或调整验证规则的嵌套逻辑,以下是两种可行实现方式:
方式一:通过WhenAsync显式控制执行条件
拆分三个验证规则,对RuleC添加前置条件判断,确保只有前两个验证都通过时才触发:
RuleFor(request => request).NotNull(); // 独立验证RuleA:UserId是否存在 RuleFor(request => request) .CustomAsync(UserIdExists) .WithMessage("指定的UserId不存在"); // 独立验证RuleB:OrderId是否存在 RuleFor(request => request) .CustomAsync(OrderIdExists) .WithMessage("指定的OrderId不存在"); // RuleC:仅当RuleA和RuleB均通过时执行 RuleFor(request => request) .CustomAsync(OrderBelongsToUser) .WithMessage("该OrderId不属于指定的UserId") .WhenAsync(async (request, context, cancellationToken) => { // 手动验证前两个规则的结果 var userIdValidationPassed = await ValidateUserId(request, cancellationToken); var orderIdValidationPassed = await ValidateOrderId(request, cancellationToken); return userIdValidationPassed && orderIdValidationPassed; }); // 辅助方法:封装UserIdExists的验证逻辑 private async Task<bool> ValidateUserId(YourRequestType request, CancellationToken cancellationToken) { var validator = new InlineValidator<YourRequestType>(); validator.CustomAsync(UserIdExists); var result = await validator.ValidateAsync(request, cancellationToken); return result.IsValid; } // 辅助方法:封装OrderIdExists的验证逻辑 private async Task<bool> ValidateOrderId(YourRequestType request, CancellationToken cancellationToken) { var validator = new InlineValidator<YourRequestType>(); validator.CustomAsync(OrderIdExists); var result = await validator.ValidateAsync(request, cancellationToken); return result.IsValid; }
方式二:利用DependentRules嵌套+条件判断
将RuleC嵌套在依赖于NotNull的块中,同时通过WhenAsync确保只有前两个验证通过时才执行:
RuleFor(request => request).NotNull().DependentRules(() => { // 独立验证RuleA RuleFor(request => request).CustomAsync(UserIdExists) .WithMessage("指定的UserId不存在"); // 独立验证RuleB RuleFor(request => request).CustomAsync(OrderIdExists) .WithMessage("指定的OrderId不存在"); // RuleC:依赖前两者通过 RuleFor(request => request).CustomAsync(OrderBelongsToUser) .WithMessage("该OrderId不属于指定的UserId") .WhenAsync(async (request, cancellationToken) => { var userIdValid = await ValidateUserId(request, cancellationToken); var orderIdValid = await ValidateOrderId(request, cancellationToken); return userIdValid && orderIdValid; }); });
原代码问题分析
你之前的代码中,CustomAsync(OrderBelongsToUser)是直接链式调用在DependentRules之后,DependentRules仅控制内部的RuleA和RuleB在NotNull验证通过后执行,但不会影响后续的RuleC——无论RuleA或RuleB是否失败,RuleC都会被触发执行,这不符合你的需求。
内容的提问来源于stack exchange,提问作者YanivHer
相关产品推荐
相关产品推荐

