First off, I'm using Fluent Results in combination with Mediatr and Fluent Validation
I initially followed this article but instead of reinventing the wheel I started using FluentResults in my Fluent Validation pipeline. Basically all responses coming from my CQRS Queries are wrapped in the Result object, this avoids having to work with exceptions as a method of error handeling.
However, I can't get my pipeline to play nice:
public class ValidationPipeline<TRequest, TResponse>
: IPipelineBehavior<TRequest, TResponse>
where TResponse : class
where TRequest : IRequest<TResponse>
{
private readonly IValidator<TRequest> _compositeValidator;
public ValidationPipeline(IValidator<TRequest> compositeValidator)
{
_compositeValidator = compositeValidator;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var result = await _compositeValidator.ValidateAsync(request, cancellationToken);
if (!result.IsValid)
{
Error error = new Error();
var responseType = typeof(TResponse);
foreach (var validationFailure in result.Errors)
{
Log.Warning($"{responseType} - {validationFailure.ErrorMessage}");
error.Reasons.Add(new Error(validationFailure.ErrorMessage));
}
// This always returns null instead of a Result with errors in it.
var f = Result.Fail(error) as TResponse;
return f;
}
return await next();
}
}
I also have to somehow convert the Result object back to TResponse, where TResponse is always a Result
Any suggestions are greatly appreciated!
Edit:
Autofac integration
protected override void Load(ContainerBuilder builder)
{
var assembly = Assembly.GetExecutingAssembly();
// MediatR
builder.AddMediatR(assembly);
// Register the Command's Validators (Validators based on FluentValidation library)
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.IsClosedTypeOf(typeof(IValidator<>)))
.AsImplementedInterfaces();
// Register all the Command classes (they implement IRequestHandler) in assembly holding the Commands
builder.RegisterAssemblyTypes(assembly)
.AsClosedTypesOf(typeof(IRequestHandler<,>));
// Register Behavior Pipeline
builder.RegisterGeneric(typeof(ValidationPipeline<,>)).As(typeof(IPipelineBehavior<,>));
}
You should change
where TResponse : class
to
where TResponse : Result
and make sure all your requests are IRequest<Result>
where T is the actual response you want to return.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With