在具有相同环境的不同机器上使用不同的appsettings.json

问题描述 投票:0回答:2

我有一个 .NET 6 控制台应用程序,它在多个服务器上运行以监视它们上的应用程序。

多个服务器已经为使用这些值的其他应用程序设置了环境变量。

例如:

Server A -> DOTNET_ENVIRONMENT = dev
Server B -> DOTNET_ENVIRONMENT = qa
Server C -> DOTNET_ENVIRONMENT = prod
Server D -> DOTNET_ENVIRONMENT = prod

尽管服务器 C 和 D 都是 prod 服务器,但它们需要不同的

appsettings
,因为它们监控这些服务器中的不同应用程序。因此,在服务器 C 和 D 中使用一个
appsettings.prod.json
在这种情况下不起作用。

我也不想弄乱

DOTNET_ENVIRONMENT
的值,因为该服务器上运行的其他应用程序正在使用它。

到目前为止我做了什么

我根据服务器名称命名了控制台应用程序的

appsettings.json
文件。

例如:

添加了

launchsettings
配置文件以将计算机名称作为环境变量传递(用于我的测试):

{
  "profiles": {
    "AppStatusWatchDog (ServerA)": {
      "commandName": "Project",
      "environmentVariables": {
        "MachineName": "ServerA"
      },
      "dotnetRunMessages": "true"
    }
  }
}

并尝试在启动过程中加载正确的

appsettings.json

public static void Main(string[] args)
{
    var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
    var pathToContentRoot = Path.GetDirectoryName(pathToExe);

    // Just calling Environment.MachineName is adequate here. GetEnvironmentVariable("MachineName") is here because we supply MachineName's value during local testing using launch profile.
    var machineName = Environment.GetEnvironmentVariable("MachineName") ?? Environment.MachineName;
    
    var config = new ConfigurationBuilder()
        .SetBasePath(pathToContentRoot)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{machineName}.json", optional: true, reloadOnChange: true)
        .AddEnvironmentVariables()
        .Build();

    // Rest of the code here...
}

这里

config
加载了我拥有的所有设置,即
appsettings.json
appsettings.ServerA.json
和环境变量,这很好🙌。

当我尝试通过将

IConfiguration
注入某个类的构造函数来使用配置时,问题就出现了😧,此时它会加载
appsettings.json
和环境变量,但不会加载
appsettings.ServerA.json

我在这里做错了什么?

c# .net-core .net-6.0 appsettings
2个回答
0
投票

您应该按如下方式修改启动设置:

{
  "profiles": {
    "AppStatusWatchDog (ServerA)": {
      "commandName": "Project",
      "commandLineArgs": "--MachineName=ServerA",
      "dotnetRunMessages": "true"
    }
  }
}

接下来,您需要修改 Main 方法以正确解析命令行参数:

public static void Main(string[] args)
{
    var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
    var pathToContentRoot = Path.GetDirectoryName(pathToExe);

    // Parse command line arguments to find the machine name
    var machineName = "default"; // Default value if no argument is provided
    for (int i = 0; i < args.Length; i++)
    {
        if (args[i] == "--MachineName" && i + 1 < args.Length)
        {
            machineName = args[i + 1];
            break;
        }
    }

    var config = new ConfigurationBuilder()
        .SetBasePath(pathToContentRoot)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{machineName}.json", optional: true, reloadOnChange: true)
        .AddEnvironmentVariables()
        .Build();

    // Rest of the code here...
}

请告诉我这是否可以解决您的问题。


0
投票

appsettings.X.json
配置文件根据控制台应用程序中
IConfiguration
变量的值加载到
DOTNET_ENVIRONMENT
中。 (
ASPNETCORE_ENVIRONMENT
适用于网络应用程序。更多信息此处)。

试试这个:

public static void Main(string[] args)
{
    var machineName = Environment.GetEnvironmentVariable("MachineName") ?? Environment.MachineName;
    
    // IMPORTANT part: 👇
    Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", machineName); 
    // For machine level change (Don't do this here):
    // Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", machineName, EnvironmentVariableTarget.Machine); // Reference: https://stackoverflow.com/a/19705691/8644294

    // If you're going to use config through dependency injection, you don't even
    // need to build 'config' below and this line can be removed altogether.
    // (Example of using config using dependency injection is shown below).
    // But for whatever reason you need 'config' in your 'Rest of the code here...'
    // part, keep this as is:
    var config = new ConfigurationBuilder()
        //.SetBasePath(Directory.GetCurrentDirectory()) // Not really needed though. Uncomment it if you'd like.
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{machineName}.json", optional: false, reloadOnChange: true)
        .AddEnvironmentVariables()
        .Build();

    // Rest of the code here...
}

像这样使用它:

public class SomeClass
{
    private readonly IConfiguration _config;
    
    public SomeClass(IConfiguration config)
    {
        _config = config; // 👈 This will have settings from appsettings.json, appsettings.ServerA.json, environment variables of the machine it's running on and so on.
    }
}

注意:

appsettings.json
的属性应如下所示:

© www.soinside.com 2019 - 2024. All rights reserved.