By default, ASP.NET Core apps listen on the following URLs:
In this post I show 5 different ways to change which URLs your app listens on.
There are multiple ways to set the URLs that ASP.NET Core binds to on startup. I have an old post about the various options available to you that applies to ASP.NET Core 1.0, but the options available in ASP.NET Core 3.x are much the same:
UseUrls()
- Set the URLs to use statically in Program.cs.- Environment variables - Set the URLs using
DOTNET_URLS
orASPNETCORE_URLS
. - Command line arguments - Set the URLs with the
--urls
parameter when running from the command line. - Using launchSettings.json - Set the URLs using the
applicationUrl
property. KestrelServerOptions.Listen()
- Configure addresses for Kestrel server manually usingListen()
.
We'll look at each of these options in more detail below.
What URLs can you use?
In this post I describe the "URLs" you can bind to, but you can't use just any URL. There are essentially 3 classes of URLs that you can bind:
- The "loopback" hostname for IPv4 and IPv6 (e.g.
http://localhost:5000
), in the format:{scheme}://{loopbackAddress}:{port}
- A specific IP address available on your machine (e.g.
http://192.168.8.31:5005
), in the format{scheme}://{IPAddress}:{port}
- "Any" IP address for a given port (e.g.
http://*:6264
), in the format{scheme}://*:{port}
The port
in the above patterns is also optional - if you omit it, the default port for the given scheme
is used instead (port 80
for http
, port 443
for https
).
Which of these pattern you choose will depend on your deployment mechanism. For example, if you're hosting multiple applications on a "bare metal" machine, you may well need to set an explicit IPAddress. If you're hosting in a container, then you can generally use a localhost
address.
Watch out for the "any" IP address format - you don't have to use
*
, you can use anything that's not an IP Address and is notlocalhost
. That means you can usehttp://*
,http://+
,http://mydomain
, orhttp://example.org
. All of these behave identically, and listen on any IP address. If you only want to handle requests from a single hostname, you need to configure host filtering in addition.
Once you know the URLs you need to listen on, you need to tell your application about them. In this post I show 5 possible ways of doing that.
UseUrls()
The first, and easiest, option to set the binding URLs is to hard code them when configuring the IWebHostBuilder
using UseUrls()
:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.UseUrls("http://localhost:5003", "https://localhost:5004");
});
}
Hard-coding the URLs never feels like a particularly clean or extensible solution, so this option isn't really useful for anything more than demos.
Luckily, you can also load the URLs from an external configuration file, from environment variables, or from command line arguments.
Environment variables
.NET Core uses two types of configuration:
App configuration is the configuration you typically use in your application, and is loaded from appSettings.json and environment variables, among other places.
Host configuration is used to configure basic things about your application, like the hosting environment and the host URLs to use.
The host configuration is the one we're interested in when considering how to set the URLs for our application. By default, host configuration values are loaded from three different sources:
- Environment variables that have the prefix
DOTNET_
. The environment variables have the prefix removed and are added to the collection. - Command line arguments.
- Environment variables that have the prefix
ASPNETCORE_
. For ASP.NET Core apps only, these environment variables are also added. These aren't added if you are creating a generic-host-based worker service.
If you don't override them manually with UseUrls()
, then ASP.NET Core will use the value of the URLS
key from the configuration system. Based on the description above you can set the URLS using either of the following environment variables:
DOTNET_URLS
ASPNETCORE_URLS
If you set both of these environment variables, the
ASPNETCORE_URLS
parameter takes precedence.
You can set environment variables in the usual way based on your environment. For example, using the command line:
setx ASPNETCORE_URLS "http://localhost:5001"
using powershell
$Env: ASPNETCORE_URLS = "http://localhost:5001"
or using bash:
export ASPNETCORE_URLS="http://localhost:5001;https://localhost:5002"
As you can see above, you can also pass multiple addresses to listen on (using HTTP or HTTPS) by separating them with a semicolon.
Command line arguments
The other way to set host configuration values is to use the command line. Command line arguments override the value of the environment variables if they're set. Simply use the --urls
parameter:
dotnet run --urls "http://localhost:5100"
As before, you can pass multiple URLs to listen on by separating them with a semicolon:
dotnet run --urls "http://localhost:5100;https://localhost:5101"
Environment variables and command line arguments are probably the most common way to set URLs for an application in production, but they're a bit cumbersome for local development. It's often easier to using launchSettings.json instead.
launchSettings.json
Most .NET project templates include a launchSettings.json file in the Properties folder. This file contains various profiles for launching your ASP.NET Core application. A typical file contains one definition for launching the profile directly from the command line and one definition for launching the profile using IIS Express. This file drives the Debug drop-down in Visual Studio:
launchSettings.json provides an easy way to set the application URLs via the applicationUrl
property - you can see one under the iisSettings
for IIS express, and one under TestApp
(the name of the application for this file).
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:38327",
"sslPort": 44310
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"TestApp": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
You don't need to do anything special to use this file — dotnet run
will pick it up automatically.
launchSettings.json also provides an easy way to set additional environment variables using the
environmentVariables
, as you can see from the file above.
When you run your app from the command line with dotnet run
, your app will use the applicationUrl
properties in the "Project" command: https://localhost:5001;http://localhost:5000
in the file above. When you run the app using the "IISExpress" command, your app will use the applicationUrl
from the iisSettings.iisExpress
node: http://localhost:38327
This file is the easiest way to configure your environment when developing locally. In fact, you have to go out of your way to not use the launchSettings.json:
dotnet run --no-launch-profile
This will skip over the launchSettings.json file and fall back to the machine environment variables to determine the URLs instead.
All of the approaches shown so far set the URLs for Kestrel indirectly, but you can also set them directly.
KestrelServerOptions.Listen()
Kestrel is configured by default in almost all ASP.NET Core apps. If you wish, you can configure the endpoints for Kestrel manually, or via configuring KestrelServerOptions
using the IConfiguration
system.
I've never found myself actually needing to do this, and there's a lot of configuration options available, so for the most part I suggest referring to the documentation. As an example, you can use the Listen()
functions exposed by KestrelServerOptions
:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.UseKestrel(opts =>
{
// Bind directly to a socket handle or Unix socket
// opts.ListenHandle(123554);
// opts.ListenUnixSocket("/tmp/kestrel-test.sock");
opts.Listen(IPAddress.Loopback, port: 5002);
opts.ListenAnyIP(5003);
opts.ListenLocalhost(5004, opts => opts.UseHttps());
opts.ListenLocalhost(5005, opts => opts.UseHttps());
});
});
}
This configuration sets Kestrel listening on multiple addresses. It's hard-coded in the example above, but it doesn't have to be — you can bind to an IConfiguration
instead. When you set the URLs for kestrel in this way, it overrides the URLS
configuration value if you've set it through one of the other mechanisms as well, such as environment variables. You'll see a warning in the logs if that happens:
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Overriding address(es) 'http://localhost:5007'. Binding to endpoints defined in UseKestrel() instead.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://127.0.0.1:5002
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://[::]:5003
Personally I haven't found a need to set the listening endpoints in Kestrel this way, but it's good to be aware that you can get complete control of Kestrel like this if you need it.
Summary
In this post I showed five different ways you can set the URLs that your application listens on. UseUrls()
is one of the simplest, but generally isn't suitable for production workloads. The --urls
command line argument and ASPNETCORE_
/DOTNET_
environment variables are most useful for setting the values in production. The launchSettings.json file is very useful for setting the URLs in a development environment. If you need fine-grained control over your configuration, you can use Kestrel's Listen*
options directly. These can also be loaded from configuration for easy use in both production and development.