Search code examples
.net-coremediatr

Adding validation using mediatR pipeline behaviour


As part of pipeline behavior, tried to set validation while creating customer

    public class ValidationBehavoir<TRequest, TResponse> : IPipelineBehavior<TRequest, TRequest>
        where TRequest : IRequest<TResponse>
    { 

        private readonly IEnumerable<IValidator<TRequest>> _validators;

        public ValidationBehavoir(IEnumerable<IValidator<TRequest>> validators)
        {
            _validators = validators;
        }
        public async Task<TRequest> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TRequest> next)
        {

            var context = new ValidationContext(request);
            var failures = _validators.Select(x => x.Validate(context)).SelectMany(x => x.Errors).ToList();

            if(failures.Any())
            {
                throw new ValidationException(failures);
            }

            return await next();
        } 
    }

Here are the services added while setting DI

            services.AddMediatR(typeof(Program));
            services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavoir<,>));
            services.AddMediatR(typeof(CreateCustomerCommand).GetTypeInfo().Assembly);
            services.AddMediatR(typeof(GetCustomersQuery).GetTypeInfo().Assembly);

But still, getting below error? 
System.ArgumentException: Implementation type 'CustomerApis.PipelineBehaviors.ValidationBehavoir`2[Customers.Service.Command.CreateCustomerCommand,Customers.Domain.Entities.Customer]' can't be converted to service type 'MediatR.IPipelineBehavior`2[Customers.Service.Command.CreateCustomerCommand,Customers.Domain.Entities.Customer]'
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ConstructorCallSite..ctor(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo, ServiceCallSite[] parameterCallSites)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.<>c__DisplayClass7_0.<GetCallSite>b__0(Type type)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)

Can someone please help me here?


Solution

  • public class ValidationBehavoir : IPipelineBehavior where TRequest : IRequest {

        private readonly IEnumerable<IValidator<TRequest>> _validators;
    
        public ValidationBehavoir(IEnumerable<IValidator<TRequest>> validators)
        {
            _validators = validators;
        }
    
        public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
        {
            var context = new ValidationContext(request);
            var failures = _validators.Select(x => x.Validate(context)).SelectMany(x => x.Errors).ToList();
    
            if (failures.Any())
            {
                throw new ValidationException(failures);
            }
    
            return await next();
        }
    }
    

    to

    public class ValidationBehavoir : IPipelineBehavior where TRequest : IRequest {

        private readonly IEnumerable<IValidator<TRequest>> _validators;
    
        public ValidationBehavoir(IEnumerable<IValidator<TRequest>> validators)
        {
            _validators = validators;
        }
    
        public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
        {
            var context = new ValidationContext(request);
            var failures = _validators.Select(x => x.Validate(context)).SelectMany(x => x.Errors).ToList();
    
            if (failures.Any())
            {
                throw new ValidationException(failures);
            }
    
            return await next();
        }
    }