MediatR icon indicating copy to clipboard operation
MediatR copied to clipboard

Handler not found

Open darthg8r opened this issue 4 years ago • 9 comments

I'm trying to register a generic request handler for a generic request, but I'm getting the error below when calling

await _mediator.Send(new ExchangeOrderRequest<ExchangeOrderResponseSuccessEvent>());

System.InvalidOperationException: Handler was not found for request of type MediatR.IRequestHandler2[MyNamespace.ExchangeOrderRequest1[MyNamespace.ExchangeOrderResponseSuccessEvent],MediatR.Unit]. Register your handlers with the container. See the samples in GitHub for examples.

As side note, for giggles, I was able to inject an instance of IRequestHandler<ExchangeOrderRequest< ExchangeOrderResponseSuccessEvent>> into a controller just fine.

// Some assembly scanning, doesn't find my handler
services.AddMediatR(typeof(Startup), typeof(ExchangeOrderRequest), typeof(IDocumentMessage), typeof(OrderExecution.Handler));

// Try to manually add the handler.  Still doesn't find it
services.AddTransient<IRequestHandler<ExchangeOrderRequest<ExchangeOrderResponseSuccessEvent>>, ExchargeOrderRequestHandler<ExchangeOrderResponseSuccessEvent, ExchangeOrderRequest<ExchangeOrderResponseSuccessEvent>>>();




public class ExchargeOrderRequestHandler<TEvent, TRequest> : IRequestHandler<TRequest> 
	where TRequest : ExchangeOrderRequest<TEvent> 
	where TEvent : ExchangeOrderEvent
{
     // Stuff
}`

public class ExchangeOrderRequest<T>: DocumentMessage, IRequest where T: ExchangeOrderEvent
{
     // Stuff
}

public class ExchangeOrderEvent : IEvent
{
      // Stuff
 
		
}

What am I missing here?

darthg8r avatar Aug 19 '20 15:08 darthg8r

can you post a small repo that reproduces this? I know that constrained generics are not supported by the dotnet core DI but if you're registering them manually i'm not sure why it wouldn't work. It could be that you have to create a non-generic class and register that. Like:

public class ExchangeOrderSuccessHandler : ExchangeOrderRequestHandler<ExchangeOrderSuccessEvent, ExchangeOrderRequest<ExchangeOrderSuccessEvent>> { ... }

lilasquared avatar Aug 19 '20 18:08 lilasquared

@lilasquared Done: https://github.com/darthg8r/GenericMediatorHandler

It can't be the DI container though. I mentioned above:

As side note, for giggles, I was able to inject an instance of IRequestHandler<ExchangeOrderRequest< ExchangeOrderResponseSuccessEvent>> into a controller just fine.

darthg8r avatar Aug 19 '20 20:08 darthg8r

It looks like there's something off in the handler resolution. Explicitly adding Unit as a generic argument to the request handler seems to have fixed it..

services.AddTransient<IRequestHandler<ExchangeOrderRequest<ExchangeOrderResponseSuccessEvent>, Unit>, ExchargeOrderRequestHandler<ExchangeOrderResponseSuccessEvent, ExchangeOrderRequest<ExchangeOrderResponseSuccessEvent>>>();




public class ExchargeOrderRequestHandler<TEvent, TRequest> : IRequestHandler<TRequest, Unit> 
	where TRequest : ExchangeOrderRequest<TEvent> 
	where TEvent : ExchangeOrderEvent
{
     // Stuff
}

If I have some time, I'll see if I can find the actual bug in the library. Change to fix the problem can be seen in final commit in my repo.

darthg8r avatar Aug 19 '20 21:08 darthg8r

Looks like you don't even need Unit in the class definition, just in the registration. I think this is the same issue I mentioned above where dotnet core DI doesn't support generic registrations. When you use the IRequestHandler<T> interface I don't think the DI can properly map it to IRequestHandler<T, Unit>. I don't know for sure but thats my guess. If you use Lamar or another more mature DI you most likely won't have this problem.

lilasquared avatar Aug 19 '20 22:08 lilasquared

Hey there, my team and I are having the same problem due to the DI container of .NET. Is there any chance that this problem would be addressed somewhere?

HunteRoi avatar Jan 14 '21 13:01 HunteRoi

#635

I have a similar issue... I was able to solve it by using the AutoFac container but couldn't get it to work using the default container.

zachpainter77 avatar May 10 '21 23:05 zachpainter77

I have the same issue. Will it be solved?

lesnerd avatar Jul 13 '21 11:07 lesnerd

Use a different container, the Microsoft DI container often can't handle these edge cases, and this is one of them. It can't handle partially closed generic types.

Otherwise, it might be fixed in the registration side of things, we might be able to forward registrations perhaps?

jbogard avatar Jul 13 '21 13:07 jbogard

I use Ninject in a .Net 4.8 project and IRequestHandler<,> can't be resolved through the ContravariantBindingResolver based on MediatR.Examples.Ninject. Could it also be the container in fault?

WillMarcouiller avatar Oct 13 '21 17:10 WillMarcouiller