MediatR管道中FluentValidation未触发调用问题排查
以下是你可能遗漏的配置或步骤,按优先级排查:
验证器泛型约束与请求类型匹配问题
确保CreateTemplateCommandValidator正确继承自AbstractValidator<CreateTemplateCommand>,且CreateTemplateCommand实现了MediatR的IRequest<TResponse>接口(哪怕是IRequest<Unit>)。如果请求类型不匹配,DI容器无法找到对应验证器,自然不会触发。ValidationBehavior的泛型定义与逻辑正确性
检查你的ValidationBehavior是否正确实现IPipelineBehavior<TRequest, TResponse>,泛型约束必须包含where TRequest : IRequest<TResponse>。同时确认行为内部逻辑:- 从DI容器获取
IEnumerable<IValidator<TRequest>>(注意是泛型的验证器集合) - 调用每个验证器的
ValidateAsync方法传入请求实例 - 收集错误并在有错误时抛出
ValidationException或返回错误响应
示例正确逻辑片段:
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken) { var context = new ValidationContext<TRequest>(request); var validationResults = await Task.WhenAll( _validators.Select(v => v.ValidateAsync(context, cancellationToken))); var failures = validationResults .SelectMany(r => r.Errors) .Where(f => f != null) .ToList(); if (failures.Any()) throw new ValidationException(failures); return await next(); }- 从DI容器获取
服务注册顺序与方式错误
注册顺序必须遵循:验证器 → 管道行为 → MediatR,且确保注册方式正确:- 用FluentValidation扩展方法注册验证器:
services.AddValidatorsFromAssemblyContaining<CreateTemplateCommandValidator>(); // 或单独注册单个验证器 services.AddValidator<CreateTemplateCommandValidator>(); - 注册管道行为:
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); - 注册MediatR,确保包含请求、处理程序、管道行为所在的程序集:
services.AddMediatR(cfg => { cfg.RegisterServicesFromAssemblyContaining<CreateTemplateCommand>(); // 若行为在不同程序集,需额外添加: // cfg.RegisterServicesFromAssemblyContaining<ValidationBehavior<,>>(); });
注意:如果MediatR注册时未包含管道行为的程序集,行为不会被加入管道。
- 用FluentValidation扩展方法注册验证器:
验证器未被DI容器正确注册
手动检查DI容器中是否存在IValidator<CreateTemplateCommand>实例。可以在启动时或请求处理中注入IEnumerable<IValidator<CreateTemplateCommand>>,查看是否包含你的验证器实例。如果为空,说明验证器注册失败,需检查程序集扫描范围或注册方式。绕开MediatR直接调用处理程序
确认你是通过IMediator.Send(command)来触发命令处理,而非直接实例化命令处理程序并调用Handle方法。直接调用处理程序会跳过MediatR的管道机制,验证行为自然不会执行。版本兼容性与依赖清理
虽然你使用的MediatR 12.1.1与FluentValidation 11.6.0理论上兼容,但可以尝试清理NuGet缓存,重新安装所有相关依赖,排除版本冲突或损坏的包文件问题。
内容的提问来源于stack exchange,提问作者defcon1

