IPipelineBehavior ValidationBehavior 在 MediatR 中注册时不会被触发

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

我将通过

LangExt 库
Result<T> 替换所有异常。问题是
ValidationBehavior
甚至没有被触发。它用于在方法签名曾经是
public class ValidationBehavior<TRequest, TResponse>(IEnumerable<IValidator<TRequest>> validators) : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
时触发。那么我如何注册
ValidationBehavior
以便它被触发,这样我就不必手动指定
AbstractValidator
类?

builder.Services.AddValidatorsFromAssemblyContaining<Program>();
builder.Services.AddMediatR(configure =>
{
    configure.RegisterServicesFromAssemblyContaining<Program>();
    configure.AddRequestPreProcessor(typeof(IRequestPreProcessor<>), typeof(LoggingBehavior<>));
    configure.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
    configure.AddBehavior(typeof(IPipelineBehavior<,>), typeof(MetricsBehavior<,>));
});
public class ValidationBehavior<TRequest, TResponse>(IEnumerable<IValidator<TRequest>> validators) : IPipelineBehavior<TRequest, Result<TResponse>>
    where TRequest : IRequest<Result<TResponse>>
{
    public async Task<Result<TResponse>> Handle(TRequest request, RequestHandlerDelegate<Result<TResponse>> next, CancellationToken cancellationToken)
    {
        if (!validators.Any())
        {
            return await next();
        }

        var context = new ValidationContext<TRequest>(request);
        var validationResults = await Task.WhenAll(validators.Select(v => v.ValidateAsync(context, cancellationToken)));

        var failures = validationResults
            .Where(r => r.Errors.Count != 0)
            .SelectMany(r => r.Errors)
            .ToList();

        if (failures.Count != 0)
        {
            return new Result<TResponse>(new ValidationException(failures));
        }

        return await next();
    }
}
c# asp.net-core fluentvalidation mediatr
1个回答
0
投票

您可能应该将班级的签名更改为如下所示:

public class ValidationPreProcessor<TRequest> : IRequestPreProcessor<TRequest>{

private readonly IEnumerable<IValidator<TRequest>> _validators;

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

public async Task Process(TRequest request, CancellationToken cancellationToken)
{
    var context = new ValidationContext<TRequest>(request);
    var failures = _validators
        .Select(v => v.Validate(context))
        .SelectMany(result => result.Errors)
        .Where(f => f != null)
        .ToList();

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

至于如何注册

public class Startup 
{

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddMediatR(typeof(Startup));
    services.AddValidatorsFromAssemblyContaining<Startup>();

    // Register pipeline behaviors
    services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
    services.AddTransient(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehavior<,>));
    services.AddTransient(typeof(IPipelineBehavior<,>), typeof(PerformanceBehavior<,>));
    services.AddTransient(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehavior<,>));

    // Register request pre-processors and post-processors
    services.AddTransient(typeof(IRequestPreProcessor<>), typeof(ValidationPreProcessor<>));
    services.AddTransient(typeof(IRequestPostProcessor<,>), typeof(LoggingPostProcessor<,>));
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
} 
}

您可以在这里找到更多信息https://argosco.io/using-ipipelinebehavior-irequestpreprocessor-and-irequestpostprocessor-in-a-net-core-api/net/

© www.soinside.com 2019 - 2024. All rights reserved.