在流畅验证中验证失败时强制转换异常



我有一个。net 6 WebApi,我正在使用MediatR的Fluent验证。当没有验证错误时,我的一切都在工作。

当我强制执行错误时,我得到以下Exception:

Unable to cast object of type 'System.Collections.Generic.Dictionary`2[System.String,System.String[]]' to type 'System.Collections.Generic.IEnumerable`1[FluentValidation.Results.ValidationFailure]'.
at TestMediatR.Behaviours.ValidationBehaviour`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at WebApi.Controllers.v1.OrdersController.AddOrder(OrderTicketDto model) in D:Git RepositoriesCurrentWeb-SitesRestWebApisrcWebApiControllersv1OrdersController.cs:line 36

执行mediatR send的代码如下:

[HttpPost("AddOrder")]
public async Task<IActionResult> AddOrder([FromBody] OrderTicketDto model)
{
_logger.LogInformation("Adding Order: {@model}", model);
try
{
var response = await Mediator.Send(new AddOrderCommand()
{
OrderData = model.OrderTicket,
Url = model.SiteUrl,
Token = model.Token
});
return Ok(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "Add Order Error"); //<------ FluentValidation exception caught here
return BadRequest(ex.Message);
}
}

,上面执行的命令的验证是这样完成的

public class AddOrderCommandValidator : AbstractValidator<AddOrderCommand>
{
public AddOrderCommandValidator()
{
RuleFor(x => x.Url)
.NotEmpty()
.NotNull();
RuleFor(x => x.Token)
.NotEmpty()
.NotNull();
RuleFor(x => x.OrderData)
.NotNull();
}
}

验证器的注册在startup

中完成
public static IServiceCollection AddPiKSRestValidators(this IServiceCollection services)
{
var domainAssembly = typeof(GetTablesCommandValidator).GetTypeInfo().Assembly;
//Add FluentValidation
services.AddValidatorsFromAssembly(domainAssembly);
return services;
}

正如我所说的,当我传递有效的属性时,一切都工作,但通过设置说Token属性为null来强制它无效,我得到异常。

感觉我错过了什么。

问题出在validationbehavior

下面是报告错误的代码
public class ValidationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : notnull, IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
private readonly ILogger<TRequest> _logger;
public ValidationBehaviour(IEnumerable<IValidator<TRequest>> validators, ILogger<TRequest> logger)
{
_validators = validators;
_logger = logger;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
if (_validators.Any())
{
var context = new ValidationContext<TRequest>(request);
var errorsDictionary = _validators
.Select(x => x.Validate(context))
.SelectMany(x => x.Errors)
.Where(x => x != null)
.GroupBy(
x => x.PropertyName,
x => x.ErrorMessage,
(propertyName, errorMessages) => new
{
Key = propertyName,
Values = errorMessages.Distinct().ToArray()
})
.ToDictionary(x => x.Key, x => x.Values);
if (errorsDictionary.Any())
{
throw new ValidationException((IEnumerable<FluentValidation.Results.ValidationFailure>)errorsDictionary);
}
}
else
_logger.LogDebug("No Validators found");
return await next();
}
}

正如你所看到的,一个字典正试图被强制转换为(IEnumerable)

修复。

var errorsDictionary = _validators
.Select(x => x.Validate(context))
.SelectMany(x => x.Errors)
.Where(x => x != null)
.GroupBy(x => new {x.PropertyName, x.ErrorMessage })
.Select(x => x.FirstOrDefault())
.ToList();            
if (errorsDictionary.Any())
{
throw new ValidationException(errorsDictionary);
}

最新更新