使用Fluent Validation验证可空字符串时传入空模型报错排查
问题分析与解决方案
错误原因
- Null实例验证限制:Fluent Validation默认不允许将
null传递给Validate方法,即便你的验证器泛型声明为string?。当pincode为null时,直接调用ValidateAndThrowMISVAppException就会触发Cannot pass null model to Validate异常。 - 异步调用阻塞问题:你在
Must中用.Result同步调用异步方法isPinCodeExists,这种写法会导致线程阻塞,极易引发死锁,属于严重的性能隐患。
解决方案
方案一:控制器层提前过滤Null
在调用验证逻辑前,先判断pincode是否非空,仅当值存在时才执行验证:
[HttpGet] public async Task<IActionResult> GetByPinCode([FromQuery] string? pincode) { if (!string.IsNullOrEmpty(pincode)) { this._isinValidator.ValidateAndThrowMISVAppException(pincode); } // 后续业务逻辑 }
方案二:修改验证器适配Null并优化异步逻辑
- 调整验证器代码,改用异步验证方法
MustAsync,同时配置允许验证Null实例:
public class PinCodeValidator : AbstractValidator<string?> { public PinCodeValidator() { // 仅当PinCode非空时执行数据库校验 When(r => !string.IsNullOrEmpty(r), () => { RuleFor(x => x) .MustAsync(async (pinCode, cancellationToken) => await isPinCodeExists(pinCode)) .WithMessage("PinCode details not found!."); }); } private Task<bool> isPinCodeExists(string pinCode) { // 数据库校验逻辑示例: // return _dbContext.PinCodes.AnyAsync(p => p.Code == pinCode); } }
- 若你的自定义
ValidateAndThrowMISVAppException方法未处理Null实例,可改用手动验证并关闭Null实例限制:
[HttpGet] public async Task<IActionResult> GetByPinCode([FromQuery] string? pincode) { var validationContext = new ValidationContext<string?>(pincode); // 允许验证Null实例 validationContext.ThrowOnNullInstance = false; var result = await _isinValidator.ValidateAsync(validationContext); if (!result.IsValid) { throw new MISVAppException(result.Errors); } // 后续业务逻辑 }
内容的提问来源于stack exchange,提问作者Ramesh Bolla
相关产品推荐
相关产品推荐

