在 .NET 8 上建立 Worker Service 預設有 appsettings.json 和 appsettings.Development.json 兩個 json 檔案
可以自行新增 json 檔案,在下述三篇文章內,都有提到新增 json 檔案時,可以透過調整 project 檔案,讓新增 json 檔案有巢狀階層,但實際上操作發現,只要是 appsettings 開頭,就會直接變成巢狀階層,VS 版本為 17.9.6
環境模式
在 Use multiple environments in ASP.NET Core 內提到有三種環境模式,分別為
- Development:launchSettings.json 內 DOTNET_ENVIRONMENT 預設值
- Staging
- Production:沒有設定 DOTNET_ENVIRONMENT 預設值
可根據不同環境模式載入不同的 appsettings.json 檔案設定,但部屬出去後不會有 launchSettings.json,也就沒有 DOTNET_ENVIRONMENT,預設即為 Production,只會載入 appsettings.json 而已,不會載入 appsettings.Development.json,另外除了系統環境變數 (該筆記是DOTNET_ENVIRONMENT) 外,也可以自訂環境變數 (該筆記是 SecretKey)。
測試 Worker Service 專案
延續 [.NET] 設定檔 - launchSettings.json 內容,已經建立 Staging Profile,後續會記錄 profile 切換 appsettings.json、自訂環境變數和部屬為 Windows Service,相關設定檔案如下
launchSettings.json
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"EnvironmentsSample": {
"commandName": "Project",
"dotnetRunMessages": true,
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development",
// 自訂環境變數 SecretKey
"SecretKey": "Secret key value From EnvironmentsSample"
}
},
"Staging": {
"commandName": "Project",
"dotnetRunMessages": true,
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Staging"
// 沒有設定 SecretKey
}
}
}
}
appsettings.json{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"SqlServer": "Server=RemoteIP;Database=AdventureWorks2022;Trusted_Connection=True;TrustServerCertificate=true"
}
}
appsettings.Development.json{
"ConnectionStrings": {
"SqlServer": "Server=.;Database=AdventureWorks2022;Trusted_Connection=True;TrustServerCertificate=true"
}
}
appsettings.Staging.json{
"ConnectionStrings": {
"SqlServer": "Server=StagingIP;Database=AdventureWorks2022;Trusted_Connection=True;TrustServerCertificate=true"
}
}
根據 profile 取得 DOTNET_ENVIRONMENT 環境變數
取得 DOTNET_ENVIRONMENT 環境變數的三種方式
namespace EnvironmentsSample
{
public class Program
{
public static void Main(string[] args)
{
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
Console.WriteLine("----- 根據 profile 來取得 DOTNET_ENVIRONMENT 環境變數 -----");
Console.WriteLine($"builder.Environment.EnvironmentName:{builder.Environment.EnvironmentName}");
Console.WriteLine($"builder.Configuration[\"DOTNET_ENVIRONMENT\"]:{builder.Configuration["DOTNET_ENVIRONMENT"]}");
Console.WriteLine($"Environment.GetEnvironmentVariable(\"DOTNET_ENVIRONMENT\"):{Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT")}");
}
}
}
下圖是以 EnvironmnetSample profile 的執行結果不使用 Host.CreateApplicationBuilder 產生預設 configuration,手動自行產生 configuration 來讀取
讀取 appsettings 內的連線字串
namespace EnvironmentsSample
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("----- 根據 profile 的 DOTNET_ENVIRONMENT 來決定 appsettings 設定檔案 -----");
string environment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{environment}.json", optional: true)
.AddEnvironmentVariables()
.Build();
string connectionString = configuration.GetConnectionString("SqlServer");
Console.WriteLine($"Environment.GetEnvironmentVariable(\"DOTNET_ENVIRONMENT\"):{environment}");
Console.WriteLine(connectionString);
}
}
}
下圖是以 Staging profile 的執行結果下述 AddJsonFile() 第二參數,在對應 profile 載入 appsettings.json 時,理論上都會設定,萬一對應 appsettings.json 不存在就不載入該設定檔案就是
.AddJsonFile($"appsettings.{environment}.json", optional: true)
在 Configuration providers in .NET 內有提到該段文字
在 Windows 和 launchSettings.json 內的 EnvironmentSample profile 建立自訂環境變數 SecretKey,Staging profile 內故意沒有設定,當 profile 內有設定,會以 profile 為主,沒有才會使用 Windows 環境變數
namespace EnvironmentsSample
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("----- 自訂環境變數:SecretKey -----");
string environment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
string secretKey = Environment.GetEnvironmentVariable("SecretKey");
Console.WriteLine($"Environment.GetEnvironmentVariable(\"DOTNET_ENVIRONMENT\"):{environment}");
Console.WriteLine($"SecretKey:{secretKey}");
}
}
}
下圖是使用 EnvironmentSample profile 和 Staging profile 的疊圖- EnvironmentSample profile:讀取 launchSettings 內的 SecretKey
- Staging profile:讀取 Windows 環境變數
參考 [.NET] 使用 BackgroundService 建立 Windows Service
把 Worker Service 註冊為 Windows Service,觀察部屬後抓到的 appsettings.json
Program 內設定為 Windows Service
namespace EnvironmentsSample
{
public class Program
{
public static void Main(string[] args)
{
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddWindowsService(options =>
{
options.ServiceName = "EnvironmentsService";
});
builder.Services.AddHostedService<Worker>();
var host = builder.Build();
host.Run();
}
}
}
Worker 內注入 configuration,並輸出相關資訊
using System.Text;
namespace EnvironmentsSample
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IConfiguration _configuration;
public Worker(ILogger<Worker> logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
string environment = _configuration["DOTNET_ENVIRONMENT"];
string secretKey = _configuration["SecretKey"];
string connectionString = _configuration.GetConnectionString("SqlServer");
StringBuilder sb = new StringBuilder();
sb.AppendLine($"Worker running at: {DateTimeOffset.Now}");
sb.AppendLine($"DOTNET_ENVIRONMENT:{environment}");
sb.AppendLine($"SecretKey:{secretKey}");
sb.AppendLine($"ConnectionString:{connectionString}");
_logger.LogError(sb.ToString());
}
}
}
沒有留言:
張貼留言