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);
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>