There are many ways that you can use to set URLs that ASP.NET Core binds to on startup. In this article, we will give you 8 ways to set the URLs for your ASP.NET Apps. Here we go.
What URLs can you use?
I list the “URLs” you can bind to in this post, but you can’t use any old URL. You can bind three different classes of URLs in essence:
- The “loopback” hostname for IPv4 and IPv6 (e.g.
http://localhost:5000
,http://127.0.0.1:5000
, orhttp://[::1]: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
).
In addition to TCP, which I’ll cover in another post, you can listen to requests on named pipes and Unix sockets in.NET 8.
The pattern you select will vary depending on your deployment method. For example, you might need to set an explicit IPAddress if you’re running several applications on a “bare metal” system. You can typically use “any” IP address when hosting in a container.
Be wary of the “any” IP address format; anything that isn’t an IP address or the loopback address, such as localhost, can be used instead of the required
*
.That means you can usehttp://*
,http://+
,http://mydomain
, orhttp://example.org
. When configuring Kestrel, all of these operate in the same way and allow listening on any IP address.
You must inform your application of the URLs you need to listen on once you are aware of them. I outline eight potential methods to accomplish that in this post.
UseUrls()
Using UseUrls()
to configure the WebApplicationBuilder and hardcoding the binding URLs is the simplest and first option. An extension method available on the WebHost
property is the UseUrls()
function:
var builder = WebApplication.CreateBuilder(args);
// Configure the URLs 👇
builder.WebHost.UseUrls("http://localhost:5003", "https://localhost:5004");
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Although the UseUrls()
method has been present in ASP.NET Core since version 1.0, a more recent method that uses WebApplication
directly has been available since.NET 6.
WebApplication.Urls
and WebApplication.Run()
WebApplication
exposes a Urls
property for configuring which URLs the application should listen to:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Urls.Add("http://*:5003"); // 👈 Add the URL
app.Run();
IServerAddressFeature
is exposed by the Urls
property behind the scenes. You are directly adding the addresses there, under Addresses collection:
public ICollection<string> Urls => ServerFeatures.GetRequiredFeature<IServerAddressesFeature>().Addresses;
A similar, related way to set the URL is to provide it in the call to app.Run()
. The URL you pass here is added to the IServerAddressesFeature
collection just before the application is started.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run("http://*:5003"); // 👈 Use the provided URL when running the application
Note that you can only provide a single URL when using the app.Run()
approach, so you need to use one of the other approaches if you want to set multiple URLs.
You won’t use this approach generally because hard-coding the URLs never feels like a particularly clean or extensible solution. Fortunately, environment variables, command line arguments, and configuration files can also be used to load the URLs.
Environment variables for the URL
A sophisticated, expandable configuration system built into ASP.NET Core allows it to load values from several different configuration sources. When using ConfigurationManager
in.NET 8, values are loaded by default from the following locations:
- appsettings.json JSON file
- Optional environment-specific JSON file, appsettings.ENVIRONMENT.json
- User Secrets
- Environment variables
- Command-line arguments
These are the default providers added, but you can add more to load from different locations. This system is used by ASP.NET Core to configure its internals, but you can also use it to load settings and customize your application.
The configuration system gains all of the following features from ASP.NET Core:
- Every environment variable is immediately added to the configuration.
- Prefix
DOTNET_
is eliminated from environment variables and their values are added to the collection. - Environment variables with the prefix
ASPNETCORE_
for ASP.NET Core applications are added to the collection after the prefix has been removed. If you are usingHostApplicationBuilder
to create a generic-host-based worker service, these are not added.
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 any of the following environment variables (casing doesn’t matter):
URLS
ASPNETCORE_URLS
DOTNET_URLS
If you set all of these environment variables in the order described above,
URLS
will have the highest precedence.
Depending on your environment, you can set environment variables in the standard manner. Using the command line, for instance:
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, by using a semicolon to separate the addresses, you can also pass multiple addresses to listen on (using HTTP or HTTPS).
Environment variables for the ports
The URLs can be set using the formats displayed at the beginning of this post by using the ASPNETCORE_URLS
and related environment variables, for instance:
ASPNETCORE_URLS="http://localhost:5001"
—listen to port 5001 on the loopback (localhost
address).ASPNETCORE_URLS="http://192.168.8.31:5001"
—listen to port 5001 on the specified IP address.ASPNETCORE_URLS="http://*:5001"
—listen to port 5001 on any IP address
One thing that’s always bugged me a little is the name of this variable. It implies (to me) that you can use things like http://example.com:5000
and your app will listen on that DNS name. That’s not the case. The above URL is treated exactly the same as http://*:5000
, i.e. it configures the app to listen to port 5000
on any IP address.
.NET 8 added new configuration keys to be more explicit about this. Instead of specifying “URLs” you specify HTTP_PORTS
and HTTPS_PORTS
, and these are used to bind any IP address. You can specify multiple ports using a semicolon separator. For example, if you set the following environment variables:
ASPNETCORE_HTTP_PORTS=5001;5002
ASPNETCORE_HTTPS_PORTS=5003
The aforementioned URLs are expanded to include:
- http://*:5001
- http://*:5002
- https://*:5003
As with other configuration keys, the values can be specified using ASPNETCORE_
, DOTNET_
, or “no prefix”:
HTTP_PORTS
(andHTTPS_PORTS
)ASPNETCORE_HTTP_PORTS
(andASPNETCORE_HTTPS_PORTS
)DOTNET_HTTP_PORTS
(orDOTNET_HTTPS_PORTS
)
Keep in mind that if you specify ASPNETCORE_URLS
(for example) along with one of these, the ASPNETCORE_URLS
value takes precedence, and the following warning is logged to the output:
warn: Microsoft.AspNetCore.Hosting.Diagnostics[15]
Overriding HTTP_PORTS '5002' and HTTPS_PORTS ''. Binding to values defined by URLS instead 'http://*:5003'.
The
ASPNETCORE_HTTP_PORTS
variable in.NET 8 docker images has a default value of 8080 (ASPNETCORE_URLS
was set in previous version docker images). SettingASPNETCORE_HTTP_PORTS
orASPNETCORE_URLS
will override this default value, among other methods.
Command line arguments are an additional means of adding values to configuration, in addition to environment variables.
Command line arguments
Using the command line is an additional method of adding values to the ASP.NET Core configuration system. If environment variables are set, the values are overridden by command line arguments. To run the application, just pass the “un-prefixed” environment variable as an argument and prefix with --
. As an illustration:
dotnet run -- --urls "http://localhost:5100"
As previously, you can pass multiple URLs to listen on by semicolons separating them:
dotnet run -- --urls "http://*:5100;http://localhost:5101"
This also functions with the dotnet
runtime version, in which dotnet
is called with the path of the compiled dll rather than dotnet run
:
dotnet ./WebApplication1.dll --urls "http://*:5100;http://localhost:5101"
You can also use --http_ports
and --https_ports
:
dotnet run -- --http_ports "5100;5101" --https_ports "5003;5004"
It should be noted that the additional
--
in thedotnet run
command is not a typo; rather, it serves to confirm that the arguments are understood as arguments for configuration rather than as arguments for the run command.
Although you can use any provider, environment variables and command line arguments are popular ways to add values to an ASP.NET Core configuration. The appsettings.json file is one of the most widely used methods (found in all default templates) for adding values to configuration.
appsettings.json
appsettings.json, and the environment-specific appsettings.Development.json files are included in virtually every modern .NET app template, and provide an easy way to add values to the ASP.NET Core configuration system.
Hopefully it’s no surprise that you can use these files to specify the URLs your app listens on using the same urls
, http_ports
and https_ports
keys you’ve seen already. The following adds the urls
key to the default template:
{
"urls": "http://*:5003", // 👈 Specify the URL
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
This version adds the http_ports
and https_ports
keys:
{
"http_ports": "5001;5002", // 👈 Expands to http://*:5001 and http://*:5002
"https_ports": "5003", // 👈 Expands to http2://*:5003
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
You can use the appsettings.json file for production and the appsettings to use different ports for development and production.For development, use Development.json. or whichever pattern suits you best.
As an alternative, launchSettings.json is a distinct JSON file that you can depend on.
launchSettings.json
Most.NET project templates include a launchSettings.json file in the Properties folder in addition to the appsettings.json file. This file contains multiple profiles for using dotnet run
to launch your ASP.NET Core application in development, rather than adding anything directly to your configuration.
Typically, a file has one definition for using IIS Express to launch the profile and one or more definitions for launching the profile directly from the command line. This file controls Visual Studio’s Debug drop-down menu:
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 each of the http
and https
profiles:
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:49412", // 👈 URL to use with IIS Express profile
"sslPort": 44381
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5005", // 👈 HTTP-only profile
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7045;http://localhost:5005", // 👈 HTTP & HTTPS profile
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"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: http://localhost:5005
in the http
profile above. When you run the app using the “IISExpress” command, your app will use the applicationUrl
from the iisSettings.iisExpress
node: http://localhost:49412
.
When developing locally, this file offers the simplest method for configuring your environment. Actually, you have to take special care to avoid using the launchSettings.JSON:
dotnet run --no-launch-profile
The launchSettings.json file will be ignored in favor of using configuration to find the URLs.
You can set the Kestrel URLs directly, but all of the methods that have been demonstrated thus far set them indirectly.
KestrelServerOptions.Listen()
In the majority of ASP.NET Core applications, Kestrel is set by default. Instead of using the higher-level configuration provided by ASPNETCORE_URLS
et al., you can choose to manually configure the Kestrel endpoints or to configure KestrelServerOptions
using the IConfiguration
system.
When you run behind IIS out-of-process or self-host your application, Kestrel is used by default. You use an IIS HTTP Server when you run in-process. You can also use the HTTP.sys kernel driver on Windows.
Configuring HTTPS certificates, SSL/TLS protocols and cipher suites, and Server Name Indications (SNI) configurations will probably require you to use the Kestrel Listen()
functions. Since there are many configuration options, I recommend consulting the documentation the majority of the time. The Listen()
functions made available by KestrelServerOptions
can be used, for instance, in the following ways:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(opts =>
{
opts.Listen(IPAddress.Loopback, port: 5002); // listen on http://localhost:5002
opts.ListenAnyIP(5003); // listen on http://*:5003
opts.ListenLocalhost(5004, listenOptions => listenOptions.UseHttps()); // listen on https://localhost:5004
opts.ListenAnyIP(5005, listenOptions => // listen on https://*:5005
{
listenOptions.UseHttps("testCert.pfx", "testPassword");
});
});
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Kestrel is configured to listen on multiple addresses. If you set the URLS
configuration value using one of the other mechanisms, like environment variables, it gets overwritten when you set the URLs for Kestrel in this manner. If that occurs, a warning will appear in the logs:
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Overriding address(es) 'http://localhost:5165'. Binding to endpoints defined via IConfiguration and/or UseKestrel() instead.
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://127.0.0.1:5002
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://[::]:5003
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://localhost:5004
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://[::]:5005
Unlike how you can bind to urls
or http_ports
, you can use IConfiguration
to bind the Kestrel configuration instead of having to hardcode it, as was the case in the example above. For instance, appsettings.json could be used to configure the Kestrel configuration mentioned above:
{
"Kestrel": {
"Endpoints": {
"HttpLoopback": {
"Url": "http://localhost:5002"
},
"HttpAny": {
"Url": "http://*:5003"
},
"HttpsDefaultCert": {
"Url": "https://localhost:5004"
},
"HttpsInlineCertFile": {
"Url": "https://*:5005",
"Certificate": {
"Path": "testCert.pfx",
"Password": "testPassword"
}
}
}
}
}
One nice thing about this is that you can configure your app’s binding and HTTPS certificate completely from the IConfiguration
. This implies that you can store your certificates and certificate passwords using safe secret storage solutions like Key Vault. You won’t even need to call ConfigureKestrel()
if you use the configuration from appsettings.json mentioned above.
Summary
I demonstrated eight different methods in this post for configuring the URLs that your application listens on. use WebApplication
and UseUrls()
.The simplest are urls, but they are typically not appropriate for use in production workloads by themselves. For setting the values in production, the ASPNETCORE_
/DOTNET_
environment variables and the command line arguments --urls
, --http_ports
, and --https_ports
are most helpful. Setting up URLs in a development environment is made very easy with the help of the launchSettings.json file. You can use Kestrel’s Listen*
options directly if you require more precise configuration control. Additionally, these can be loaded from configuration for simple use in development and production scenarios.
Javier is Content Specialist and also .NET developer. He writes helpful guides and articles, assist with other marketing and .NET community work