Return 响应错误而不是在验证管道 mediatr 3 中抛出异常
Return response with errors instead of throwing exception in validation pipeline mediatr 3
我目前正在使用 Mediatr 3 中的管道行为进行请求验证。如果发生任何故障,我遇到的所有示例都会抛出 ValidationException,而不是这样做我想 return 响应错误。任何人都知道如何去做?
下面是验证管道的代码:
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();
}
}
注意:我发现了这个问题 ,我对答案的第一个选项很感兴趣,但没有关于如何做到这一点的明确示例。
这是我的回复class:
public class ResponseBase : ValidationResult
{
public ResponseBase() : base() { }
public ResponseBase(IEnumerable<ValidationFailure> failures) : base(failures) {
}
}
我在验证管道中添加了以下签名 class:
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);
但这给了我错误 'cannot convert to TResponse'。
如果有任何失败,请不要调用 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();
}
}
注:
您的 class(在我的示例中为 Thing
)必须是 TResponse
类型
几年前,我创建了通用的 Result 对象,我一直在不断改进它。很简单,检查https://github.com/martinbrabec/mbtools.
如果您认为结果(或结果<>)是应用层中的 return 类型 每个方法,那么您可以使用 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();
}
}
由于您的所有处理程序 return 结果(或基于结果的结果<>),您将能够无一例外地处理所有验证错误。
您可以使用包配置验证处理
https://www.nuget.org/packages/MediatR.Extensions.FluentValidation.AspNetCore
只需在配置部分插入:
services.AddFluentValidation(new[] {typeof(GenerateInvoiceHandler).GetTypeInfo().Assembly});
我目前正在使用 Mediatr 3 中的管道行为进行请求验证。如果发生任何故障,我遇到的所有示例都会抛出 ValidationException,而不是这样做我想 return 响应错误。任何人都知道如何去做?
下面是验证管道的代码:
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();
}
}
注意:我发现了这个问题
这是我的回复class:
public class ResponseBase : ValidationResult
{
public ResponseBase() : base() { }
public ResponseBase(IEnumerable<ValidationFailure> failures) : base(failures) {
}
}
我在验证管道中添加了以下签名 class:
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);
但这给了我错误 'cannot convert to TResponse'。
如果有任何失败,请不要调用 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();
}
}
注:
您的 class(在我的示例中为 Thing
)必须是 TResponse
几年前,我创建了通用的 Result 对象,我一直在不断改进它。很简单,检查https://github.com/martinbrabec/mbtools.
如果您认为结果(或结果<>)是应用层中的 return 类型 每个方法,那么您可以使用 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();
}
}
由于您的所有处理程序 return 结果(或基于结果的结果<>),您将能够无一例外地处理所有验证错误。
您可以使用包配置验证处理 https://www.nuget.org/packages/MediatR.Extensions.FluentValidation.AspNetCore
只需在配置部分插入:
services.AddFluentValidation(new[] {typeof(GenerateInvoiceHandler).GetTypeInfo().Assembly});