Got error Unable to resolve service for type 'Microsoft.Extensions.Logging.ILoggerFactory' when using public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
Steps to reproduce the behavior:
Startup.cs with public class Startup
{
private readonly ILogger<Startup> _logger;
public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
{
Configuration = configuration;
_logger = loggerFactory.CreateLogger<Startup>();
}
An error occurred while starting the application.
InvalidOperationException: Unable to resolve service for type 'Microsoft.Extensions.Logging.ILoggerFactory' while attempting to activate 'WebApplication21.Startup'.
Microsoft.Extensions.DependencyInjection.ActivatorUtilities+ConstructorMatcher.CreateInstance(IServiceProvider provider)
InvalidOperationException: Unable to resolve service for type 'Microsoft.Extensions.Logging.ILoggerFactory' while attempting to activate 'WebApplication21.Startup'.
Microsoft.Extensions.DependencyInjection.ActivatorUtilities+ConstructorMatcher.CreateInstance(IServiceProvider provider)
Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, object[] parameters)
Microsoft.AspNetCore.Hosting.Internal.GenericWebHostBuilder.UseStartup(Type startupType, HostBuilderContext context, IServiceCollection services)
Microsoft.AspNetCore.Hosting.Internal.GenericWebHostBuilder+<>c__DisplayClass13_0.b__2(IApplicationBuilder app)
Microsoft.AspNetCore.Server.IIS.Core.IISServerSetupFilter+<>c__DisplayClass2_0.b__0(IApplicationBuilder app)
Microsoft.AspNetCore.HostFilteringStartupFilter+<>c__DisplayClass0_0.b__0(IApplicationBuilder app)
Microsoft.AspNetCore.Hosting.Internal.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
Successfully resove service ILoggerFactory loggerFactory
Is this something that is intended to be available?
If not then what is the intended workaround when there are components that need to be explicitly created in ConfigureServices that require an ILogger<>?
Issue is also reproduced on ASP.NET Core preview3. Related question on SO: https://stackoverflow.com/questions/54570904/unable-to-resolve-service-for-type-microsoft-extensions-logging-ilogger1webap
Resolving ILoggerFactory and ILogger<Startup> at Startup ctor works perfectly on ASP.NET Core 2.2. Moreover, this feature is listed in docs
I have the same issue. Tried to follow this guide setup Application Insights using this guide: https://docs.microsoft.com/en-us/azure/azure-monitor/app/ilogger#capturing-ilogger-logs-from-startupcs-programcs-in-aspnet-core-applications
and hit the same error.
I am using Preview 4
Any ideas on this gang?
@anurse This is the thing we talked about yesterday right?
Yes, in 3.0 we made a change to limit the types you can inject in to Startup. It was a misleading feature because it used a completely separate DI container to the rest of the app. You can still inject ILogger<T> in to your Configure method directly, but no longer in to the constructor or ConfigureServices. (cc @Tratcher)
See https://github.com/aspnet/Announcements/issues/353 for more details and https://github.com/aspnet/AspNetCore/issues/9337 for discussions on this topic.
If not then what is the intended workaround when there are components that need to be explicitly created in ConfigureServices that require an ILogger<>?
Can you provide an example of what you want to do? If you need to configure a service that depends on ILogger<T> you can either use constructor injection or you can provide a factory method (you should only use this if there is no other option, such as if you need to fill a property with a DI injected service):
public void ConfigureServices(IServiceCollection services)
{
// You can't access services (like ILogger) here, since the
// container hasn't been constructed yet. We made it work in 2.x by having two
// different containers, which was misleading and confusing. So we removed that in 3.0
services.AddSingleton<IMyService>((container) =>
{
// This func runs the first time the DI container needs to construct an instance
// of your type. You can access all the registered services here if you need to.
var logger = container.GetRequiredService<ILogger<MyService>>();
return new MyService() { Logger = logger };
});
}
I've just stuck with BackgroundService's because No service for type 'Microsoft.Extensions.Logging.ILogger' has been registered. Not typed ILogger! So much time spent for nothing ((
Closing this issue as the change was an intentional breaking change (see announcements linked above). BackgroundServices and IHostedServices are the preferred way to do initialization and non-request-bound logic anyway and those do provide access to DI-injected services like ILogger.
What about updating the docs to reflect this will break in future releases?
https://docs.microsoft.com/en-us/azure/azure-monitor/app/ilogger#capturing-ilogger-logs-from-startupcs-programcs-in-aspnet-core-applications
Those aren't our docs but I submitted a PR to update it: https://github.com/MicrosoftDocs/azure-docs/pull/33059 . Feel free to suggest edits for any other docs that are inconsistent here!
馃憤
How would you handle a case where another line inside the ConfigureServices needs the ILoggerFactory? I'm creating the LoggerFactory in my Program.cs, so it's already instantiated before the HostBuilder is created.
For example, the EntityFramework suggests that you configure it with the ILoggerFactory like so:
services.AddDbContext<MyDbContext>(options =>
{
options.UseLoggerFactory(loggerFactory); // Warning: Do not create a new ILoggerFactory instance each time. See https://docs.microsoft.com/en-us/ef/core/miscellaneous/logging
@joshmouch specifying the logger factory shouldn't be required when using EF in AspNetCore, it should resolve it automatically. If you have trouble making that work then please open a new issue for it.
Edit: nevermind, I missed the comment about already creating your own. If you created it in Program.cs then the only good way to flow it into Startup is with a static property.
@Tratcher ,
Slight correction. I create a Serilog.ILogger, then one of its extension methods creates the ILoggerFactory. However, I no longer have access to that ILoggerFactory inside Startup.cs. So here is another example of code that breaks. This is where you configure MassTransit to use the LoggerFactory.
services.AddMassTransit(a =>
{
...
a.AddBus(provider => Bus.Factory.CreateUsingAzureServiceBus(b =>
{
b.UseExtensionsLogging(loggerFactory);
Most helpful comment
Yes, in 3.0 we made a change to limit the types you can inject in to
Startup. It was a misleading feature because it used a completely separate DI container to the rest of the app. You can still injectILogger<T>in to yourConfiguremethod directly, but no longer in to the constructor orConfigureServices. (cc @Tratcher)See https://github.com/aspnet/Announcements/issues/353 for more details and https://github.com/aspnet/AspNetCore/issues/9337 for discussions on this topic.