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.

Validator for Generic Request not found

See original GitHub issue

I have a Generic SearchQuery used with MediatR

public record SearchQuery<TEntity, TEntityDto, TSearchDto>
    (TSearchDto Search) : IRequest<Result<PagedResultSet<TEntityDto>>>
    where TEntity : class, new()
    where TEntityDto : class, new()
    where TSearchDto : PagedResultsRequestDTO, new();

I defined a Validator for it:

public class SearchQueryValidator<TEntity, TEntityDto, TSearchDto> 
    : AbstractValidator<SearchQuery<TEntity, TEntityDto, TSearchDto>>
    where TEntity : class, new()
    where TEntityDto : class, new()
    where TSearchDto : PagedResultsRequestDTO, new()
{
    public SearchQueryValidator()
    {
        RuleFor(x => x.Search.PageSize).GreaterThan(0).
            WithMessage("Page size must be >= 0");
    }
}

There is a PipelineBehavior that handles the validation:

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

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

    public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
    {
        if (!_validators.Any())
        {
            return await next();
        }

        var context = new ValidationContext<TRequest>(request);

        var errorsDictionary = _validators
            .Select(x => x.Validate(context))
            .SelectMany(x => x.Errors)
            .Where(x => x != null);

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

        return await next();
    }
}

The validator and pipeline are registered

public static IServiceCollection AddApplication(this IServiceCollection services, IConfiguration configuration) =>
      services
          .AddAutoMapper(typeof(ApplicationServices))
          .AddMediatR(typeof(ApplicationServices).Assembly)
          .AddScoped<EventDispatcher>()
          .AddScoped(typeof(QueryService<,,>))
          .AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>))
          .AddValidatorsFromAssemblyContaining(typeof(SearchQueryValidator<,,>),ServiceLifetime.Transient);

  public class ApplicationServicesModule : Module
  {
      protected override void Load(ContainerBuilder builder)
      {
          builder.RegisterGeneric(typeof(GetByIdHandler<,>)).AsImplementedInterfaces();
          builder.RegisterGeneric(typeof(GetLookupService<>)).AsImplementedInterfaces();
          builder.RegisterGeneric(typeof(SearchQueryHandler<,,>)).AsImplementedInterfaces();
      }
  }

However, if I set a breakpoint here, there are 0 Validators found, and it’s looking for the concrete SearchQuery signature:

image

What am I missing?

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
jbogardcommented, Oct 13, 2022

Yep, MediatR delegates completely to the container to resolve services:

var behaviors = serviceProvider.GetServices<IPipelineBehavior<TRequest, TResponse>>();

No magic, pure DI. Try doing that yourself after registering everything, and if AutoFac can’t locate the services, it’s a registration or resolution problem.

0reactions
jbogardcommented, Oct 14, 2022

Yes typically open generics you have to register yourself (same with the MediatR.DI package). It’s too hard for these libraries to guess that you want to register open generics, they’ll only register the closed generics.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Spring Boot Validation not working with Generics
... can not valid Generics Type. I implementation 'org.springframework.boot:spring-boot-starter-validation' in build.gradle I have a object:
Read more >
Spring Validation Example - Spring MVC Form Validator
Form Validation Error Messages Resource Bundle​​ {modelObjectName}. {field} is looked up and if that is not found then {ValidationClass}.
Read more >
Validate Request Body and Parameter in Spring Boot
Validate Request parameter​​ The endpoint will look like this: /reservations/RSV-2021–1001. Since the user provided the reservation's code, we need to validate ...
Read more >
Validation and Exception Handling in Spring Boot
Request Validation ... Usually we send requests to the back-end to perform various things. One case can be considered as creating a resource....
Read more >
7. Validation, Data Binding, and Type Conversion
The Validator interface works using an Errors object so that while validating, validators can report validation failures to the Errors object. Let's consider...
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