cqrs-validation-mediatr-fluentvalidation
cqrs-validation-mediatr-fluentvalidation copied to clipboard
How to use MustAsync in Pipeline
Hello, thank for you example. I am want to use Validator like
public class CustomerValidator : AbstractValidator<Customer> { SomeExternalWebApiClient _client;
public CustomerValidator(SomeExternalWebApiClient client) { _client = client;
RuleFor(x => x.Id).MustAsync(async (id, cancellation) =>
{
bool exists = await _client.IdExists(id);
return !exists;
}).WithMessage("ID Must be unique");
} }
When i am used this code, i am recive exception in line
public sealed class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : class, ICommand<TResponse> { private readonly IEnumerable<IValidator<TRequest>> _validators; public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators) => _validators = validators; public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next) { if (!_validators.Any()) { return await next(); } var context = new ValidationContext<TRequest>(request); var errorsDictionary = _validators .Select(x => x.Validate(context)) <-- Exceptions here, need to call ValidateAsync .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);
Can you to modify code for old cases (sync validators) and for new case (MustAsync calls)?
Hi, maybe you have to do something like this :
var context = new ValidationContext<TRequest>(request);
var tasks = _validators.Select(x => x.ValidateAsync(context, cancellationToken));
var result = await Task.WhenAll(tasks);
var add = result.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);
then you have to combine Validate Dictionary + ValidateAsync. But I don't like this approach, I prefer to check it in Handler. The validator shouldn't be heavy.
many thx for your code