19

I notice there is no explicit ILogger registration in ConfigureServices in Startup.cs.

First question: how does ILogger get injected into e.g. controllers.

Second question: how do I configure ILogger to get injected into middleware?

Nkosi
  • 235,767
  • 35
  • 427
  • 472
pomeroy
  • 1,377
  • 1
  • 12
  • 21

1 Answers1

25

Logging is added as part of the HostBuilder.Build process

private void CreateServiceProvider()
{
    var services = new ServiceCollection();
    services.AddSingleton(_hostingEnvironment);
    services.AddSingleton(_hostBuilderContext);
    services.AddSingleton(_appConfiguration);
    services.AddSingleton<IApplicationLifetime, ApplicationLifetime>();
    services.AddSingleton<IHostLifetime, ConsoleLifetime>();
    services.AddSingleton<IHost, Host>();
    services.AddOptions();
    services.AddLogging();//<--HERE

    //...

WebHostBuilder.BuildCommonServices

    private IServiceCollection BuildCommonServices(out AggregateException hostingStartupErrors)
    {

        //... code removed for brevity

        var services = new ServiceCollection();
        services.AddSingleton(_options);
        services.AddSingleton<IHostingEnvironment>(_hostingEnvironment);
        services.AddSingleton<Extensions.Hosting.IHostingEnvironment>(_hostingEnvironment);
        services.AddSingleton(_context);

        var builder = new ConfigurationBuilder()
            .SetBasePath(_hostingEnvironment.ContentRootPath)
            .AddConfiguration(_config);

        _configureAppConfigurationBuilder?.Invoke(_context, builder);

        var configuration = builder.Build();
        services.AddSingleton<IConfiguration>(configuration);
        _context.Configuration = configuration;

        var listener = new DiagnosticListener("Microsoft.AspNetCore");
        services.AddSingleton<DiagnosticListener>(listener);
        services.AddSingleton<DiagnosticSource>(listener);

        services.AddTransient<IApplicationBuilderFactory, ApplicationBuilderFactory>();
        services.AddTransient<IHttpContextFactory, HttpContextFactory>();
        services.AddScoped<IMiddlewareFactory, MiddlewareFactory>();
        services.AddOptions();
        services.AddLogging();

To get ILogger injected into a controller just include it in the constructor as a dependency

private readonly ILogger logger;

public MyController(ILogger<MyController> logger) {
    this.logger = logger;
}

//...

and the framework will inject it into the controller when it is being activated.

Reference Dependency injection into controllers in ASP.NET Core

The same can be done for Middleware vai constructor injection just like with the controller,

or directly into the Invoke method for per-request dependencies

public Task Invoke(HttpContext context, ILogger<MyMiddleware> logger) {
    //...
}

like any other injected service

Reference ASP.NET Core Middleware

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Very well written response. Thanks. It seems the per-request dependencies are limited. For example, I am not able to inject an ILogger into `Invoke`. Do you know where details on per-request dependencies are documented? – pomeroy Sep 04 '18 at 03:41