I'm trying to configure kestrel so that when it's in it's raw mode it runs on a specific port. However to do so it appears that the launchsettings.json needs to pass command line args to do so since there is no straight up option and it always runs on port 5000 which will obviously conflict if you have an api you need to run and a website.
So I added the CommandLine package to my site and you can indeed use builder.AddCommandLine() in the startup.cs file.
The problem is how to get the args from the program.cs to the Startup.cs or look them up other than a static variable.
Kind of makes the extension method pointless if you can't get at the args.
Any better ways of doing this?
A simple solution is to access the command line arguments through the Environment.GetCommandLineArgs method.
You only need to make sure that you remove the first argument, which is the executable name:
public class Startup
{
public Startup(IHostingEnvironment env)
{
var args = Environment.GetCommandLineArgs().Skip(1).ToArray();
var builder = new ConfigurationBuilder();
builder.AddCommandLine(args);
Configuration = builder.Build();
}
}
UPDATE
I actually found what seems more elegant solution:
IConfigurationRoot
in Program (using CommandLineApplication, good article & examples here)IConfigurationRoot
to Startup
via DI container.Like so:
public static IWebHost BuildWebHost(string[] args)
{
var configuration = LoadConfiguration(args);
// Use Startup as always, register IConfigurationRoot to services
return new WebHostBuilder()
.UseKestrel()
.UseConfiguration(configuration)
.ConfigureServices(s => s.AddSingleton<IConfigurationRoot>(configuration))
.UseStartup<Startup>()
.Build();
}
public class Startup
{
public Startup(IConfigurationRoot configuration)
{
// You get configuration in Startup constructor or wherever you need
}
}
Example implementation of LoadConfiguration, which parses args and builds IConfigurationRoot
(in this example configuration file name can be overridden in command line arguments):
private static IConfigurationRoot LoadConfiguration(string[] args)
{
var configurationFileName = "configuration.json";
var cla = new CommandLineApplication(throwOnUnexpectedArg: true);
var configFileOption = cla.Option("--config <configuration_filename>", "File name of configuration", CommandOptionType.SingleValue);
cla.OnExecute(() =>
{
if (configFileOption.HasValue())
configurationFileName = configFileOption.Value();
return 0;
});
cla.Execute(args);
return new ConfigurationBuilder()
.SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
.AddJsonFile(configurationFileName, optional: false, reloadOnChange: true)
.AddCommandLine(args)
.Build();
}
OLD ANSWER
You can instantiate Startup class by yourself and pass it as instances to WebHostBuilder. It is somewhat not so elegant, but doable. From here.
public static IWebHost BuildWebHost(string[] args)
{
// Load configuration and append command line args
var config = new ConfigurationBuilder()
.SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
.AddJsonFile("configuration.json")
.AddCommandLine(args)
.Build();
// pass config to Startup instance
var startup = new Startup(config);
// Instead of using UseStartup<Startup>()
// Register startup to services
return new WebHostBuilder()
.UseKestrel()
.UseSetting("applicationName", "Your.Assembly.Name")
.UseConfiguration(config)
.ConfigureServices(services => services.AddSingleton<IStartup>(startup))
.Build();
}
Couple of caveats are:
IStartup
which is limited for Configure
method in parameters to only Configure(IApplicationBuilder app)
instead of full Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime lifetime)
applicationName
parameter manually as in my example. I'm testing this on 2.0.0-preview1-final
Kestrel can be configured to listen on a different port in several ways. None of these methods need to happen in the Startup
class, but rather in the Main
method of the Program
class. Using the AddCommandLine
extension method is one of them. To use that, modify your Program.cs file's Main
method to look something like this:
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.AddCommandLine(args)
.Build();
var host = new WebHostBuilder()
.UseKestrel()
.UseConfiguration(config)
.UseStartup<Startup>()
.Build();
host.Run();
}
Then, run the application with dotnet run --server.urls http://*:<yourport>
, replacing <yourport>
with the actual port number that you want it to run on. The *
makes it listen on all available IP addresses, if you want to listen on a specific address then you need to specify it there instead of the *
.
Another option for changing the port is to use the .UseUrls
method to hard-code the port and address. For example:
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseUrls("http://*:8080")
.UseStartup<Startup>()
.Build();
host.Run();
}
This example will make your application listen on port 8080
on all available IP addresses.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With