12
votes

I have an Asp.net core application with the following code.

Program.cs

public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseUrls("http://*:5000")
            ......

I don't want to hard code the port number 5000. How to read it from the configure file?

The startup.cs uses the config file for some settings. Should the code be duplicated in the program.cs? But how to get IHostingEnvironment env?

Startup.cs

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

    builder.AddEnvironmentVariables();
    Configuration = builder.Build();
}
4

4 Answers

11
votes

It is possible to create instance of IConfiguration in main method and use it for host configuration. Moreover you can directly use:

public static void Main(string[] args)
{
    var config = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    //.AddJsonFile("hosting.json", optional: true)
                    //.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    //.AddCommandLine(args)
                    //.AddEnvironmentVariables()
                    .Build();

    var host = new WebHostBuilder()
            .UseUrls(<values from config>);
}

Moreover, you can directly use .UseConfiguration(config) extension method:

var host = new WebHostBuilder()
                .UseConfiguration(config)
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .Build();

in this case, you configuration file should have 'server.urls' parameter. For your case:

"server.urls": "http://*:5000"

Also note, that when you run app directly, you can pass port from command line:

dotnet run --server.urls=http://0.0.0.0:5001
3
votes

Reading config value as mentioned by @Set above but using it in CreateHostBuilder() works for WebHost.

private static string GetHostPort()
{
    var config = new ConfigurationBuilder()
        .AddJsonFile(SelfHostSettings, optional: false, reloadOnChange: false)
        .Build();

    return config["HostPort"] ?? "8080";
}

private static IHostBuilder CreateHostBuilder(string[] args)
{
    var hostPort = GetHostPort();

    return Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration(GetConfig)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseUrls($"http://localhost:{hostPort}");
            webBuilder.UseStartup<Startup>();
        })
        .UseWindowsService();
}

Note that trying to read config from Main() defaults the directory to %windir%\system32 but calling the same from CreateHostBuilder() is set to application directory.

0
votes

Overriding Urls (listen on port 5020):

$ dotnet run --urls=http://*:5020

http/https:

$ dotnet run --urls="http://*:5020;https://*:5021"
0
votes

You can set urls via Kestrel options like this:

Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(hostBuilder =>
    {
        hostBuilder.UseKestrel((builderContext, kestrelOptions) =>
        {
            kestrelOptions.ListenAnyIP(builderContext.Configuration.GetValue<int>("Port"));
        });
    }
);

As you can see, you can access the configuration via builder context and get any information from there. Including port.