不在 MediatR 管道中调用 FluentValidation

问题描述 投票:0回答:1

我正在使用: 媒体R 12.1.1 FluentValidation 11.6.0

我已经创建了我的验证器:

internal class CreateTemplateCommandValidator : AbstractValidator<CreateTemplateCommand>
{
    public CreateTemplateCommandValidator(ITemplateRepository templateRepository)
    {
        RuleFor(template => template.Name)
            .NotEmpty()
            .DependentRules(() =>
        {
            RuleFor(template => template.Name)
                .MustAsync(async (name, token) => !(await templateRepository.NameExists(name)))
                .WithMessage("Name must be unique.");
        });
    }
}

我希望通过 MediatR 管道处理验证。这是我的 ValidationBehavior 类:

public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    private readonly IEnumerable<IValidator<TRequest>> _validators;

    public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
    {
        _validators = validators;
    }

    public async Task<TResponse> Handle(
        TRequest request,
        RequestHandlerDelegate<TResponse> next,
        CancellationToken cancellationToken)

    {
        var context = new ValidationContext<TRequest>(request);

        var failures = _validators
            .Select(validator => validator.Validate(context))
            .SelectMany(result => result.Errors)
            .Where(failure => failure is not null)
            .ToList();

        if (failures.Any())
        {
            throw new ValidationException(failures);
        }

        return await next();
    }
}

我还注册了这些:

        services.AddMediatR(cfg =>
        {
            cfg.RegisterServicesFromAssembly(typeof(Extension).Assembly);
        });


        services.AddValidatorsFromAssemblyContaining(typeof(Extension));
        services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
     

不幸的是,验证器从未被调用。 我陷入困境,因为我在其他地方找不到答案,似乎我已经正确遵循了模式 - 我错过了什么?

c# .net asp.net-core fluentvalidation mediatr
1个回答
0
投票

您的验证器是内部的。 您需要将 DI 更改为:

services.AddValidatorsFromAssemblyContaining(typeof(Extension), includeInternalTypes: true);

我还建议使用:

services.AddMediatR(cfg =>
{
    cfg.RegisterServicesFromAssembly(typeof(Extension).Assembly);
    cfg.AddOpenBehavior(typeof(ValidationBehavior<,>)
});

关于你的方法:

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));

最后,在重现您的问题时,我发现了另一个错误,您将在应用此修复程序时发现:

Unhandled exception. FluentValidation.AsyncValidatorInvokedSynchronouslyException: Validator "CreateTemplateCommandValidator" contains asynchronous rules but was invoked synchronously. Please call ValidateAsync rather than Validate.

我建议使用

System.Linq.Async
并将验证码更改为:

var failures = _validators
    .ToAsyncEnumerable()
    .SelectAwait(async validator => await validator.ValidateAsync(context))
    .ToEnumerable()
    .SelectMany(result => result.Errors)
    .Where(failure => failure is not null)
    .ToList();
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.