返回带有错误的响应,而不是在验证管道 mediatr 3 中抛出异常
Posted
技术标签:
【中文标题】返回带有错误的响应,而不是在验证管道 mediatr 3 中抛出异常【英文标题】:Return response with errors instead of throwing exception in validation pipeline mediatr 3 【发布时间】:2017-10-19 05:35:28 【问题描述】:我目前正在使用 Mediatr 3 中的管道行为进行请求验证。如果发生任何故障,我遇到的所有示例都会抛出 ValidationException,而不是这样做,我想返回带有错误的响应。有人知道怎么做吗?
以下是验证管道的代码:
public class ValidationPipeline<TRequest, TResponse> :
IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationPipeline(IEnumerable<IValidator<TRequest>> validators)
_validators = validators;
public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next)
var failures = _validators
.Select(v => v.Validate(request))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if (failures.Any())
throw new ValidationException(failures);
return next();
注意:我发现了这个问题Handling errors/exceptions in a mediator pipeline using CQRS?,我对答案中的第一个选项感兴趣,但没有关于如何做到这一点的明确示例。
这是我的响应类:
public class ResponseBase : ValidationResult
public ResponseBase() : base()
public ResponseBase(IEnumerable<ValidationFailure> failures) : base(failures)
我在验证管道类中添加了以下签名:
public class ValidationPipeline<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
where TResponse : ResponseBase
然后我在 Handle 方法中这样做了:
var response = new ResponseBase(failures);
return Task.FromResult<TResponse>(response);
但这给了我错误“无法转换为 TResponse”。
【问题讨论】:
return the response with the error
- response
是什么样的?
管道TResponse
将与底层处理程序TResponse
相同——ResponseBase : ValidationResult
对我来说就像是代码味道。我不清楚您要达到的目标。
我正在尝试从 FluentValidation 的 ValidationResult 类继承
这意味着整个管道(包括您的主处理程序)将返回这种类型,对吗?
是的,完全正确。感谢您指出了这一点。所以我决定不从任何类继承 ResponseBase,它现在可以工作了!非常感谢。
【参考方案1】:
几年前,我创建了通用的 Result 对象,我正在不断改进它。很简单,查看https://github.com/martinbrabec/mbtools。
如果您可以接受 Result(或 Result)作为应用层中的返回类型每个方法,那么您可以像这样使用 ValidationBehavior:
public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
where TResponse : Result, new()
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
_validators = validators;
public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
if (_validators.Any())
var context = new ValidationContext(request);
List<ValidationFailure> failures = _validators
.Select(v => v.Validate(context))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if (failures.Any())
TResponse response = new TResponse();
response.Set(ErrorType.NotValid, failures.Select(s => s.ErrorMessage), null);
return Task.FromResult<TResponse>(response);
else
return next();
return next();
由于您的所有处理程序都返回 Result(或基于 Result 的 Result),您将能够毫无例外地处理所有验证错误。
【讨论】:
【参考方案2】:如果有任何故障,请不要致电next
:
public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next)
var failures = _validators
.Select(v => v.Validate(request))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if (failures.Any())
var response = new Thing(); //obviously a type conforming to TResponse
response.Failures = failures; //I'm making an assumption on the property name here.
return Task.FromResult(response);
else
return next();
注意:
你的班级(在我的例子中是Thing
)必须是TResponse
类型的
【讨论】:
嗨,我会在这里回答你上面的问题。我的响应类如下所示:public class ResponseBase : ValidationResult public ResponseBase() : base() public ResponseBase(IEnumerable<ValidationFailure> failures) : base(failures)
我这样做了,但是尝试将 ResponseBase 转换为 TResponse 时出现错误 var response = new ResponseBase(failures); return Task.FromResult您可以使用包配置验证处理 https://www.nuget.org/packages/MediatR.Extensions.FluentValidation.AspNetCore
只需在配置部分插入:
services.AddFluentValidation(new[] typeof(GenerateInvoiceHandler).GetTypeInfo().Assembly);
GitHub
【讨论】:
这不是被问到的。他们已经知道如何从管道中抛出验证异常。他们特别询问如何不抛出异常,而是返回错误。以上是关于返回带有错误的响应,而不是在验证管道 mediatr 3 中抛出异常的主要内容,如果未能解决你的问题,请参考以下文章
Gitlab管道失败:错误:准备失败:来自守护进程的错误响应:toomanyrequests
重定向到带有 SAML 响应的回调 url 时出现错误无法以角度发布
为啥“”.abcd 返回未定义的值而不是在 Javascript 中抛出未定义的错误(但 Typescript 抛出警告)