.NET Generic Host

The Worker Service templates create a .NET Generic Host, HostBuilder. The Generic Host can be used with other types of .NET applications, such as Console apps.

A host is an object that encapsulates an app's resources, such as:

  • Dependency injection (DI)
  • Logging
  • Configuration
  • IHostedService implementations

When a host starts, it calls IHostedService.StartAsync on each implementation of IHostedService registered in the service container's collection of hosted services. In a worker service app, all IHostedService implementations that contain BackgroundService instances have their BackgroundService.ExecuteAsync methods called.

The main reason for including all of the app's interdependent resources in one object is lifetime management: control over app startup and graceful shutdown. This is achieved with the Microsoft.Extensions.Hosting NuGet package.

Set up a host

The host is typically configured, built, and run by code in the Program class. The Main method:

The .NET Worker Service templates generate the following code to create a Generic Host:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
            });
}

Default builder settings

The CreateDefaultBuilder method:

  • Sets the content root to the path returned by GetCurrentDirectory().
  • Loads host configuration from:
    • Environment variables prefixed with DOTNET_.
    • Command-line arguments.
  • Loads app configuration from:
    • appsettings.json.
    • appsettings.{Environment}.json.
    • Secret Manager when the app runs in the Development environment.
    • Environment variables.
    • Command-line arguments.
  • Adds the following logging providers:
    • Console
    • Debug
    • EventSource
    • EventLog (only when running on Windows)
  • Enables scope validation and dependency validation when the environment is Development.

The ConfigureServices method exposes the ability to add services to the Microsoft.Extensions.DependencyInjection.IServiceCollection instance. Later, these services can be made available from dependency injection.

Framework-provided services

The following services are registered automatically:

IHostApplicationLifetime

Inject the IHostApplicationLifetime service into any class to handle post-startup and graceful shutdown tasks. Three properties on the interface are cancellation tokens used to register app start and app stop event handler methods. The interface also includes a StopApplication() method.

The following example is an IHostedService implementation that registers IHostApplicationLifetime events:

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace AppLifetime.Example
{
    public class ExampleHostedService : IHostedService
    {
        private readonly ILogger _logger;

        public ExampleHostedService(
            ILogger<ExampleHostedService> logger,
            IHostApplicationLifetime appLifetime)
        {
            _logger = logger;

            appLifetime.ApplicationStarted.Register(OnStarted);
            appLifetime.ApplicationStopping.Register(OnStopping);
            appLifetime.ApplicationStopped.Register(OnStopped);
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("1. StartAsync has been called.");

            return Task.CompletedTask;
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("4. StopAsync has been called.");

            return Task.CompletedTask;
        }

        private void OnStarted()
        {
            _logger.LogInformation("2. OnStarted has been called.");
        }

        private void OnStopping()
        {
            _logger.LogInformation("3. OnStopping has been called.");
        }

        private void OnStopped()
        {
            _logger.LogInformation("5. OnStopped has been called.");
        }
    }
}

The Worker Service template could be modified to add the ExampleHostedService implementation:

using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace AppLifetime.Example
{
    class Program
    {
        static Task Main(string[] args) =>
            CreateHostBuilder(args).Build().RunAsync();

        static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((_, services) =>
                    services.AddHostedService<ExampleHostedService>());
    }
}

The application would write the following sample output:

// Sample output:
//     info: ExampleHostedService[0]
//           1. StartAsync has been called.
//     info: ExampleHostedService[0]
//           2. OnStarted has been called.
//     info: Microsoft.Hosting.Lifetime[0]
//           Application started.Press Ctrl+C to shut down.
//     info: Microsoft.Hosting.Lifetime[0]
//           Hosting environment: Production
//     info: Microsoft.Hosting.Lifetime[0]
//           Content root path: ..\app-lifetime\bin\Debug\net5.0
//     info: ExampleHostedService[0]
//           3. OnStopping has been called.
//     info: Microsoft.Hosting.Lifetime[0]
//           Application is shutting down...
//     info: ExampleHostedService[0]
//           4. StopAsync has been called.
//     info: ExampleHostedService[0]
//           5. OnStopped has been called.

IHostLifetime

The IHostLifetime implementation controls when the host starts and when it stops. The last implementation registered is used.

Microsoft.Extensions.Hosting.Internal.ConsoleLifetime is the default IHostLifetime implementation. ConsoleLifetime:

  • Listens for Ctrl+C, SIGINT, or SIGTERM and calls StopApplication to start the shutdown process.
  • Unblocks extensions such as RunAsync and WaitForShutdownAsync.

IHostEnvironment

Inject the IHostEnvironment service into a class to get information about the following settings:

Host configuration

Host configuration is used to configure properties of the IHostEnvironment implementation.

The host configuration is available in HostBuilderContext.Configuration within the ConfigureAppConfiguration method. When calling the ConfigureAppConfiguration method, the HostBuilderContext and IConfigurationBuilder are passed into the configureDelegate. The configureDelegate is defined as an Action<HostBuilderContext, IConfigurationBuilder>. The host builder context exposes the .Configuration property, which is an instance of IConfiguration. It represents the configuration built from the host, whereas the IConfigurationBuilder is the builder object used to configure the app.

Tip

After ConfigureAppConfiguration is called the HostBuilderContext.Configuration is replaced with the app config.

To add host configuration, call ConfigureHostConfiguration on IHostBuilder. ConfigureHostConfiguration can be called multiple times with additive results. The host uses whichever option sets a value last on a given key.

The following example creates host configuration:

using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

class Program
{
    static async Task Main(string[] args)
    {
        using IHost host = CreateHostBuilder(args).Build();

        // Application code should start here.

        await host.RunAsync();
    }

    static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureHostConfiguration(configHost =>
            {
                configHost.SetBasePath(Directory.GetCurrentDirectory());
                configHost.AddJsonFile("hostsettings.json", optional: true);
                configHost.AddEnvironmentVariables(prefix: "PREFIX_");
                configHost.AddCommandLine(args);
            });
}

App configuration

App configuration is created by calling ConfigureAppConfiguration on IHostBuilder. ConfigureAppConfiguration can be called multiple times with additive results. The app uses whichever option sets a value last on a given key.

The configuration created by ConfigureAppConfiguration is available in HostBuilderContext.Configuration for subsequent operations and as a service from DI. The host configuration is also added to the app configuration.

For more information, see Configuration in .NET.

See also