Nový generic host v .NET Core 3.0

Od verze: .NET Core 3.0
Miroslav Holec

Miroslav Holec

19. září. 2019

Šablony webových projektů ASP.NET Core 3.0 používají nově tzv. HostBuilder pro výchozí konfiguraci aplikace. Zatímco původní IWebHostBuilder měl omezené použití pouze pro účely webových aplikací, nový IHostBuilder lze použít i pro další druhy aplikací, jako například Worker Service.

K čemu je HostBuilder

Třída HostBuilder umožňuje konfiguraci základních komponent aplikace, mezi které patří zejména konfigurační nastavení, dependency injection a logování. Toto nastavení je provedeno při startu aplikace ve statické metodě Main().

Konfigurace WorkerService

WorkerService je .NET Core aplikace, určená pro odbavení dlouhotrvajících úloh (i jednorázových). Příkladem může být kontinuální běh a odbavování požadavků z fronty zpráv. Výchozí nastavení takové služby vypadá následovně:

Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    {
        services.AddHostedService<Worker>();
    })
    .Build()
    .Run();

Klíčové je volání CreateDefaultBuilder(), které na pozadí provede výchozí konfiguraci aplikace. Součástí takové konfigurace je registrace klíčových služeb do kontejneru, podpora logování do debug window + konzole + event logu OS a samozřejmě načtení konfigurace ze souborů appsettings.json + appsettings.[environment].json + konfigurace z proměnných prostředí nebo argumentů předaných do programu. Později v tomto článku je výchozí nastavení naznačeno kódem.

Pro worker service je signifikantní přidání tzv. hosted service do DI pomocí services.AddHostedService. HostedServices nejsou nic nového a již v minulosti jste je mohli používat společně s ASP.NET Core webovými aplikacemi.

Konfigurace webové aplikace

Díky generickému chování lze velmi podobně nastavit i webovou aplikaci.

Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(builder =>
    {
        builder.UseStartup<Startup>();
    })
    .Build()
    .Run();

V případě webové aplikace je zde nepatrný rozdíl, protože webová aplikace je specifická. Vyžaduje konfiguraci tzv. request pipeline, aby bylo jasné, jak mají být odbaveny požadavky proti webovému serveru. Proto je zde ještě metoda ConfigureWebHostDefaults(), která zajistí výchozí nastavení webového serveru. Konfigurace request pipeline pak probíhá v metodě Configure(), která je odsunuta pro přehlednost do třídy Startup.cs. Ta je registrována pomocí metody UseStartup().

Ačkoliv by i zde mohla být použita metoda ConfigureServices() přímo nad hostem, typicky se tato metoda taktéž přesouvá do Startup.cs, aby bylo vše pospolu.

Generická konfigurace

V praxi lze tedy generický host použít pro konfiguraci jak konzolových, tak webových aplikací. Pro ilustraci zkombinujeme dva příklady z článku a spustíme nejen webovou aplikaci, ale i souběžnou worker service. Místo třídy Startup.cs navíc použijeme přímo provolání metod Configure() a ConfigureServices() nad tradičním WebHost builderem.

Nastavení by mohlo vypadat takto:

await Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webHostBuilder =>
    {
        webHostBuilder
            .Configure(applicationBuilder =>
            {
                applicationBuilder.UseRouting();
                applicationBuilder.UseEndpoints(endpointBuilder =>
                {
                    endpointBuilder.MapControllers(); 

                });
            });

        webHostBuilder.ConfigureServices(collection =>
        {
            collection.AddControllers(); 
        });
    })
    .ConfigureServices(collection =>
    {
        collection.AddHostedService<Worker>(); 
    })
    .ConfigureAppConfiguration((host, builder) =>
    {
        builder.AddJsonFile("appsettings.json");
        builder.AddJsonFile($"appsettings.{host.HostingEnvironment.EnvironmentName}.json");
        builder.AddEnvironmentVariables();
        builder.AddCommandLine(args);
    })
    .ConfigureLogging((host, builder) =>
    {
        builder.AddConfiguration(host.Configuration);
        builder.AddDebug();
        builder.AddConsole();
        builder.AddEventSourceLogger();
    })
    .Build()
    .RunAsync();

Jak si můžete všimnout, máme generické nastavení konfigurace pro oba typy aplikací, společné logování i registraci služeb do DI. Pro webový host nicméně máme dodatečnou konfiguraci routování v metodě Configure().

Application Startup

Co se při takové konfiguraci děje po startu aplikace?

Co to znamená pro vývojáře

Úžasnou věc! Když budete chtít vytvořit konzolovku s podporou DI, logování a konfigurace, můžete nyní použít generic host a registrovat si vlastní hosted service, která zasupluje to, co jste doposud měli v metodě Main(). Klíčová výhoda je v tom, že zmíněná hosted service již plně podporuje DI a můžete si do ní injectnout služby dle potřeby. Navíc takových hosted services můžete spustit hned několik souběžně.

class Program
{
    static void Main(string[] args)
    {
        Host.CreateDefaultBuilder()
            .ConfigureServices(collection => collection.AddHostedService<Worker>())
            .Build()
            .Run();
......

public class Worker : IHostedService
    {
        private readonly ILogger<Worker> logger;

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

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            logger.LogInformation(nameof(StartAsync) + " runs");
            Console.WriteLine("Hello World!");
        }

Výsledkem bude v konzoli:

Generic Host Worker Service

TOP Termíny školení

ASP.NET Core se dočkal již své třetí verze a nabízí řadu možností pro vývoj webových aplikací a služeb. I v roce 2020 mám vypsané termíny na nejrůznější témata od základů .NET Core přes vývoj REST API až po mikroslužby pomocí gRPC.

Termín Místo
🍀 Novinky a změny v ASP.NET Core 3.x leden 2020 Praha více
🍀 Vývoj REST API v .NET Core (třídenní) leden 2020 Praha více
🍀 Vývoj aplikací v ASP.NET Core březen 2020 Praha více
🍀 Microservices v ASP.NET Core gRPC březen 2020 Praha více
🍀 Vývoj REST API v .NET Core (dvoudenní) březen 2020 Praha více
🍀 Tipy a triky pro ASP.NET Core březen 2020 Praha více

👨‍🎓 Školení 2020
👍 Vývoj aplikací v ASP.NET Core
👍 Vývoj REST služeb v .NET Core
👍 Microservices v ASP.NET Core gRPC
👍 Tipy a triky v ASP.NET Core
👍 Změny v ASP.NET Core 3.x