bitshift
bitshift

Reputation: 6842

Wrong appsettings values getting into ConfigurationBuilder object at debug time

Im running a .net core console app, hosting the aspnet core runtime. There are 3 different environements I'm using - Debug, Dev and Prod and their associated appsettings json files. So I'm using a Startup class, but even before the Startup code is used, the WebhostBuilder is setup. From the docs:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.0

If a value for the same key is set by the same or different configuration providers, the last value set on the key is the value used.

Ok great, maybe I don't really understand how the correct settings get into the config object, but see below how I'm adding the root appsettings json file then the environment-specific one, and this seems to work.
So at most, I should have TWO appsettings being referenced and the value However, later when the config object gets injected into one of the services in my Startup class, the value i'm trying to pull from the config object isn't there. Since my environment variable is Debug, it should be reading from the value in the appsettings.debug.json file

in appsettings.json

-not there-

in appsettings.debug.json

"AppSettings": {
  "CustomerFilesRoot": "\\\\dev-haulops1\\d$\\BoxFiles",

Also, when Im stepping into one of my services and looking at the config object that has been injected, I see 4 Json configuration providers? Why 4 instead of 2 ? Drilling down into these, there are 2 each from appsettings.debug.json and appsettings.json Hmmm strange. I'm obviously missing something.

enter image description here

In my Program.cs

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)                
                .ConfigureLogging((hostingContext, logging) =>
                {
                    logging.AddEventLog();
                })
                .ConfigureAppConfiguration((context, config) =>
                {

                    // Configure the app here.
                    var env = context.HostingEnvironment;
                    config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                                      .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

                })
                .UseStartup<Startup>();

The beginnings of Startup.cs

public IConfiguration Configuration { get; }
public IHostingEnvironment HostingEnvironment { get; }

public Startup(IConfiguration configuration, IHostingEnvironment environment)
{
    Configuration = configuration;
    HostingEnvironment = environment;
}

[ update ]
Not sure if anyone noticed, Im using WebHost rather than Generic Host, so just like with a web app, there is no explicit need to "add" the appsettings files. Eg, in a web app I have. So, Im still scratching my head why within a console app that happens to be using the aspcore runtime and using WebHost that its not trying to use the file (at least for me) associated with the environment var that is set in the launchsettings.json file. When I take out the explicit loading of the two appsettings files, I get them loaded as configurationproviders at debugtime and I can see two (as opposed to 4 mentioned earlier). The problem is that when I go to extract a value from the config object, its giving me a value from the file that does not match the environment var.

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

Upvotes: 1

Views: 3368

Answers (3)

bitshift
bitshift

Reputation: 6842

Praise the Lord, I found it. Turns out there was a problem with the appsettings.Debug.json file after all. I was starring right at it. The Configuration was picking it up all along, but the structure of the settings were different. Then I recalled I had copied these files from another project.

See the difference? What I was actually reading from:

  "JobSettings" {
      "SomethingHere" : "test",
      "AppSettings": {
        "setting1" : "val1"
      }
  }

What I THOUGHT I was reading from:

  "JobSettings" {
      "SomethingHere" : "test",
  } ,
  "AppSettings": {
    "setting1" : "val1"
  }   

In case anyone is looking at this same issue down the road, check these things:
(1) Do you have your environment variable set and is it getting picked up? set a breakpoint in your Startup constructor and check environemnt.EnvironmentName
(2) Take a real close look at your appsettings files. Do you actually have a file with the matching environment name in the format of appsettings.{environment}.json? Are you trying to read a value that is at the same location that your code is trying to reference?

Upvotes: 3

crgolden
crgolden

Reputation: 4634

You didn't show this part, so I'm not sure if you're doing it. But make sure you're setting the ASPNETCORE_ENVIRONMENT environment variable.

Since you are using environment names that are different that the three conventional names (Development, Staging, and Production), you'll need to set the environment name explicitly. There are a number of ways to do this. Like in your launchSettings.json file, for example:

"EnvironmentsSample": {
   "commandName": "Project",
   "launchBrowser": true,
   "applicationUrl": "https://localhost:5001;http://localhost:5000",
   "environmentVariables": {
     "ASPNETCORE_ENVIRONMENT": "Debug"
   }
}

Reference: Set the environment.

But ultimately, somewhere you'll need to determine which machine you're currently running on and set the ASPNETCORE_ENVIRONMENT environment variable based on that information (ASPNETCORE_ENVIRONMENT=Debug, for instance).

I think until you do that, IHostingEnvironment.EnvironmentName will behave differently than you're expecting.

Upvotes: 1

ak42
ak42

Reputation: 11

Well, at first glance you are missing config And do not forget to call config.AddEnvironmentVariables(); this will add the env variables.

.ConfigureAppConfiguration((context, config) =>
            {

                // Configure the app here.
                var env = context.HostingEnvironment;
                config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                config.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
                config.AddEnvironmentVariables();
            })

And for your reference, the configs from appsetting.json is referenced in the reverse order of the files loaded using AddJsonFile. In other words in your case appsettings.{env.Environment.json} will be searched for CustomerFilesRoot if it is found then value will be returned immediately, if not then appsettings.json will be searched for that value.

Upvotes: 1

Related Questions