FluentValidation 通过 MediatR 管道响应错误

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

我正在使用这个

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
            .ToAsyncEnumerable()
            .SelectAwait(async validator => await validator.ValidateAsync(context))
            .ToEnumerable()
            .SelectMany(result => result.Errors)
            .Where(failure => failure is not null)
            .ToList();

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

        return await next();
    }
}

我正在通过 MediatR 管道进行操作,就像这样:

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

验证器非常简单,只是检查金额是否大于0。

internal class DepositCommandHandlerValidator : AbstractValidator<DepositCommand>
{
    public DepositCommandHandlerValidator()
    {
        RuleFor(c => c.Amount).GreaterThan(0).WithMessage("Amount must be greater than 0.");
    }
}

控制器中有一个动作:

    [HttpPatch("deposit")]
    public async Task<IActionResult> Deposit([FromRoute] Guid id, [FromBody] decimal amount)
    {
        bool result = await _mediator.Send(new DepositCommand(id, amount), CancellationToken.None);
        if (result)
        {
            return NoContent();
        }
        return BadRequest();
    }

现在,正常的 api 错误会产生正确的消息,例如,我发送一个完全空的正文,我得到:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.13",
    "title": "Unsupported Media Type",
    "status": 415,
    "traceId": "00-55b083e06040a567d23741ac86df0166-6c9093c560f5addc-00"
}

但是,当出现验证异常时,我可以看到正确的消息,这没关系,而且我还可以看到整个堆栈跟踪。例如,假设我在请求正文中输入一个负值,我得到:

FluentValidation.ValidationException: Validation failed: 
 -- Amount: Amount must be greater than 0. Severity: Error
   at BankApp.Core.Middleware.ValidationBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken) in C:\Users\Jan\source\repos\BankApi\BankApi.Core\Middleware\ValidationBehavior.cs:line 33
   at BankApp.Api.Controllers.CustomersController.Deposit(Guid id, Decimal amount) in C:\Users\Jan\source\repos\BankApi\BankApi.Api\Controllers\CustomersController.cs:line 25
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======
Accept: */*
Connection: keep-alive
Host: localhost:7098
User-Agent: PostmanRuntime/7.33.0
Accept-Encoding: gzip, deflate, br
Content-Type: application/json
Content-Length: 2
Postman-Token: 72d7805a-490a-478c-a1d1-a5d53283f05e

为什么要发送整个堆栈跟踪?

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

中间件出现错误。它没有像评论中那样正确处理异常

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