Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Fluent Results inside a MediatR validation pipeline to return a Result<TResponse>

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<,>));

    }
like image 515
Jason Landbridge Avatar asked Sep 05 '25 03:09

Jason Landbridge


1 Answers

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.

like image 140
dariogriffo Avatar answered Sep 09 '25 02:09

dariogriffo