question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

FluentValidation within MediatR pipeline using .NET Core's default DI container

See original GitHub issue

I would greatly appreciate it if someone could help me to integrate FluentValidation into the MediatR pipeline using .NET Core’s default DI container.

I have the following classes which represent my request, my handler, and my FluentValidation Validator: `

public class SimpleRequestRequest : IRequest<string>
{
	public int Id { get; set; }
}

public class SimpleRequestRequestValidator : AbstractValidator<SimpleRequestRequest>
{

	public SimpleRequestRequestValidator(SimpleRequestRequest request)
	{
	
		RuleFor(m => m.Id).MustAsync(BeValidIdAsync).WithMessage("Id must be greater than 0, it is {PropertyValue}");
	}

	private Task<bool> BeValidIdAsync(int id, CancellationToken cancellationToken)
	{
		return Task.FromResult( id > 0);
	}
}

public class SimpleRequestHandler : IRequestHandler<SimpleRequestRequest, string>
{
	public Task<string> Handle(SimpleRequestRequest request, CancellationToken cancellationToken)
	{
		return Task.FromResult($"Request was for {request.Id}");
	}
}

`

In order to inject FluentValidation, I have created the following behavior class: `

public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
{
	private readonly IEnumerable<IValidator<TRequest>> _validators;

	public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
	{
		_validators = validators;
	}

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

		if (failures.Count != 0)
		{
			throw new ValidationException(failures);
		}

		return next();
	}
}

`

Within my ASP.NET Core (2.1) WebApi, I have the following controller: `

[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
    private readonly IMediator _mediator;

    public TestController(IMediator mediator)
    {
	    _mediator = mediator;
    }

	// GET api/values/5
	[HttpGet("{id}")]
    public Task<string> Get(int id)
	{
		return _mediator.Send(new SimpleRequestRequest {Id = id});
    }

}

`

What I would like to have happen is when the controller calls _mediator.Send, I would like the Validation to run. I have this working in a non .NET core solution using the IRequestPreProcessor interface. I am just trying to update things so that I can do the same type of thing within .NET Core.

I believe my struggle is in registering the services. This is in the Startup.cs file. `

	public void ConfigureServices(IServiceCollection services)
	{
		services.AddMvc()
			.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
			.AddFluentValidation(fv=> fv.RegisterValidatorsFromAssemblyContaining(typeof(SimpleRequestRequestValidator)));
		
		services.AddMediatR(typeof(SimpleRequestHandler).Assembly);
		services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
		AssemblyScanner.FindValidatorsInAssembly(typeof(SimpleRequestHandler).Assembly)
			.ForEach(result =>
				{
					Console.WriteLine("Here we are");
					//services.AddScoped(result.InterfaceType, result.ValidatorType);
					services.AddTransient(result.InterfaceType, result.ValidatorType);
				}
				);
	}

`

Within this, I don’t think I need to call AddFluentValidation on the AddMvc builder. I really am not trying to overwrite the validation on the Web-API controllers. I just want it on the MediatR portion.

The issue I am running into, however, is when I call the WebAPI controller. It gets to _mediator.Send, and it throws the following error: Unable to resolve service for type ‘MediatrSample.DLL.BLL.Requests.SimpleRequestRequest’ while attempting to activate ‘MediatrSample.DLL.BLL.Requests.SimpleRequestRequestValidator’.

It is like the DI container for .NET Core doesn’t know how to create the SimpleRequestRequest to pass into the Validator.

Any thoughts or ideas? I have found a number of articles that use things like AutoFac for the DI Container, but I am trying to use the default DI in .NET Core.

Ideally, I don’t want to have to register all validation and request classes. I would rather it discovers it automatically. I thought that is what I was doing with the AssemblyScanner, but apparently not.

Thank you!

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:4
  • Comments:13 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
dbeylkhanovcommented, Jan 31, 2020

maybe it will be useful for other developers who will face the issue like me. So my issue was in collection type for IValidator<TRequest> validators, because I was using IList and was getting the error something like - Unable to resolve service for type 'System.Collections.Generic.IList1[FluentValidation.IValidator... Finally, after replacing the IList type on IEnumerable, this error was disappeared. It means that the container can be set up to resolve only for IEnumerable collection

3reactions
Lapeno94commented, Oct 31, 2019

I know it is late to answer but u can use: services.AddValidatorsFromAssemblyContaining(typeof(yourCommandValidator));

Read more comments on GitHub >

github_iconTop Results From Across the Web

MediatR Pipeline Behaviour in ASP.NET Core - Logging ...
This helps keep the code well organized and easy to test. Before continuing, let's register this validator with the ASP.NET Core DI Container....
Read more >
CQRS Validation Pipeline with MediatR and FluentValidation
Naturally, they cover the Read part in CRUD. To learn how to implement CQRS with MediatR in your ASP.NET Core application, be sure...
Read more >
Using multiple FluentValidators on MediatR pipeline
Service resolution depends on the DI container that you use. It seems that you use built-in .NET Core container and it cannot resolve ......
Read more >
ASP.NET Core — FluentValidation documentation
With automatic validation, FluentValidation plugs into the validation pipeline that's part of ASP.NET Core MVC and allows models to be validated before a ......
Read more >
Use MediatR with FluentValidation in the ASP.Net Core ...
What is it? For a while I am using MediatR to handle messages in my ASP.Net Core applications. (New to the Mediator design...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found