40 KiB
title | author | description | ms.author | ms.custom | ms.date | uid |
---|---|---|---|---|---|---|
ASP.NET Core Web Host | guardrex | Learn about the web host in ASP.NET Core, which is responsible for app startup and lifetime management. | riande | mvc | 06/19/2018 | fundamentals/host/web-host |
ASP.NET Core Web Host
By Luke Latham
ASP.NET Core apps configure and launch a host. The host is responsible for app startup and lifetime management. At a minimum, the host configures a server and a request processing pipeline. This topic covers the ASP.NET Core Web Host (IWebHostBuilder), which is useful for hosting web apps. For coverage of the .NET Generic Host (IHostBuilder), see xref:fundamentals/host/generic-host.
Set up a host
::: moniker range=">= aspnetcore-2.0"
Create a host using an instance of IWebHostBuilder. This is typically performed in the 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:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
CreateDefaultBuilder
performs the following tasks:
- Configures Kestrel as the web server and configures the server using the app's hosting configuration providers. For the Kestrel default options, see xref:fundamentals/servers/kestrel#kestrel-options.
- Sets the content root to the path returned by Directory.GetCurrentDirectory.
- Loads host configuration from:
- Environment variables prefixed with
ASPNETCORE_
(for example,ASPNETCORE_ENVIRONMENT
). - Command-line arguments.
- Environment variables prefixed with
- Loads app configuration from:
- appsettings.json.
- appsettings.{Environment}.json.
- User secrets when the app runs in the
Development
environment using the entry assembly. - Environment variables.
- Command-line arguments.
- Configures logging for console and debug output. Logging includes log filtering rules specified in a Logging configuration section of an appsettings.json or appsettings.{Environment}.json file.
- When running behind IIS, enables IIS integration. Configures the base path and port the server listens on when using the 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:host-and-deploy/iis/index#iis-options.
- Sets ServiceProviderOptions.ValidateScopes to
true
if the app's environment is Development. For more information, see Scope validation.
The configuration defined by CreateDefaultBuilder
can be overridden and augmented by ConfigureAppConfiguration, ConfigureLogging, and other methods and extension methods of IWebHostBuilder. A few examples follow:
-
ConfigureAppConfiguration is used to specify additional
IConfiguration
for the app. The followingConfigureAppConfiguration
call adds a delegate to include app configuration in the appsettings.xml file.ConfigureAppConfiguration
may be called multiple times. Note that this configuration doesn't apply to the host (for example, server URLs or environment). See the Host configuration values section.WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true); }) ...
-
The following
ConfigureLogging
call adds a delegate to configure the minimum logging level (SetMinimumLevel) to LogLevel.Warning. This setting overrides the settings in appsettings.Development.json (LogLevel.Debug
) and appsettings.Production.json (LogLevel.Error
) configured byCreateDefaultBuilder
.ConfigureLogging
may be called multiple times.WebHost.CreateDefaultBuilder(args) .ConfigureLogging(logging => { logging.SetMinimumLevel(LogLevel.Warning); }) ...
-
The following call to UseKestrel overrides the default Limits.MaxRequestBodySize of 30,000,000 bytes established when Kestrel was configured by
CreateDefaultBuilder
:WebHost.CreateDefaultBuilder(args) .UseKestrel(options => { options.Limits.MaxRequestBodySize = 20000000; }); ...
The content root determines where the host searches for content files, such as MVC view files. When the app is started from the project's root folder, the project's root folder is used as the content root. This is the default used in Visual Studio and the dotnet new templates.
For more information on app configuration, see xref:fundamentals/configuration/index.
[!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. For more information, see the ASP.NET Core 1.x tab.
::: moniker-end
::: moniker range="< aspnetcore-2.0"
Create a host using an instance of WebHostBuilder. Creating a host is typically performed in the app's entry point, the Main
method. In the project templates, Main
is located in Program.cs:
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
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 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 is obtained for UseContentRoot
by Directory.GetCurrentDirectory. When the app is started from the project's root folder, the project's root folder is used as the content root. 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 listens on when using the ASP.NET Core Module to create a reverse proxy between Kestrel and IIS. To use IIS with ASP.NET Core, UseKestrel
and UseIISIntegration
must be specified. UseIISIntegration
only activates when running behind IIS or IIS Express. For more information, see xref:fundamentals/servers/aspnet-core-module and xref:host-and-deploy/aspnet-core-module.
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();
::: moniker-end
When setting up a host, Configure and ConfigureServices methods can be provided. If a Startup
class is specified, it must define a Configure
method. For more information, see xref:fundamentals/startup. Multiple calls to ConfigureServices
append to one another. Multiple calls to Configure
or UseStartup
on the WebHostBuilder
replace previous settings.
Host configuration values
WebHostBuilder relies on the following approaches to set the host configuration values:
- Host builder configuration, which includes environment variables with the format
ASPNETCORE_{configurationKey}
. For example,ASPNETCORE_ENVIRONMENT
. - Extensions such as UseContentRoot and UseConfiguration (see the Override configuration section).
- UseSetting and the associated key. When setting a value with
UseSetting
, the value is set as a string regardless of the type.
The host uses whichever option sets a value last. For more information, see Override configuration in the next section.
Application Key (Name)
The IHostingEnvironment.ApplicationName property is automatically set when UseStartup or Configure is called during host construction. The value is set to the name of the assembly containing the app's entry point. To set the value explicitly, use the WebHostDefaults.ApplicationKey:
Key: applicationName
Type: string
Default: The name of the assembly containing the app's entry point.
Set using: UseSetting
Environment variable: ASPNETCORE_APPLICATIONKEY
::: moniker range=">= aspnetcore-2.1"
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")
::: moniker-end
::: moniker range="< aspnetcore-2.1"
var host = new WebHostBuilder()
.UseSetting("applicationName", "CustomApplicationName")
::: moniker-end
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
Environment variable: ASPNETCORE_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.
::: moniker range=">= aspnetcore-2.0"
WebHost.CreateDefaultBuilder(args)
.CaptureStartupErrors(true)
::: moniker-end
::: moniker range="< aspnetcore-2.0"
var host = new WebHostBuilder()
.CaptureStartupErrors(true)
::: moniker-end
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
Environment variable: ASPNETCORE_CONTENTROOT
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.
::: moniker range=">= aspnetcore-2.0"
WebHost.CreateDefaultBuilder(args)
.UseContentRoot("c:\\<content-root>")
::: moniker-end
::: moniker range="< aspnetcore-2.0"
var host = new WebHostBuilder()
.UseContentRoot("c:\\<content-root>")
::: moniker-end
Detailed Errors
Determines if detailed errors should be captured.
Key: detailedErrors
Type: bool (true
or 1
)
Default: false
Set using: UseSetting
Environment variable: ASPNETCORE_DETAILEDERRORS
When enabled (or when the Environment is set to Development
), the app captures detailed exceptions.
::: moniker range=">= aspnetcore-2.0"
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
::: moniker-end
::: moniker range="< aspnetcore-2.0"
var host = new WebHostBuilder()
.UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
::: moniker-end
Environment
Sets the app's environment.
Key: environment
Type: string
Default: Production
Set using: UseEnvironment
Environment variable: ASPNETCORE_ENVIRONMENT
The environment can be set 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:fundamentals/environments.
::: moniker range=">= aspnetcore-2.0"
WebHost.CreateDefaultBuilder(args)
.UseEnvironment(EnvironmentName.Development)
::: moniker-end
::: moniker range="< aspnetcore-2.0"
var host = new WebHostBuilder()
.UseEnvironment(EnvironmentName.Development)
::: moniker-end
::: moniker range=">= aspnetcore-2.0"
Hosting Startup Assemblies
Sets the app's hosting startup assemblies.
Key: hostingStartupAssemblies
Type: string
Default: Empty string
Set using: UseSetting
Environment variable: ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
A semicolon-delimited string of hosting startup assemblies to load on startup.
Although the configuration value defaults to an empty string, the hosting startup assemblies always include the app's assembly. When hosting startup assemblies are provided, they're added to the app's assembly for loading when the app builds its common services during startup.
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")
::: moniker-end
::: moniker range=">= aspnetcore-2.1"
HTTPS Port
Set the HTTPS redirect port. Used in enforcing HTTPS.
Key: https_port
Type: string
Default: A default value isn't set.
Set using: UseSetting
Environment variable: ASPNETCORE_HTTPS_PORT
WebHost.CreateDefaultBuilder(args)
.UseSetting("https_port", "8080")
Hosting Startup Exclude Assemblies
DESCRIPTION
Key: hostingStartupExcludeAssemblies
Type: string
Default: Empty string
Set using: UseSetting
Environment variable: ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES
A semicolon-delimited string of hosting startup assemblies to exclude on startup.
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")
::: moniker-end
::: moniker range=">= aspnetcore-2.0"
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
Environment variable: ASPNETCORE_PREFERHOSTINGURLS
WebHost.CreateDefaultBuilder(args)
.PreferHostingUrls(false)
::: moniker-end
::: moniker range=">= aspnetcore-2.0"
Prevent Hosting Startup
Prevents the automatic loading of hosting startup assemblies, including hosting startup assemblies configured by the app's assembly. For more information, see xref:fundamentals/configuration/platform-specific-configuration.
Key: preventHostingStartup
Type: bool (true
or 1
)
Default: false
Set using: UseSetting
Environment variable: ASPNETCORE_PREVENTHOSTINGSTARTUP
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")
::: moniker-end
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
Environment variable: ASPNETCORE_URLS
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.
::: moniker range=">= aspnetcore-2.0"
WebHost.CreateDefaultBuilder(args)
.UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")
Kestrel has its own endpoint configuration API. For more information, see xref:fundamentals/servers/kestrel#endpoint-configuration.
::: moniker-end
::: moniker range="< aspnetcore-2.0"
var host = new WebHostBuilder()
.UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")
::: moniker-end
::: moniker range=">= aspnetcore-2.0"
Shutdown Timeout
Specifies the amount of time to wait for the web host to shut down.
Key: shutdownTimeoutSeconds
Type: int
Default: 5
Set using: UseShutdownTimeout
Environment variable: ASPNETCORE_SHUTDOWNTIMEOUTSECONDS
Although the key accepts an int with UseSetting
(for example, .UseSetting(WebHostDefaults.ShutdownTimeoutKey, "10")
), the UseShutdownTimeout extension method takes a TimeSpan.
During the timeout period, hosting:
- Triggers IApplicationLifetime.ApplicationStopping.
- Attempts to stop hosted services, logging any errors for services that fail to stop.
If the timeout period expires before all of the hosted services stop, any remaining active services are stopped when the app shuts down. The services stop even if they haven't finished processing. If services require additional time to stop, increase the timeout.
WebHost.CreateDefaultBuilder(args)
.UseShutdownTimeout(TimeSpan.FromSeconds(10))
::: moniker-end
Startup Assembly
Determines the assembly to search for the Startup
class.
Key: startupAssembly
Type: string
Default: The app's assembly
Set using: UseStartup
Environment variable: ASPNETCORE_STARTUPASSEMBLY
The assembly by name (string
) or type (TStartup
) can be referenced. If multiple UseStartup
methods are called, the last one takes precedence.
::: moniker range=">= aspnetcore-2.0"
WebHost.CreateDefaultBuilder(args)
.UseStartup("StartupAssemblyName")
WebHost.CreateDefaultBuilder(args)
.UseStartup<TStartup>()
::: moniker-end
::: moniker range="< aspnetcore-2.0"
var host = new WebHostBuilder()
.UseStartup("StartupAssemblyName")
var host = new WebHostBuilder()
.UseStartup<TStartup>()
::: moniker-end
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
Environment variable: ASPNETCORE_WEBROOT
::: moniker range=">= aspnetcore-2.0"
WebHost.CreateDefaultBuilder(args)
.UseWebRoot("public")
::: moniker-end
::: moniker range="< aspnetcore-2.0"
var host = new WebHostBuilder()
.UseWebRoot("public")
::: moniker-end
Override configuration
Use Configuration to configure the web host. In the following example, host configuration is optionally specified in a hostsettings.json file. Any configuration loaded from the hostsettings.json file may be overridden by command-line arguments. The built configuration (in config
) is used to configure the host with UseConfiguration. IWebHostBuilder
configuration is added to the app's configuration, but the converse isn't true—ConfigureAppConfiguration
doesn't affect the IWebHostBuilder
configuration.
::: moniker range=">= aspnetcore-2.0"
Overriding the configuration provided by UseUrls
with hostsettings.json config first, command-line argument config second:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("hostsettings.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();
}
}
hostsettings.json:
{
urls: "http://*:5005"
}
::: moniker-end
::: moniker range="< aspnetcore-2.0"
Overriding the configuration provided by UseUrls
with hostsettings.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("hostsettings.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();
}
}
hostsettings.json:
{
urls: "http://*:5005"
}
::: moniker-end
[!NOTE] The UseConfiguration extension method isn't currently capable of parsing a configuration section returned by
GetSection
(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.
UseConfiguration
only copies keys from the providedIConfiguration
to the host builder configuration. Therefore, settingreloadOnChange: true
for JSON, INI, and XML settings files has no effect.
To specify the host run on a particular URL, the desired value can be passed in from a command prompt when executing dotnet run. The command-line argument overrides the urls
value from the hostsettings.json file, and the server listens on port 8080:
dotnet run --urls "http://*:8080"
Manage the host
::: moniker range=">= aspnetcore-2.0"
Run
The Run
method starts the web app and blocks the calling thread until the host is shut down:
host.Run();
Start
Run the host in a non-blocking manner by calling its Start
method:
using (host)
{
host.Start();
Console.ReadLine();
}
If a list of URLs is passed 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();
}
The app 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<IRouteBuilder> routeBuilder)
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<IRouteBuilder> routeBuilder)
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 shut down the host...");
host.WaitForShutdown();
}
Produces the same result as Start(Action<IRouteBuilder> routeBuilder), except the app responds at http://localhost:8080
.
StartWith(Action<IApplicationBuilder> app)
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 shut down 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<IApplicationBuilder> app)
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 shut down the host...");
host.WaitForShutdown();
}
Produces the same result as StartWith(Action<IApplicationBuilder> app), except the app responds on http://localhost:8080
.
::: moniker-end
::: moniker range="< aspnetcore-2.0"
Run
The Run
method starts the web app and blocks the calling thread until the host is shut down:
host.Run();
Start
Run the host in a non-blocking manner by calling its Start
method:
using (host)
{
host.Start();
Console.ReadLine();
}
If a list of URLs is passed 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();
}
::: moniker-end
IHostingEnvironment interface
The IHostingEnvironment interface provides information about the app's web hosting environment. Use 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
}
}
A convention-based approach can be used to configure the app at startup based on the environment. Alternatively, 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. For more information, see xref:fundamentals/environments.
The IHostingEnvironment
service can also be injected directly into the Configure
method for setting up the 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;
}
IHostingEnvironment
can be injected into the Invoke
method when creating custom 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
IApplicationLifetime allows for post-startup and shutdown activities. Three properties on the interface are cancellation tokens used to register Action
methods that define startup and shutdown events.
Cancellation Token | Triggered when… |
---|---|
ApplicationStarted | The host has fully started. |
ApplicationStopped | The host is completing a graceful shutdown. All requests should be processed. Shutdown blocks until this event completes. |
ApplicationStopping | The host is performing a graceful shutdown. Requests may still be processing. Shutdown blocks until this event completes. |
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
}
}
StopApplication requests termination of the app. The following class uses StopApplication
to gracefully shut down an app when the class's Shutdown
method is called:
public class MyClass
{
private readonly IApplicationLifetime _appLifetime;
public MyClass(IApplicationLifetime appLifetime)
{
_appLifetime = appLifetime;
}
public void Shutdown()
{
_appLifetime.StopApplication();
}
}
Scope validation
::: moniker range=">= aspnetcore-2.0"
CreateDefaultBuilder sets ServiceProviderOptions.ValidateScopes to true
if the app's environment is Development.
::: moniker-end
When ValidateScopes
is set to true
, the default service provider performs checks to verify that:
- Scoped services aren't directly or indirectly resolved from the root service provider.
- Scoped services aren't directly or indirectly injected into singletons.
The root service provider is created when BuildServiceProvider is called. The root service provider's lifetime corresponds to the app/server's lifetime when the provider starts with the app and is disposed when the app shuts down.
Scoped services are disposed by the container that created them. If a scoped service is created in the root container, the service's lifetime is effectively promoted to singleton because it's only disposed by the root container when app/server is shut down. Validating service scopes catches these situations when BuildServiceProvider
is called.
To always validate scopes, including in the Production environment, configure the ServiceProviderOptions with UseDefaultServiceProvider on the host builder:
WebHost.CreateDefaultBuilder(args)
.UseDefaultServiceProvider((context, options) => {
options.ValidateScopes = true;
})
::: moniker range="= aspnetcore-2.0"
Troubleshooting System.ArgumentException
The following only applies to ASP.NET Core 2.0 apps when the app doesn't call UseStartup
or Configure
.
A host may be built by injecting IStartup
directly into the dependency injection container rather than calling UseStartup
or Configure
:
services.AddSingleton<IStartup, Startup>();
If the host is built this way, the following error may occur:
Unhandled Exception: System.ArgumentException: A valid non-empty application name must be provided.
This occurs because the app name (the name of the current assembly) is required to scan for HostingStartupAttributes
. If the app manually injects IStartup
into the dependency injection container, add the following call to WebHostBuilder
with the assembly name specified:
WebHost.CreateDefaultBuilder(args)
.UseSetting("applicationName", "AssemblyName")
Alternatively, add a dummy Configure
to the WebHostBuilder
, which sets the app name automatically:
WebHost.CreateDefaultBuilder(args)
.Configure(_ => { })
For more information, see Announcements: Microsoft.Extensions.PlatformAbstractions has been removed (comment) and the StartupInjection sample.
::: moniker-end