Hosting in ASP.NET Core
By Luke Latham
ASP.NET Core apps configure and launch a host, which is responsible for app startup and lifetime management. At a minimum, the host configures a server and a request processing pipeline.
Setting up a host
ASP.NET Core 2.x
Create a host using an instance of WebHostBuilder. This is typically performed in your app’s entry point, the Main
method. In the project templates, Main
is located in Program.cs. A typical Program.cs calls CreateDefaultBuilder to start setting up a host:
[!code-csharpMain]
1: using System;
2: using System.Collections.Generic;
3: using System.IO;
4: using System.Linq;
5: using System.Threading.Tasks;
6: using Microsoft.AspNetCore;
7: using Microsoft.AspNetCore.Hosting;
8: using Microsoft.Extensions.Configuration;
9: using Microsoft.Extensions.Logging;
10:
11: namespace WebApplication1
12: {
13: #region snippet_Main
14: public class Program
15: {
16: public static void Main(string[] args)
17: {
18: BuildWebHost(args).Run();
19: }
20:
21: public static IWebHost BuildWebHost(string[] args) =>
22: WebHost.CreateDefaultBuilder(args)
23: .UseStartup<Startup>()
24: .Build();
25: }
26: #endregion
27: }
CreateDefaultBuilder
performs the following tasks:
- Configures Kestrel as the web server. For the Kestrel default options, see (xref:)the Kestrel options section of Kestrel web server implementation in ASP.NET Core.
- Sets the content root to Directory.GetCurrentDirectory.
- Loads optional configuration from:
- appsettings.json.
- appsettings.{Environment}.json.
- (xref:)User secrets when the app runs in the
Development
environment. - Environment variables.
- Command-line arguments.
- Configures (xref:)logging for console and debug output with (xref:)log filtering rules specified in a Logging configuration section of an appsettings.json or appsettings.{Environment}.json file.
- When running behind IIS, enables (xref:)IIS integration by configuring the base path and port the server should listen on when using the (xref:)ASP.NET Core Module. The module creates a reverse-proxy between IIS and Kestrel. Also configures the app to capture startup errors. For the IIS default options, see (xref:)the IIS options section of Host ASP.NET Core on Windows with IIS.
The content root determines where the host searches for content files, such as MVC view files. The default content root is Directory.GetCurrentDirectory. This results in using the web project’s root folder as the content root when the app is started from the root folder (for example, calling dotnet run from the project folder). This is the default used in Visual Studio and the dotnet new templates.
See (xref:)Configuration in ASP.NET Core for more information on app configuration.
[!NOTE] As an alternative to using the static
CreateDefaultBuilder
method, creating a host from WebHostBuilder is a supported approach with ASP.NET Core 2.x. See the ASP.NET Core 1.x tab for more information.
ASP.NET Core 1.x
Create a host using an instance of WebHostBuilder. This is typically performed in your app’s entry point, the Main
method. In the project templates, Main
is located in Program.cs. The following Program.cs demonstrates how to use WebHostBuilder
to build the host:
[!code-csharpMain]
1: using System;
2: using System.Collections.Generic;
3: using System.IO;
4: using System.Linq;
5: using System.Threading.Tasks;
6: using Microsoft.AspNetCore.Hosting;
7:
8: namespace WebApplication1
9: {
10: public class Program
11: {
12: public static void Main(string[] args)
13: {
14: var host = new WebHostBuilder()
15: .UseKestrel()
16: .UseContentRoot(Directory.GetCurrentDirectory())
17: .UseIISIntegration()
18: .UseStartup<Startup>()
19: .Build();
20:
21: host.Run();
22: }
23: }
24: }
WebHostBuilder
requires a server that implements IServer. The built-in servers are Kestrel and HTTP.sys (prior to the release of ASP.NET Core 2.0, HTTP.sys was called (xref:)WebListener). In this example, the UseKestrel extension method specifies the Kestrel server.
The content root determines where the host searches for content files, such as MVC view files. The default content root supplied to UseContentRoot
is Directory.GetCurrentDirectory. This results in using the web project’s root folder as the content root when the app is started from the root folder (for example, calling dotnet run from the project folder). This is the default used in Visual Studio and the dotnet new templates.
To use IIS as a reverse proxy, call UseIISIntegration as part of building the host. UseIISIntegration
doesn’t configure a server, like UseKestrel does. UseIISIntegration
configures the base path and port the server should listen on when using the (xref:)ASP.NET Core Module to create a reverse-proxy between Kestrel and IIS. To use IIS with ASP.NET Core, you must specify both UseKestrel
and UseIISIntegration
. UseIISIntegration
only activates when running behind IIS or IIS Express. For more information, see (xref:)Introduction to ASP.NET Core Module and (xref:)ASP.NET Core Module configuration reference.
A minimal implementation that configures a host (and an ASP.NET Core app) includes specifying a server and configuration of the app’s request pipeline:
var host = new WebHostBuilder()
.UseKestrel()
.Configure(app =>
{
app.Run(context => context.Response.WriteAsync("Hello World!"));
})
.Build();
host.Run();
When setting up a host, you can provide Configure and ConfigureServices methods. If you specify a Startup
class, it must define a Configure
method. For more information, see Application Startup in ASP.NET Core. Multiple calls to ConfigureServices
append to one another. Multiple calls to Configure
or UseStartup
on the WebHostBuilder
replace previous settings.
Host configuration values
WebHostBuilder provides methods for setting most of the available configuration values for the host, which can also be set directly with UseSetting and the associated key. When setting a value with UseSetting
, the value is set as a string (in quotes) regardless of the type.
Capture Startup Errors
This setting controls the capture of startup errors.
Key: captureStartupErrors
Type: bool (true
or 1
)
Default: Defaults to false
unless the app runs with Kestrel behind IIS, where the default is true
.
Set using: CaptureStartupErrors
When false
, errors during startup result in the host exiting. When true
, the host captures exceptions during startup and attempts to start the server.
ASP.NET Core 2.x
ASP.NET Core 1.x
Content Root
This setting determines where ASP.NET Core begins searching for content files, such as MVC views.
Key: contentRoot
Type: string
Default: Defaults to the folder where the app assembly resides.
Set using: UseContentRoot
The content root is also used as the base path for the Web Root setting. If the path doesn’t exist, the host fails to start.
ASP.NET Core 2.x
ASP.NET Core 1.x
Detailed Errors
Determines if detailed errors should be captured.
Key: detailedErrors
Type: bool (true
or 1
)
Default: false
Set using: UseSetting
When enabled (or when the Environment is set to Development
), the app captures detailed exceptions.
ASP.NET Core 2.x
ASP.NET Core 1.x
Environment
Sets the app’s environment.
Key: environment
Type: string
Default: Production
Set using: UseEnvironment
You can set the Environment to any value. Framework-defined values include Development
, Staging
, and Production
. Values aren’t case sensitive. By default, the Environment is read from the ASPNETCORE_ENVIRONMENT
environment variable. When using Visual Studio, environment variables may be set in the launchSettings.json file. For more information, see (xref:)Working with Multiple Environments.
ASP.NET Core 2.x
ASP.NET Core 1.x
Hosting Startup Assemblies
Sets the app’s hosting startup assemblies.
Key: hostingStartupAssemblies
Type: string
Default: Empty string
Set using: UseSetting
A semicolon-delimited string of hosting startup assemblies to load on startup. This feature is new in ASP.NET Core 2.0.
Although the configuration value defaults to an empty string, the hosting startup assemblies always include the app’s assembly. When you provide hosting startup assemblies, they’re added to the app’s assembly for loading when the app builds its common services during startup.
ASP.NET Core 2.x
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")
...
ASP.NET Core 1.x
This feature is unavailable in ASP.NET Core 1.x.
Prefer Hosting URLs
Indicates whether the host should listen on the URLs configured with the WebHostBuilder
instead of those configured with the IServer
implementation.
Key: preferHostingUrls
Type: bool (true
or 1
)
Default: true
Set using: PreferHostingUrls
This feature is new in ASP.NET Core 2.0.
ASP.NET Core 2.x
ASP.NET Core 1.x
This feature is unavailable in ASP.NET Core 1.x.
Prevent Hosting Startup
Prevents the automatic loading of hosting startup assemblies, including the app’s assembly.
Key: preventHostingStartup
Type: bool (true
or 1
)
Default: false
Set using: UseSetting
This feature is new in ASP.NET Core 2.0.
ASP.NET Core 2.x
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")
...
ASP.NET Core 1.x
This feature is unavailable in ASP.NET Core 1.x.
Server URLs
Indicates the IP addresses or host addresses with ports and protocols that the server should listen on for requests.
Key: urls
Type: string
Default: http://localhost:5000
Set using: UseUrls
Set to a semicolon-separated (;) list of URL prefixes to which the server should respond. For example, http://localhost:123
. Use “*” to indicate that the server should listen for requests on any IP address or hostname using the specified port and protocol (for example, http://*:5000
). The protocol (http://
or https://
) must be included with each URL. Supported formats vary between servers.
ASP.NET Core 2.x
WebHost.CreateDefaultBuilder(args)
.UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")
...
Kestrel has its own endpoint configuration API. For more information, see (xref:)Kestrel web server implementation in ASP.NET Core.
ASP.NET Core 1.x
var host = new WebHostBuilder()
.UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")
...
Shutdown Timeout
Specifies the amount of time to wait for the web host to shutdown.
Key: shutdownTimeoutSeconds
Type: int
Default: 5
Set using: UseShutdownTimeout
Although the key accepts an int with UseSetting
(for example, .UseSetting(WebHostDefaults.ShutdownTimeoutKey, "10")
), the UseShutdownTimeout
extension method takes a TimeSpan
. This feature is new in ASP.NET Core 2.0.
ASP.NET Core 2.x
ASP.NET Core 1.x
This feature is unavailable in ASP.NET Core 1.x.
Startup Assembly
Determines the assembly to search for the Startup
class.
Key: startupAssembly
Type: string
Default: The app’s assembly
Set using: UseStartup
You can reference the assembly by name (string
) or type (TStartup
). If multiple UseStartup
methods are called, the last one takes precedence.
ASP.NET Core 2.x
ASP.NET Core 1.x
Web Root
Sets the relative path to the app’s static assets.
Key: webroot
Type: string
Default: If not specified, the default is “(Content Root)/wwwroot”, if the path exists. If the path doesn’t exist, then a no-op file provider is used.
Set using: UseWebRoot
ASP.NET Core 2.x
ASP.NET Core 1.x
Overriding configuration
Use (xref:)Configuration to configure the host. In the following example, host configuration is optionally specified in a hosting.json file. Any configuration loaded from the hosting.json file may be overridden by command-line arguments. The built configuration (in config
) is used to configure the host with UseConfiguration
.
ASP.NET Core 2.x
hosting.json:
Overriding the configuration provided by UseUrls
with hosting.json config first, command-line argument config second:
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("hosting.json", optional: true)
.AddCommandLine(args)
.Build();
return WebHost.CreateDefaultBuilder(args)
.UseUrls("http://*:5000")
.UseConfiguration(config)
.Configure(app =>
{
app.Run(context =>
context.Response.WriteAsync("Hello, World!"));
})
.Build();
}
}
ASP.NET Core 1.x
hosting.json:
Overriding the configuration provided by UseUrls
with hosting.json config first, command-line argument config second:
public class Program
{
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("hosting.json", optional: true)
.AddCommandLine(args)
.Build();
var host = new WebHostBuilder()
.UseUrls("http://*:5000")
.UseConfiguration(config)
.UseKestrel()
.Configure(app =>
{
app.Run(context =>
context.Response.WriteAsync("Hello, World!"));
})
.Build();
host.Run();
}
}
[!NOTE] The
UseConfiguration
extension method isn’t currently capable of parsing a configuration section returned byGetSection
(for example,.UseConfiguration(Configuration.GetSection("section"))
. TheGetSection
method filters the configuration keys to the section requested but leaves the section name on the keys (for example,section:urls
,section:environment
). TheUseConfiguration
method expects the keys to match theWebHostBuilder
keys (for example,urls
,environment
). The presence of the section name on the keys prevents the section’s values from configuring the host. This issue will be addressed in an upcoming release. For more information and workarounds, see Passing configuration section into WebHostBuilder.UseConfiguration uses full keys.
To specify the host run on a particular URL, you could pass in the desired value from a command prompt when executing dotnet run
. The command-line argument overrides the urls
value from the hosting.json file, and the server listens on port 8080:
dotnet run --urls "http://*:8080"
Ordering importance
Some of the WebHostBuilder
settings are first read from environment variables, if set. These environment variables use the format ASPNETCORE_{configurationKey}
. To set the URLs that the server listens on by default, you set ASPNETCORE_URLS
.
You can override any of these environment variable values by specifying configuration (using UseConfiguration
) or by setting the value explicitly (using UseSetting
or one of the explicit extension methods, such as UseUrls
). The host uses whichever option sets the value last. If you want to programmatically set the default URL to one value but allow it to be overridden with configuration, you can use command-line configuration after setting the URL. See Overriding configuration.
Starting the host
ASP.NET Core 2.x
Run
The Run
method starts the web app and blocks the calling thread until the host is shutdown:
Start
You can run the host in a non-blocking manner by calling its Start
method:
If you pass a list of URLs to the Start
method, it listens on the URLs specified:
var urls = new List<string>()
{
"http://*:5000",
"http://localhost:5001"
};
var host = new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup>()
.Start(urls.ToArray());
using (host)
{
Console.ReadLine();
}
You can initialize and start a new host using the pre-configured defaults of CreateDefaultBuilder
using a static convenience method. These methods start the server without console output and with WaitForShutdown wait for a break (Ctrl-C/SIGINT or SIGTERM):
Start(RequestDelegate app)
Start with a RequestDelegate
:
using (var host = WebHost.Start(app => app.Response.WriteAsync("Hello, World!")))
{
Console.WriteLine("Use Ctrl-C to shutdown the host...");
host.WaitForShutdown();
}
Make a request in the browser to http://localhost:5000
to receive the response “Hello World!” WaitForShutdown
blocks until a break (Ctrl-C/SIGINT or SIGTERM) is issued. The app displays the Console.WriteLine
message and waits for a keypress to exit.
Start(string url, RequestDelegate app)
Start with a URL and RequestDelegate
:
using (var host = WebHost.Start("http://localhost:8080", app => app.Response.WriteAsync("Hello, World!")))
{
Console.WriteLine("Use Ctrl-C to shutdown the host...");
host.WaitForShutdown();
}
Produces the same result as Start(RequestDelegate app), except the app responds on http://localhost:8080
.
Start(Action
Use an instance of IRouteBuilder
(Microsoft.AspNetCore.Routing) to use routing middleware:
using (var host = WebHost.Start(router => router
.MapGet("hello/{name}", (req, res, data) =>
res.WriteAsync($"Hello, {data.Values["name"]}!"))
.MapGet("buenosdias/{name}", (req, res, data) =>
res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
.MapGet("throw/{message?}", (req, res, data) =>
throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
.MapGet("{greeting}/{name}", (req, res, data) =>
res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
.MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
Console.WriteLine("Use Ctrl-C to shutdown the host...");
host.WaitForShutdown();
}
Use the following browser requests with the example:
Request | Response |
---|---|
http://localhost:5000/hello/Martin |
Hello, Martin! |
http://localhost:5000/buenosdias/Catrina |
Buenos dias, Catrina! |
http://localhost:5000/throw/ooops! |
Throws an exception with string “ooops!” |
http://localhost:5000/throw |
Throws an exception with string “Uh oh!” |
http://localhost:5000/Sante/Kevin |
Sante, Kevin! |
http://localhost:5000 |
Hello World! |
WaitForShutdown
blocks until a break (Ctrl-C/SIGINT or SIGTERM) is issued. The app displays the Console.WriteLine
message and waits for a keypress to exit.
Start(string url, Action
Use a URL and an instance of IRouteBuilder
:
using (var host = WebHost.Start("http://localhost:8080", router => router
.MapGet("hello/{name}", (req, res, data) =>
res.WriteAsync($"Hello, {data.Values["name"]}!"))
.MapGet("buenosdias/{name}", (req, res, data) =>
res.WriteAsync($"Buenos dias, {data.Values["name"]}!"))
.MapGet("throw/{message?}", (req, res, data) =>
throw new Exception((string)data.Values["message"] ?? "Uh oh!"))
.MapGet("{greeting}/{name}", (req, res, data) =>
res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!"))
.MapGet("", (req, res, data) => res.WriteAsync("Hello, World!"))))
{
Console.WriteLine("Use Ctrl-C to shutdown the host...");
host.WaitForShutdown();
}
Produces the same result as Start(Actionhttp://localhost:8080
.
StartWith(Action
Provide a delegate to configure an IApplicationBuilder
:
using (var host = WebHost.StartWith(app =>
app.Use(next =>
{
return async context =>
{
await context.Response.WriteAsync("Hello World!");
};
})))
{
Console.WriteLine("Use Ctrl-C to shutdown the host...");
host.WaitForShutdown();
}
Make a request in the browser to http://localhost:5000
to receive the response “Hello World!” WaitForShutdown
blocks until a break (Ctrl-C/SIGINT or SIGTERM) is issued. The app displays the Console.WriteLine
message and waits for a keypress to exit.
StartWith(string url, Action
Provide a URL and a delegate to configure an IApplicationBuilder
:
using (var host = WebHost.StartWith("http://localhost:8080", app =>
app.Use(next =>
{
return async context =>
{
await context.Response.WriteAsync("Hello World!");
};
})))
{
Console.WriteLine("Use Ctrl-C to shutdown the host...");
host.WaitForShutdown();
}
Produces the same result as StartWith(Actionhttp://localhost:8080
.
ASP.NET Core 1.x
Run
The Run
method starts the web app and blocks the calling thread until the host is shutdown:
Start
You can run the host in a non-blocking manner by calling its Start
method:
If you pass a list of URLs to the Start
method, it listens on the URLs specified:
var urls = new List<string>()
{
"http://*:5000",
"http://localhost:5001"
};
var host = new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup>()
.Start(urls.ToArray());
using (host)
{
Console.ReadLine();
}
IHostingEnvironment interface
The IHostingEnvironment interface provides information about the app’s web hosting environment. You can use (xref:)constructor injection to obtain the IHostingEnvironment
in order to use its properties and extension methods:
public class CustomFileReader
{
private readonly IHostingEnvironment _env;
public CustomFileReader(IHostingEnvironment env)
{
_env = env;
}
public string ReadFile(string filePath)
{
var fileProvider = _env.WebRootFileProvider;
// Process the file here
}
}
You can use a (xref:)convention-based approach to configure your app at startup based on the environment. Alternatively, you can inject the IHostingEnvironment
into the Startup
constructor for use in ConfigureServices
:
public class Startup
{
public Startup(IHostingEnvironment env)
{
HostingEnvironment = env;
}
public IHostingEnvironment HostingEnvironment { get; }
public void ConfigureServices(IServiceCollection services)
{
if (HostingEnvironment.IsDevelopment())
{
// Development configuration
}
else
{
// Staging/Production configuration
}
var contentRootPath = HostingEnvironment.ContentRootPath;
}
}
[!NOTE] In addition to the
IsDevelopment
extension method,IHostingEnvironment
offersIsStaging
,IsProduction
, andIsEnvironment(string environmentName)
methods. See (xref:)Working with multiple environments for details.
The IHostingEnvironment
service can also be injected directly into the Configure
method for setting up your processing pipeline:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
// In Development, use the developer exception page
app.UseDeveloperExceptionPage();
}
else
{
// In Staging/Production, route exceptions to /error
app.UseExceptionHandler("/error");
}
var contentRootPath = env.ContentRootPath;
}
You can inject IHostingEnvironment
into the Invoke
method when creating custom (xref:)middleware:
public async Task Invoke(HttpContext context, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
// Configure middleware for Development
}
else
{
// Configure middleware for Staging/Production
}
var contentRootPath = env.ContentRootPath;
}
IApplicationLifetime interface
The IApplicationLifetime interface allows you to perform post-startup and shutdown activities. Three properties on the interface are cancellation tokens that you can register with Action
methods to define startup and shutdown events. There’s also a StopApplication
method.
Cancellation Token | Triggered when… |
---|---|
ApplicationStarted |
The host has fully started. |
ApplicationStopping |
The host is performing a graceful shutdown. Requests may still be processing. Shutdown blocks until this event completes. |
ApplicationStopped |
The host is completing a graceful shutdown. All requests should be completely processed. Shutdown blocks until this event completes. |
Method | Action |
---|---|
StopApplication |
Requests termination of the current application. |
public class Startup
{
public void Configure(IApplicationBuilder app, IApplicationLifetime appLifetime)
{
appLifetime.ApplicationStarted.Register(OnStarted);
appLifetime.ApplicationStopping.Register(OnStopping);
appLifetime.ApplicationStopped.Register(OnStopped);
Console.CancelKeyPress += (sender, eventArgs) =>
{
appLifetime.StopApplication();
// Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
}
private void OnStarted()
{
// Perform post-startup activities here
}
private void OnStopping()
{
// Perform on-stopping activities here
}
private void OnStopped()
{
// Perform post-stopped activities here
}
}
Troubleshooting System.ArgumentException
Applies to ASP.NET Core 2.0 Only
If you build the host by injecting IStartup
directly into the dependency injection container rather than calling UseStartup
or Configure
, you may encounter the following error: Unhandled Exception: System.ArgumentException: A valid non-empty application name must be provided
.
This occurs because the applicationName(ApplicationKey) (the current assembly) is required to scan for HostingStartupAttributes
. If you manually inject IStartup
into the dependency injection container, add the following call to your WebHostBuilder
with the assembly name specified:
Alternatively, add a dummy Configure
to your WebHostBuilder
, which sets the applicationName
(ApplicationKey
) automatically:
NOTE: This is only required with the ASP.NET Core 2.0 release and only when you don’t call UseStartup
or Configure
.
For more information, see Announcements: Microsoft.Extensions.PlatformAbstractions has been removed (comment) and the StartupInjection sample.
Additional resources
- Publish to Windows using IIS
- Publish to Linux using Nginx
- Publish to Linux using Apache
- (xref:)Host in a Windows Service
|