Unable to resolve Fluent Validation using MediatR without StructureMap

Viewed 2789

Trying to inject Fluent Validation in .Net Core 3.1 micro service with MediatR without Structure Map.

Added Below Nuget Packages:

<PackageReference Include="FluentValidation.AspNetCore" Version="8.6.2" />
<PackageReference Include="MediatR" Version="4.0.1" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="4.0.0" />

Startup.cs:

services.AddMvc(options =>
            {
                options.Filters.Add(typeof(HttpGlobalExceptionFilter));
                options.EnableEndpointRouting = false;
            }).AddControllersAsServices()
            .AddNewtonsoftJson()
            .AddViewLocalization(
                       LanguageViewLocationExpanderFormat.Suffix,
                       opts => { opts.ResourcesPath = "Resources"; })
            .AddDataAnnotationsLocalization()
            .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
            .AddFluentValidation(fv=> fv.RegisterValidatorsFromAssemblyContaining(typeof(Startup)));

Registered IPipelineBehavior and Validator:

services.AddMediatR();

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidatorBehaviour<,>));

ValidatorBehaviour.cs:

public class ValidatorBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    {
        private readonly IValidator<TRequest>[] _validators;
        public ValidatorBehaviour(IValidator<TRequest>[] validators) => _validators = validators;

        public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
        {
            var failures = _validators
                .Select(v => v.Validate(request))
                .SelectMany(result => result.Errors)
                .Where(error => error != null)
                .ToList();

            if (failures.Any())
            {
                var errorFieldsMessages = failures.Select(x => x.ErrorMessage + ", ").ToArray();

                throw new PomDetailsException(
                    $"Command Validation Errors for type {typeof(TRequest).Name}. " +
                    $"Validation failed : {string.Join(string.Empty, errorFieldsMessages)}", new ValidationException("Validation exception", failures));
            }

            var response = await next();
            return response;
        }
    }

Exception:

Unable to resolve service for type 'FluentValidation.IValidator`1[][]' while attempting to activate 

I am guessing I have the configuration wrong but I have been changing configuration several times with no success.

Any guidance would be much appreciated

1 Answers

You are trying to resolve collection of IValidator<TRequest> so you specified constructor parameter as IValidator<TRequest>[] (array). But the framework's DI requires using IEnumerable for this purpose. Update ValidatorBehaviour constructor as following and it will work as expected

private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidatorBehaviour(IEnumerable<IValidator<TRequest>> validators) => _validators = validators;
Related