1

In prior versions of ASP.NET Core we could dynamically add appsetting.json files with the environment suffix like appsettings.Production.json for production environment.

Since the structure is a bit different, it seems that the configuration now got loaded in class Program. But we dont have the `` injected here,so I tried it myself using environment variable:

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

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) {
            string envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            string envConfigFile = $"appsettings.{envName}.json";

            var config = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile(envConfigFile, optional: true);

            var finalConfig = config.Build();
            return WebHost.CreateDefaultBuilder(args)
                .UseUrls("http://0.0.0.0:5000")
                .UseConfiguration(finalConfig)
                .UseStartup<Startup>();
        }
    }

The code got executed but it doesn't override my appsettings.json config. Let's say I have the following appsettings.json:

{
    "MyConnectionString": "Server=xxx,Database=xxx, ..."
}

This ConnectionString is working. Now I createappsettings.Development.json

{
    "MyConnectionString": ""
}

and set ASPNETCORE_ENVIRONMENT=Development. This should definitely throw an exception. But the app start correctly with the ConnectionString from appsettings.json.

According to ASP.NET Core 2 configuration changes, the WebHost.CreateDefaultBuilder method should itself use the new ConfigureAppConfiguration approach and load environment specific config by default. Also the official docs say that appsettings.{Environment}.json are loaded automatically. But this doesn't work and also loading it manually like this doesn't solve the problem:

return WebHost.CreateDefaultBuilder(args)
                .UseUrls("http://0.0.0.0:5000")
                .ConfigureAppConfiguration((builderContext, config) => {
                    IHostingEnvironment env = builderContext.HostingEnvironment;
                    config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
                })
                .UseStartup<Startup>();

How can I override the config using "appsettings.{envName}.json" pattern? I liked that cause it was handy to override env specific things in ASP.NET Core.

Lion
  • 16,606
  • 23
  • 86
  • 148
  • `CreateDefaultBuilder` *already* includes `appsettings.json` and `appsettings.{environment}.json`. You don't need to add anything additional. – Chris Pratt Oct 08 '18 at 14:04

6 Answers6

5

Found out that I had a custom DesignTimeDbContextFactory class for migrations:

public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext> {
        public ApplicationDbContext CreateDbContext(string[] args) {
            var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
            string connectionString = Config.GetConnectionString("AppDbContext");
            builder.UseMySql(connectionString);

            return new ApplicationDbContext(builder.Options);
        }
    }

Since the injection of the configratuion doesn't seem to work here (at the time I got errors for my connection strings when using default Startup class), I wrote some custom configuration class:

public class Config {
        static IConfigurationRoot config;
        static IConfigurationRoot AppConfig {
            get {
                if (config == null) {
                    config = new ConfigurationBuilder()
                             .SetBasePath(Directory.GetCurrentDirectory())
                             .AddJsonFile("appsettings.json")
                             .Build();
                }
                return config;
            }
        }
        public static string GetConnectionString(string name) {
            var connectionString = AppConfig.GetConnectionString(name);
            return connectionString;
        }
    }

So the problem was, that ASP.NET Core's default ConfigureAppConfiguration wasn't used for consistence. Instead my solution only loads appsettings.json since at the time of writing this class, no environment specific config was used.

I simply need to add loading here like this:

    static IConfigurationRoot AppConfig {
        get {
            if (config == null) {
                var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
                config = new ConfigurationBuilder()
                         .SetBasePath(Directory.GetCurrentDirectory())
                         .AddJsonFile("appsettings.json")
                         // https://github.com/aspnet/MetaPackages/blob/rel/2.0.0/src/Microsoft.AspNetCore/WebHost.cs
                         .AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true)
                         .Build();
            }
            return config;
        }
    }

I'd appreciate it if someone has a cleaner solution here that let me use the default ConfigureAppConfiguration approach in EF migrations, cause it seems less error prone when using such default stuff instead of customized methods.

Lion
  • 16,606
  • 23
  • 86
  • 148
4

According to docs, the JSON Configuration Provider should automatically load twice in ASP.NET Core 2.1 (and ASP.NET Core 2.1) when using CreateDefaultBuilder (so move your code from the separate ConfigurationBuilder).

AddJsonFile is automatically called twice when you initialize a new WebHostBuilder with CreateDefaultBuilder. The method is called to load configuration from:

  • appsettings.json – This file is read first. The environment version of the file can override the values provided by the appsettings.json file.
  • appsettings.{Environment}.json – The environment version of the file is loaded based on the IHostingEnvironment.EnvironmentName.

Their example:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.SetBasePath(Directory.GetCurrentDirectory());
            config.AddJsonFile(
                "config.json", optional: true, reloadOnChange: true);
        })

(If you want to use connection strings from your startup (UI MVC) project, for adding migrations in a different migrations project you may want to check this answer.)

Yahoo Serious
  • 3,728
  • 1
  • 33
  • 37
2

Environment variable Settings Image

Based on Enviroment Variables settings we can use appsettings.environment.json file as config file

 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)
                    .AddEnvironmentVariables();
                Configuration = builder.Build();
            }
0

You should check your build settings. If you want your project to load an specific environment then you should specify to the compiler wish environment settings you want to be loaded.

I hope it helps. Good luck.

  • I already changed `ASPNETCORE_ENVIRONMENT` to production. On startup the app confirms that: `Hosting environment: Production`. – Lion Oct 07 '18 at 11:24
0

You need to go to your solution in visual studio 2017c click on the solution, in menu click properties > build and you’ll see That environment variable has already been created for the environment named Development. If you override that value within the properties page for your given web project , it will pull the environment variables from the app environment specific app settings . I would also just keep your web host builder default code if your version is 2.1 or above

Judy007
  • 5,484
  • 4
  • 46
  • 68
  • I already changed `ASPNETCORE_ENVIRONMENT` to production. On startup the app confirms that: `Hosting environment: Production`. But also when using the default web host builder (I'm using 2.1), the environment specific config is not loaded. – Lion Oct 07 '18 at 11:24
  • Make sure you dont have a machine wide environment variable set, that will take higher precidence if it does exists. There is no reason why the config would not work as expected unless you take matters into your own hands and change Program.cs CreateWebHostBuilder. – Judy007 Oct 07 '18 at 21:03
0

Try using CreateDefaultBuilder() which should provide you with the configuration settings you want (as in the example in the docs). Note that if you are running on Linux it is case sensitive - if the file name has a capital P for Production, the value of the environment variable must as well. Also, check you have the files in the correct directory - print the value of Directory.CurrentDirectory() at runtime. This is where they should be.

If this works but you don't actually want a default builder, just copy the parts you need from the source.

rbennett485
  • 1,907
  • 15
  • 24