11

I have the following in my appSetting.json;

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "MailServiceSettings": {
    "SmtpServer": "<server>",
    "ToAddresses": [
      "[email protected]",
      "[email protected]"
    ],
    "UserName": "username",
    "Password": "password"
  }
}

and in appSettings.Development.json i have a subtle change;

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "MailServiceSettings": {
    "SmtpServer": "<server>",
    "ToAddresses": [
      "[email protected]"
    ],
    "UserName": "username",
    "Password": "password"
  }
}

This is so I can text the mail sender settings in my localhost without bombarding the live mailbox.

However, when I run in debug the settings from appSettings.json are being injected insted of the appSettings.Development.json.

My Program.cs is using the default WebHostBuilder;

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

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

and setup the DI as following in my StartUp.cs;

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        services.Configure<MailServiceSettings>(Configuration.GetSection("MailServiceSettings"));

        // In production, the Angular files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });
    }

Then when I debug and break on the configuration I can see that the appSettings.Development.json have been read (as I can drill down into the Configuration sections when debugging I can see they are added as an additional entry, and I believe WebHost.CreateDefaultbuilder adds the env.EnvironmentName files by default).

However, when I then instantiate an controller method;

public ContactController(IOptions<MailServiceSettings> mailSettings, IHostingEnvironment hostingEnvironment)
{
    _mailSettings = mailSettings;
    _hostingEnvironment = hostingEnvironment;
}

I am finding that the 2x email address from the appSettings.json are injected instead of the appSettings.Development.json

I have also checked env.IsDevelopment() at runtime and this is returning true.

Can anyone tell me what I am doing wrong here?

3
  • Check both files' properties. Is option Copy to Output Directory set to Copy Always in Advanced section? Commented Feb 22, 2019 at 15:53
  • From further tests it seems that appSettings.json is overriding the development version, for example if I remove the 2x email address completely from appSettings.json the 1x email address is injected from the appSettings.Developement.json is this correct? Commented Feb 22, 2019 at 15:54
  • It's wierd. Did you set ASPNETCORE_ENVIRONMENT value in Properties/defaultSettings.json? Or in your host environment variables? Commented Feb 22, 2019 at 16:01

1 Answer 1

10

I'm having trouble tracking down and official source for this, but essentially the issue is that IConfiguration is basically a dictionary and the keys and values from configuration sources are flattened into that. In other words, at the end of the day, what you're actually getting is something like the following in pseudo-code:

["MailServiceSettings:ToAddresses[0]"] = "[email protected]"
["MailServiceSettings:ToAddresses[1]"] = "[email protected]"

Then, when your appsettings.Development.json config comes in:

["MailServiceSettings:ToAddresses[0]"] = "[email protected]"

In other words, you still have two items in the config. The only way around this is to have settings like this only in your environment-specific config. If you remove this from appsettings.json entirely and then do:

appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "MailServiceSettings": {
    "SmtpServer": "<server>",
    "UserName": "username",
    "Password": "password"
  }
}

appsettings.Development.json

{
  "MailServiceSettings": {
    "ToAddresses": [
      "[email protected]"
    ]
  }
}

appsettings.Production.json

{
  "MailServiceSettings": {
    "ToAddresses": [
      "[email protected]",
      "[email protected]"
    ]
  }
}

Then, you'll correctly only have the one address in development and the two in production.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.