Hosting, Servers, and Environments

This section documents ASP.NET Core on .NET 10 (LTS), the current release — the minimal hosting model, the middleware pipeline, dependency injection, Minimal APIs, MVC & Razor Pages, Blazor with the current render modes, SignalR and gRPC, EF Core, ASP.NET Core Identity and policy-based authorization, output caching, rate limiting, and Native-AOT-aware building — as described by the official documentation at Microsoft Learn, which is the reference these pages are written and verified against.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. .NET ships a major release every November and its APIs continue to evolve: the examples here target .NET 10 / C# 14.

This section’s bibliography lists the reference material consulted while preparing these pages.

The host starts the app, owns dependency injection, configuration, logging, and the lifetime, and runs the web server. Environments let one build behave differently in Development, Staging, and Production.

WebApplication vs. the Generic Host

WebApplication.CreateBuilder is the web host: it configures Kestrel, HTTPS, routing, and the DI/config/logging stack in one call. For a non-web worker (a queue processor, a scheduled job) use Host.CreateApplicationBuilder, which gives the same DI/config/logging without a web server.

// worker process -- no HTTP server
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<InvoiceWorker>();
var host = builder.Build();
await host.RunAsync();

Host configuration (content root, environment name, DOTNET_/ASPNETCORE_ variables) is read before the app is built; app configuration (appsettings.json, user secrets, etc.) is layered on top. Inject IHostApplicationLifetime to react to ApplicationStarted / ApplicationStopping / ApplicationStopped. See .NET Generic Host.

Background work

Register long-running work as a hosted service. BackgroundService is the base class for a single ExecuteAsync loop; implement IHostedService directly for start/stop hooks.

public sealed class InvoiceWorker(IServiceScopeFactory scopeFactory, ILogger<InvoiceWorker> logger)
    : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        using var timer = new PeriodicTimer(TimeSpan.FromMinutes(5));
        while (await timer.WaitForNextTickAsync(stoppingToken))
        {
            using var scope = scopeFactory.CreateScope();   // resolve scoped services safely
            var svc = scope.ServiceProvider.GetRequiredService<IInvoiceService>();
            await svc.ProcessPendingAsync(stoppingToken);
        }
    }
}

builder.Services.AddHostedService<InvoiceWorker>();

The host waits up to HostOptions.ShutdownTimeout (default 30s) for stoppingToken-aware work to finish. See Background tasks with hosted services.

Servers

Kestrel is the default cross-platform server. Configure endpoints in appsettings.json or code; it supports HTTP/1.1, HTTP/2, and HTTP/3, TLS, and connection limits.

// appsettings.json
{
  "Kestrel": {
    "Endpoints": {
      "Https": { "Url": "https://*:7010", "Protocols": "Http1AndHttp2AndHttp3" }
    },
    "Limits": { "MaxConcurrentConnections": 1000, "MaxRequestBodySize": 10485760 }
  }
}
builder.WebHost.ConfigureKestrel(o => o.AddServerHeader = false);

IIS / ASP.NET Core Module hosts Kestrel on Windows: in-process (default, fastest — the app runs inside the IIS worker) or out-of-process (IIS reverse-proxies to Kestrel). HTTP.sys is a Windows-only alternative server with kernel-mode features (Windows auth, port sharing). See Kestrel and HTTP.sys.

Behind a reverse proxy

Nginx, Apache, YARP, or a cloud load balancer terminate TLS and forward requests. Enable forwarded-headers processing first in the pipeline so Request.Scheme and Connection.RemoteIpAddress reflect the original client:

builder.Services.Configure<ForwardedHeadersOptions>(o =>
{
    o.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    o.KnownProxies.Add(System.Net.IPAddress.Parse("10.0.0.5"));
});

app.UseForwardedHeaders();   // before UseHttpsRedirection, UseAuthentication, etc.

Environments

The ASPNETCORE_ENVIRONMENT variable (Development, Staging, Production, or any custom name) drives IWebHostEnvironment and which appsettings.{Environment}.json file is layered on.

if (app.Environment.IsDevelopment())
    app.UseDeveloperExceptionPage();
else
    app.UseExceptionHandler("/error");

if (app.Environment.IsEnvironment("QA"))
    app.UseCustomQaTools();

In Razor views, the <environment> tag helper renders content only for the named environments:

<environment include="Development"><script src="~/js/app.js"></script></environment>
<environment exclude="Development"><script src="~/js/app.min.js" asp-append-version="true"></script></environment>