Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Difference in behavior between UseConfiguration and ConfigureAppConfiguration #1148

Closed
cesarblum opened this issue Jul 28, 2017 · 10 comments
Closed

Comments

@cesarblum
Copy link
Contributor

Ran into this while investigating aspnet/AzureIntegration#81.

Code:

public static void Main(string[] args)
{
    var host = new WebHostBuilder()
        .ConfigureAppConfiguration((context, config) =>
        {
            config.AddCommandLine(args);
        })
        .ConfigureLogging(factory =>
        {
            factory.SetMinimumLevel(LogLevel.Trace);
            factory.AddConsole();
        })
        .UseKestrel()
        .UseStartup<Startup>()
        .Build();

    host.Run();
}

Output:

> dotnet .\bin\Debug\netcoreapp2.0\App.dll --server.urls http://localhost:12345
...
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Note that it bound to the default address.

If I change the code to:

public static void Main(string[] args)
{
    var config = new ConfigurationBuilder()
        .AddJsonFile("appsettings.json")
        .AddCommandLine(args)
        .Build();

    var host = new WebHostBuilder()
        .UseConfiguration(config)
        .ConfigureLogging(factory =>
        {
            factory.SetMinimumLevel(LogLevel.Information);
            factory.AddConsole();
        })
        .UseKestrel()
        .UseStartup<Startup>()
        .Build();

    host.Run();
}

It behaves as expected (binds to http://localhost:12345):

> dotnet .\bin\Debug\netcoreapp2.0\App.dll --server.urls http://localhost:12345
...
Now listening on: http://localhost:12345
Application started. Press Ctrl+C to shut down.

Is this by design?

@JunTaoLuo
Copy link
Contributor

JunTaoLuo commented Jul 28, 2017

I think the ConfigureAppConfiguration was intended to configure the IConfiguration in the application services whereas UseConfiguration is intended to configure the settings of the WebHostBuilder. Since the url address is a setting on the WebHostBuilder only UseConfiguration will work here. Note that the WebHostBuilder's configuration is added to the application's configuration but the converse is not true; configuring the application's configuration does not affect the WebHostBuilder's configuration. cc @Tratcher to make sure I'm not speaking non-sense.

@Tratcher
Copy link
Member

That about covers it. The distinction is somewhat arbitrary at this point.

@JunTaoLuo
Copy link
Contributor

So I guess we are happy with this behaviour and can close the issue? Or is there any possible improvement in the user experience here.

@muratg
Copy link

muratg commented Aug 8, 2017

This is by-design.

@filipgoris
Copy link

I think this is very confusing.
Consider the following simple apsettings.json:

{
  "server.urls": "http://localhost:12345",
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Trace"
    }
  }
}

With

var config = new ConfigurationBuilder().AddJsonFile("appsettings.json")

and

var host = new WebHostBuilder().UseConfiguration(config)

server.urls is applied, but

var host = new WebHostBuilder().ConfigureLogging((context, logging) =>
{
   logging.AddConfiguration(context.Configuration.GetSection("Logging"))
}

won't apply Log settings.

With

var host = new WebHostBuilder()
   .configureAppConfiguration((context, config) =>
   (
      config.AddJsonFile("appsettings.json", true, true)
   })
   .configureLogging((context, logging) =>
   {
      logging.AddConfiguration(context.Configuration.GetSection("Logging"));
   ))

I can inject log settings, but not server.urls. Meaning I have to load this appsettings.json using both methods.

Or am I seeing this wrong?

@cesarblum
Copy link
Contributor Author

If you can read the Logging section from you config, there's no reason why you shouldn't be able to read server.urls as well (after having loaded your JSON file in ConfigureAppConfiguration).

@0xorial
Copy link

0xorial commented Dec 6, 2017

-2 to that design...

@RehanSaeed
Copy link

It's still unclear to me when to use UseConfiguration and ConfigureAppConfiguration in relation to configuring Kestrel from appsettings.json:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    new WebHostBuilder()
        .UseKestrel(
            (builderContext, options) =>
            {
                options.Configure(builderContext.Configuration.GetSection(nameof(ApplicationOptions.Kestrel)));
            })
            ...

Reading the comments, you'd think that you need to use UseConfiguration but CreateDefaultBuilder only calls UseConfiguration with the command line arguments:

builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build());

That must mean it's using ConfigureAppConfiguration.

@Tratcher
Copy link
Member

That UseKestrel lamda is delay executed after both UseConfiguration and ConfigureAppConfiguration, so it's able to consume config from either source. Note it only reads the new "Kestrel" config section. "server.Urls" is awkward because kestrel doesn't read it directly, the host reads it after UseConfiguration and before ConfigureAppConfiguration and then passes it through a side channel (IServerAddressesFeature) to servers.

Since the new "Kestrel" config section works with appsettings.json and is so much more powerful we opted not to rework "server.Urls" to work with appsettings.json, it's redundant.

@bugproof
Copy link

It's not clear and should be documented when to use one over another.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants