aspnet / Hosting

[Archived] Code for hosting and starting up an ASP.NET Core application. Project moved to https://github.com/aspnet/Extensions and https://github.com/aspnet/AspNetCore
Apache License 2.0
552 stars 312 forks source link

Wrong configuration injected into Startup #1528

Closed BalassaMarton closed 5 years ago

BalassaMarton commented 6 years ago

Try this setup:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IConfiguration BuildConfiguration()
        {
            return new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .AddJsonFile("othersettings.json")
                .Build();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args)
        {
            return WebHost.CreateDefaultBuilder(args)
                .UseConfiguration(BuildConfiguration())
                .UseStartup<Startup>();
        }
    }

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // ...  
    }

The configuration object injected into Startup will not have any values or providers from the one passed to UseConfiguration, e.g. nothing from othersettings.json. The configuration is otherwise correctly injected into controllers and pages.

BalassaMarton commented 6 years ago

Workaround is to use ConfigureAppConfiguration instead of UseConfiguration.

khellang commented 6 years ago

It's not really a "workaround". Everything works as designed, as confusing as it is. The ConfigureAppConfiguration exist for a reason 😉 See https://github.com/aspnet/Hosting/issues/1148#issuecomment-318524939

BalassaMarton commented 6 years ago

From documentation:

Host configuration key-value pairs become part of the app's global configuration.

And from another documentation page:

IWebHostBuilder configuration is added to the app's configuration, but the converse isn't true—ConfigureAppConfiguration doesn't affect the IWebHostBuilder configuration.

While it is true that the application isn't really running yet when Startup methods are called, this is very couter-intuitive.

But the disturbing thing is that I can't even repro it on my home machine, like it was some SDK-specific thing. Here Startup receives host+app configuration as expected. I need to check this again on my work machine.

BalassaMarton commented 6 years ago

After a few hours of trial and error, I can finally repro the problem. It's not that the wrong instance is injected. When using WebHost.CreateDefaultBuilder, appsettings.json is loaded after anything that was passed to UseConfiguration, overwriting existing values. The problem goes away when either calling ConfigureAppConfiguration or building the host manually with a new WebHostBuilder. I'm not sure if this qualifies as a bug, it's more like a documentation problem. The previously quoted sections fail to mention that the default builder itself calls ConfigureAppConfiguration, which ultimately overwrites anything passed in UseConfiguration. To try it out, clone this repo and fiddle with the switches in Program.cs https://github.com/BalassaMarton/AspnetHosting1528Repro

lonix1 commented 6 years ago

This is certainly a mess!

In my case I need to start logging before the webhost, to ensure if something goes wrong during startup, it gets logged! So I setup 1) configuration, 2) logging (serilog) and 3) webhost.

So obviously I pass the config into UseConfiguration() and it doesn't work properly. But if I use ConfigureAppConfiguration() it does work, but trashes the existing config, so my webhost and logging are using different config!

@BalassaMarton What approach are you now using?

khellang commented 6 years ago

@lonix1 Sounds like https://github.com/aspnet/Hosting/issues/1150

lonix1 commented 6 years ago

I posted a separate issue for that.

@BalassaMarton I tried your code and get the same results.

aspnet-hello commented 5 years ago

We periodically close 'discussion' issues that have not been updated in a long period of time.

We apologize if this causes any inconvenience. We ask that if you are still encountering an issue, please log a new issue with updated information and we will investigate.