Unable to resolve service for type X while attempting to activate Handler
See original GitHub issueHi, I recently tried upgrading a solution to MediatR 12 which was previously working fine with with MediatR 11. Now I’m getting this error and I can’t figure out what’s wrong:
System.InvalidOperationException: Unable to resolve service for type 'XXX.Core.Auth.Token.IJwtTokenProvider' while attempting to activate 'XXX.Core.Application.Handlers.Account.Login+Handler'.
IJwtTokenProvider
is just a simple service registered in DI: container.Register<IJwtTokenProvider, JwtTokenProvider>();
The Login
command is in the XXX.Core.Application
project. Program.cs
is in XXX.WebAPI
project.
If I try to inject and access IJwtTokenProvider
inside AccountController
(which normally dispatches the Login command), I can access the IJwtTokenProvider
without problems. However, it seems there’s some issue between MediatR and SimpleInjector when I inject IJwtTokenProvider
inside the Login handler. Also, it’s not IJwtTokenProvider
specifically that’s the problem, it’s other injected services as well.
This is my Program.cs (.net6)
var container = ContainerFactory.CreateSimpleInjectorContainer();
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
var appSettings = new AppSettings(builder.Configuration);
var appEnvironment = new AppEnvironment(appSettings);
builder.Host.UseDefaultServiceProvider((context, options) => options.ValidateOnBuild = false);
services.AddApplicationInsightsTelemetry();
services.AddIdentityServices(appEnvironment);
services.AddJwtAuthentication(appSettings);
services.AddWebApiServices(appSettings);
services.AddSwaggerServices(appSettings);
services.AddSimpleInjector(container);
services.AddMemoryCache();
if (appEnvironment.IsDev())
{
services.AddMiniProfiler();
}
// .Initialize() is my extension method where DI bindings for all the layters of the solution are set up
container.Initialize(appSettings, appEnvironment);
var app = builder.Build();
app.Services.UseSimpleInjector(container);
if (appEnvironment.IsDev())
{
app.UseDeveloperExceptionPage();
}
app.UseMiddleware<ExceptionHandlingMiddleware>();
app.UseLLBLGen(appSettings);
app.UseRouting();
app.UseCors(AppConfigOptions.DefaultCorsPolicyName);
app.UseAuthentication();
app.UseAuthorization();
app.UseSwagger(appSettings);
if (appEnvironment.IsDev())
{
app.UseMiniProfiler();
}
app.UseEndpoints
(
endpoints =>
{
endpoints.MapControllers();
}
);
container.Verify();
app.Run();
This is my MediatR 11 config which works fine:
public static void RegisterPipeline(this Container container, Assembly[] assemblies)
{
container.RegisterSingleton<IMediator, Mediator>();
container.Register(typeof(IRequestHandler<,>), assemblies);
container.RegisterHandlers(assemblies);
container.RegisterBehaviors();
container.Register(() => new ServiceFactory(container.GetInstance), Lifestyle.Singleton);
}
private static void RegisterHandlers(this Container container, Assembly[] assemblies)
{
container.RegisterHandlers(typeof(INotificationHandler<>), assemblies);
container.RegisterHandlers(typeof(IRequestExceptionAction<,>), assemblies);
container.RegisterHandlers(typeof(IRequestExceptionHandler<,,>), assemblies);
}
private static void RegisterHandlers(this Container container, Type collectionType, Assembly[] assemblies)
{
var handlerTypes = container.GetTypesToRegister
(
collectionType,
assemblies,
new TypesToRegisterOptions
{
IncludeGenericTypeDefinitions = true,
IncludeComposites = false
}
);
container.Collection.Register(collectionType, handlerTypes);
}
private static void RegisterBehaviors(this Container container)
{
container.Collection.Register
(
typeof(IPipelineBehavior<,>),
new[]
{
// NOTE: Add additional behaviors here. Order of binding = order of execution.
typeof(RequestExceptionProcessorBehavior<,>),
typeof(RequestExceptionActionProcessorBehavior<,>),
typeof(AuthenticationBehavior<,>),
typeof(AuthorizationBehavior<,>),
typeof(ValidationBehavior<,>),
typeof(MemoryCachedBehavior<,>),
typeof(DbTransactionalBehavior<,>)
}
);
}
Mediatr 12 changes:
public static void RegisterPipeline(this Container container, IServiceCollection services, Assembly[] assemblies)
{
container.RegisterSingleton<IMediator>(() => new Mediator(services.BuildServiceProvider()));
container.Register(typeof(IRequestHandler<,>), assemblies);
container.RegisterHandlers(assemblies);
container.RegisterBehaviors();
services.AddMediatR(config => config.RegisterServicesFromAssembly(typeof(Login).Assembly));
// I also tried these two, but I'm under the assumption that I need to register the assembly where the Login handler is?
// services.AddMediatR(config => config.RegisterServicesFromAssembly(typeof(Program).Assembly));
// services.AddMediatR(config => config.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly()));
}
Any rough ideas on what I might be doing wrong?
Thank you.
Issue Analytics
- State:
- Created 6 months ago
- Comments:6 (3 by maintainers)
Top GitHub Comments
No, none of those samples are up to date. It takes me a bit to update those since I really only use either the vanilla container or Lamar. Probably I’ll come back through and update them to use the various extensions of Ms.Ext.DI. I’m sure there are folks NOT using MS.Ext.DI but I’m not one of them.
Ok, that helps. At least I know not to use that sample for now. 😄 Thnx!