---
markdown.preview.linkify=false
---
# Configuration in ASP.NET Core
## 起因
由於加入了 [Cloud SQL Auth proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy),因此原本 ASP.NET Core 放在 `appsettings.json` 的連線字串需要更改,但每次更改都需要重新打包才能部署到 K8s 上著實不便,從權限管理或是資安角度來看也不合適。因此選擇使用 K8s Secret 將連線字串注入至環境變數才是較佳的做法。
前篇:[Connect Cloud SQL from Kubernetes Engine](/K1siCTj9TjugpbTK8TcprQ)
## 簡介
Source: [Microsoft Documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0)
ASP.NET Core 中的組態是由一或多個[組態提供者](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0#cp)。組態提供者從多種組態來源讀取組態資料的鍵值對:
- 設定檔,例如:*appsettings.json*
- 環境變數
- 命令列參數
- 目錄(directory)檔
- 記憶體內的 .NET 物件
- ......
## 預設組態
一個由 [dotnet new](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-new) 或 Visual Studio 建立的 ASP.NET Core web app 會產生下列程式碼:
```csharp
var builder = WebApplication.CreateBuilder(args);
```
[WebApplication.CreateBuilder](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.webapplication.createbuilder?view=aspnetcore-6.0) 使用預配置的預設值初始化了一個新的 [WebApplicationBuilder](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.webapplicationbuilder) class 個體。依照下面的順序,初始化的 `WebApplicationBuilder` (`builder`) 提供預設的組態給該應用程式:
1. [ChainedConfigurationProvider](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.configuration.chainedconfigurationsource): 加入現有的 `IConfiguration` 作為來源。在預設的組態情況裡,新增 [host](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0#hvac) 組態並將它設定為給該 *app* 組態的第一個來源。
2. 使用 [JSON 組態提供者](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0#file-configuration-provider) 的 [appsettings.json](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0#appsettingsjson)。
3. 使用 JSON configuration provider 的 *appsettings.`Environment`.json*。例如:*appsettings.**Production**.json* 和 *appsettings.**Development**.json*。
4. 當 app 在 `Developement` 環境執行時使用的 [app secrets](https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-6.0)。
5. 使用[環境變數組態提供者](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0#evcp)的環境變數。
6. 使用[命令列組態提供者](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0#command-line)的命令列參數。
較晚加入的組態提供者會覆寫之前的 key 設定。舉例來說,如果 `MyKey` 在 *appsettings.json* 和環境都有設定的話,會使用環境變數的值。
# Get conneciton string from environment variables in ASP.NET Core
## 使用預設的環境變數提供者
這種方式是改動最少的方式,只要在環境變數添加以下開頭的 key,default configuration provider 就會自動將它判定為連線字串了:
| Connection string prefix | Provider |
| ------------------------ | ------------------ |
| `CUSTOMCONNSTR_` | Custom provider |
| `MYSQLCONNSTR_` | MySQL |
| `SQLCONNSTR_` | SQL Server |
| `SQLAZURECONNSTR_` | Azure SQL Database |
當任一個上表列的四項前綴字串在環境變數中被發現並載入至組態時:
- 移除環境變數前綴並加入組態鍵區(`ConnectionStrings`)來建立組態鍵(configuration key)。
- 建立一個代表資料庫連線提供者(除了沒有明列提供者的 `CUSTOMCONNSTR_`)的新組態鍵值對。
| Environment variable key | Converted configuration key | Provider configuration entry |
| ------------------------ | --------------------------- | ---------------------------------------------------------------------------------- |
| `CUSTOMCONNSTR_{KEY}` | `ConnectionStrings:{KEY}` | Configuration entry not created. |
| `MYSQLCONNSTR_{KEY}` | `ConnectionStrings:{KEY}` | Key: `ConnectionStrings:{KEY}_ProviderName:` <br />Value: `MySql.Data.MySqlClient` |
| `SQLCONNSTR_{KEY}` | `ConnectionStrings:{KEY}` | Key: `ConnectionStrings:{KEY}_ProviderName:` <br />Value: `System.Data.SqlClient` |
| `SQLAZURECONNSTR_{KEY}` | `ConnectionStrings:{KEY}` | Key: `ConnectionStrings:{KEY}_ProviderName:` <br />Value: `System.Data.SqlClient` |
### Example
`Program.cs`
```csharp
builder.Services.AddDbContext<YourContext>(options =>
{
if (builder.Environment.IsDevelopment())
{
options.UseSqlite(builder.Configuration.GetConnectionString("SqliteContext"));
}
else
{
options.UseNpgsql(builder.Configuration.GetConnectionString("Postgresql"));
}
});
```
設定環境變數
```bash
export CUSTOMCONNSTR_Postgresql="Server=localhost;Database=postgres;Username=postgres;Password=pwd;"
```
## 新增自訂的環境變數前綴
使用指定環境變數前綴的字串呼叫 [AddEnvironmentVariables](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.configuration.environmentvariablesextensions.addenvironmentvariables):
```csharp=
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_");
var app = builder.Build();
```
上述的程式碼:
- `builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_")` 在 [default configuration provider](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0#default) 後加入。
- 含有 `MyCustomPrefix_` 前綴的環境變數會覆寫 [default configuration providers](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0#default)。
當組態鍵值對被讀取時會去掉前綴。
:::warning
The `:` separator doesn't work with environment variable hierarchical keys on all platforms. `__`, the double underscore, is:
- Supported by all platforms. For example, the `:` separator is not supported by Bash, but `__` is.
- Automatically replaced by a `:`
:::
###### tags: `asp-net` `asp-net-core` `k8s`