(新格式)visual studio 项目中的可选 appsettings.local.json

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

我的应用使用 appsettings.json 进行某些设置。如果 appsettings.local.json 存在,它应该覆盖 appsettings.json 它包含的任何设置。到目前为止,没问题。

但我使用 git 进行版本控制。显然,我不希望其他用户拉低我的本地设置。所以我 git 忽略 appsettings.json.

此外,解决方案中有很多项目。他们共享相同的设置。所以在解决方案级别有一个 appsettings.json,所有项目都将其作为 link.

还好,除了一件事。为了可用,我必须将 appsettings.local.json 复制到输出目录。但它不应该在版本控制中。因此,如果有人克隆了新鲜的解决方案,他们将不会拥有它。那应该没问题,但事实并非如此。对比。说 "this file should be linked, but where the heck is it?" 构建错误。

我该如何处理?

计划:

  1. 将默认本地值设为 appsettings.local-base.json
  2. appsettings.local.json 添加到 .gitignore
  3. appsettings.local-base.json复制为appsettings.local.json到输出文件夹if appsettings.local.json 不存在
  4. 如果用户在项目文件夹中有自己的 appsettings.local.json,则不执行任何操作(它将被 VS 复制到输出文件夹)。

MSBuild Copy 目标可以有条件地复制一个文件 before/after 构建。下面的目标是 Visual Studio 2017 和基于 csproj 的 .NET Core 项目的实际目标(文件名已减少):

<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>

项目构建后,VS 构建输出中应出现以下消息:

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

对于 v2,这非常简单。

  1. 向您的项目添加一个 appsettings.local.json(它应该嵌套在主 appsettings.json 文件下方)。
  2. appsettings.local.json 添加到您的 .gitignore
  3. 在构造函数中的 startup.cs 中执行以下操作:

    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
         */
    }
    

似乎这些东西变化太快了,很难跟踪"the right way"微软希望处理这些东西。

在 ASP.NET Core 2 中,我相信开发人员处理每个开发人员配置值的预期方式是使用 Secret Manager.

简短摘要:在 Visual Studio 2019 年,右键单击项目并选择 管理用户机密。这会在 %APPDATA%\Microsoft\UserSecrets\... 中创建一个 JSON 文件,该文件由 WebHost.CreateDefaultBuilders() 自动获取(在默认 ASP.NET 核心项目中隐式调用)。

对于 .Net Core >2.1,您可以简单地将扩展方法 ConfigureAppConfiguration(Action<WebHostBuilderContext, IConfigurationBuilder> configureDelegate) 链接到您的 WebHost。这是一个例子:

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

当然,请忽略 .gitignore 中的 appsettings.Local.json。

对于 .NET 6,您可以使用它。

另外请确保,您 git 忽略 appsettings.local.json 以避免 check-in 密码和秘密等敏感信息。

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);
    }
});

不能说我喜欢将这个特定于环境的东西添加到源代码中,将它添加为像 appsetting.local.json 这样的文件似乎更清晰,然后在你的 launchSettings.json 中确保添加环境变量为本地。


{
  "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
     */
}