Optional appsettings.local.json in (new format) visual studio project
Asked Answered
S

7

29

My app uses appsettings.json for some settings. If appsettings.local.json is present, that should override appsettings.json for whatever settings it contains. So far, no problem.

But I use git for version control. Obviously, I don't want other users pulling down my local settings. So I git ignore appsettings.json.

Furthermore, there are a lot of projects in the solution. They share the same settings. So there is an appsettings.json at the solution level, and all the projects include it as a link.

Still fine, except for one thing. In order to be usable, I have to copy appsettings.local.json over to the output directory. But it shouldn't be in version control. So if someone clones the solution fresh they won't have it. That ought to be fine, but it isn't. VS. says "this file should be linked, but where the heck is it?" build error.

How can I deal with that?

Sirup answered 29/5, 2017 at 19:23 Comment(2)
Why don't you git ignore appsettings.local.json only?Affianced
The file needs to exist for everyone. I just don't want changes to be pushed.Sirup
P
36

With v2 this is dead simple.

  1. Add an appsettings.local.json to your project (it should nest itself below the main appsettings.json file).
  2. Add appsettings.local.json to your .gitignore
  3. In your startup.cs within the constructor do the following:

    public class Startup
    {
        public IConfigurationRoot Configuration { get; }
    
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) //load base settings
                .AddJsonFile("appsettings.local.json", optional: true, reloadOnChange: true) //load local settings
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) //load environment settings
                .AddEnvironmentVariables();
    
            Configuration = builder.Build();
        }
    
        /*
         * rest of your startup.cs
         */
    }
    
Portraiture answered 4/4, 2018 at 18:58 Comment(1)
Thank you, that worked for me! I don't have the startup.cs, but the Program.cs and I can confirm that the same approach works fine just by using the builder.Configuration.Eugeniaeugenics
R
10

For .Net Core >2.1 you can simply chain the extension method ConfigureAppConfiguration(Action<WebHostBuilderContext, IConfigurationBuilder> configureDelegate) to your WebHost. Here is an example:

WebHost.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        config.AddJsonFile(
            "appsettings.Local.json",
             optional: true,
             reloadOnChange: true);
    })
    // ...

And of course ignore the appsettings.Local.json in your .gitignore.

Roadbed answered 18/9, 2019 at 14:57 Comment(0)
V
8

For .NET 6, you can use this.

Also make sure, you git ignore appsettings.local.json to avoid check-in sensitive information like password and secrets.

var builder = WebApplication.CreateBuilder(args);

// Add configurations
builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.Sources.Clear();

    var env = hostingContext.HostingEnvironment;

    config.SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) //load base settings
            .AddJsonFile("appsettings.local.json", optional: true, reloadOnChange: true) //load local settings
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) //load environment settings
            .AddEnvironmentVariables();

    if (args != null)
    {
        config.AddCommandLine(args);
    }
});
Voiture answered 10/2, 2022 at 12:14 Comment(1)
I found when doing this it causes the launchsettings.json file to be ignored. (I can see this by the fact that I have specific applicationUrl specified there, but when the app launches it is listing on port 5000.Fatherland
O
7

Can't say I like adding this a environment specific thing into the source code, It seems cleaner to add it as a file like appsetting.local.json, then inside your launchSettings.json make sure to add environment variable as local.


{
  "profiles": {
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "local"
      }
    }
  }
}

public class Startup
{
    public IConfigurationRoot Configuration { get; }

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) //load base settings
            // Avoid this nasty code in your codebase, its oddly specific for a particular environment.
            //.AddJsonFile("appsettings.local.json", optional: true, reloadOnChange: true) //load local settings
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) //load environment settings
            .AddEnvironmentVariables();

        Configuration = builder.Build();
    }

    /*
     * rest of your startup.cs
     */
}
Outward answered 6/4, 2022 at 19:33 Comment(0)
A
4

The plan:

  1. Place default local values to appsettings.local-base.json.
  2. Add appsettings.local.json to .gitignore.
  3. Copy appsettings.local-base.json as appsettings.local.json to output folder if appsettings.local.json doesn't exist.
  4. Do nothing if user has his own appsettings.local.json in project folder (it will be copied to output folder by VS).

MSBuild Copy target can conditionally copy a file before/after build. The target below is actual for a Visual Studio 2017 and csproj-based .NET Core project (file names are reduced):

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    </PropertyGroup>

    <!--rest of file -->  

    <Target Name="TestTarget" AfterTargets="Build">
        <ItemGroup>
            <FromFile Include="src.json" />
            <ToFile Include="$(OutDir)dest.json" />
        </ItemGroup>

        <Message Text="Copying @(FromFile) file to: @(ToFile)" Importance="high" />

        <Copy   
            SourceFiles="@(FromFile)" 
            DestinationFiles="@(ToFile)" 
            Condition="!Exists('@(ToFile)')" 
            OverwriteReadOnlyFiles="true" 
            SkipUnchangedFiles="false" />
    </Target>  
</Project>

After the project build the following message should appear in VS build output:

Copying src.json file to: bin\Debug\netcoreapp1.1\dest.json

Affianced answered 30/5, 2017 at 17:48 Comment(0)
A
3

Seems like this stuff is changing so fast, it's hard to keep track of "the right way" Microsoft wants these things handled.

In ASP.NET Core 2, I believe the expected way for developers to handle per-developer configuration values is with the Secret Manager.

Short summary: In Visual Studio 2019, right-click the project and choose Manage User Secrets. This creates a JSON file in %APPDATA%\Microsoft\UserSecrets\... that is picked up automatically by WebHost.CreateDefaultBuilders() (which is called implicitly in default ASP.NET core projects).

Aleshia answered 24/7, 2019 at 17:27 Comment(1)
This actually the best answer. It's underrated.Dixiedixieland
R
1

Here is Pim's answer but for a .Net6+ programs that don't have a startup.cs file.

var builder = WebApplication.CreateBuilder(args);    

builder.Configuration
        .SetBasePath(builder.Environment.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile("appsettings.local.json", optional: true, reloadOnChange: true) 
        .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true) 
        .AddEnvironmentVariables();
Redstone answered 5/4 at 19:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.