.Net Core Configuration(組態設定)
以往的組態設定方式
相信有寫過.Net Framework MVC 開發專案的人員,都會從專案中的Web.config來取得組態設定,但在.Net Core裡面是已經沒有Web.config檔案了,取而代之的是
- 組態設定檔(Json ,Xml,INI)
- 命令列參數
- 環境變數
- 自訂的組態提供者 (custom configuration provider)
- 記憶體中的 .NET 物件
- 從未加密的 Secret Manager 儲存區取得設定
- Azure Key Vault
等等的來源,之前在我的文章內也有稍微帶到ASP .NET MVC 5 前進 .NET
這次的紀錄會聚焦在組態設定檔的實作
OK Let's Get Ready To Rumble!!!
Configuration的初步認識
首先我們先開一個專案Empty 的 .Net Core,這也是我很常用來研究.Net 以及要弄清楚各個功能會去開設的專案,原因是要學習一項新的知識,環境越簡單越好,如果開啟預設的.Net Core Web應用程式,它會有很多預設好的文件和設定,這樣對學習來說會變得更加難以理解。
我們在日常專案中會將
- DB連線字串
- Client ID
- API Keys
- Domain Names
- Constant email addresses
- SSMTP 站台的設定
等等放入組態文件appsettings.json中,由於是Key Value的形式,只要前面有個,做分隔 就可以開始定義自己想要的組態的值。
之後再到Program.cs,啟用我們這次練習會用到的Services 以及 Middleware,預設的app.MapGet(“/”, () => “Hello World!”);這個可以拿掉,不影響我們的操作。
利用 app.Configuration[“MyKey”] 來取得我們在先前appsettings.json定義的MyKey。
app.MapGet("/", async context =>
{
var appsettingsMyKey = app.Configuration["MyKey"];
if (appsettingsMyKey is not null)
{
await context.Response.WriteAsync(appsettingsMyKey);
}
else
{
await context.Response.WriteAsync("No Value");
}
});
我們可以成功地從 MyKey 這個Key值取到我們的 Value值
還有另外一種寫法
我們也可以使用app.Configuration.GetValue<>的方法,來定義要取值的型別,像這邊我使用string型別來取得”MyKey”的Value
app.MapGet("/", async context =>
{
//var appsettingsMyKey = app.Configuration["MyKey"];
var appsettingsMyKey = app.Configuration.GetValue<string>("MyKey");
if (appsettingsMyKey is not null)
{
await context.Response.WriteAsync(appsettingsMyKey);
}
else
{
await context.Response.WriteAsync("No Value");
}
});
app.Configuration.GetValue<>的方法也可以提供預設值Default value,像以下的例子我提供了第二個參數,也就是Default value
我們的appsettings.json並沒有 x 這個Key,我們將預設值設定為66
app.MapGet("/", async context =>
{
//var appsettingsMyKey = app.Configuration["MyKey"];
var appsettingsMyKey = app.Configuration.GetValue<string>("MyKey");
var numberx = app.Configuration.GetValue<int>("x", 66);
if (appsettingsMyKey is not null)
{
await context.Response.WriteAsync(appsettingsMyKey + "\n");
await context.Response.WriteAsync(numberx + "\n");
}
else
{
await context.Response.WriteAsync("No Value");
}
});
程式運行起來我們也能夠拿到預設值66。
在Controller 或其他地方取得組態設定
在Controller中或其他Class中取得Configuration也是我們平日在專案中比較常見的操作方式
我們先將Program.cs中的app.MapGet 這段註解
在我們練習的專案裡面建立簡單的Controller 跟 View
在Controller內 定義一個 private readonly 的 IConfiguration
透過 constructor DI注入取得IConfiguration的服務
我們用ViewBag來取得組態的值
這邊我故意取我們appsettings.json中沒有設定的Key MyAPI 並且給它一個預設值
View 也是相當簡單,直接把我們的ViewBag帶過來
OK,可以成功取得我們在appsettings.json 設定的組態。
但利用IConfiguration這種方式取值是相對來說比較rough的,但如果在你的專案中也只有一些地方需要使用到,沒有高重複利用的需求這樣的方法也是可以接受的,假如說是使用HttpClient要不停得呼叫API,當中要使用到API的Token這樣的方式可能不太好,我們會使用Options Pattern的方式。
Options Pattern
我們在appsettings.json 再新增一個StripeSetting段落的組態設定
然後定義出一個StripeService 的 class
這邊的const string 很關鍵,字串的值必須與appsettings.json中的StripeSetting段落的組態名稱匹配。
回到我們的Program.cs
builder.Services.Configure<StripeService>(builder.Configuration.GetSection(StripeService.StripeSetting));
我們就可以完全用強型別的方式去指定,我們要從appsettings.json拿取的Section 也就是StripeSetting 這個段落。
回到我們的Controller
一樣從constructor DI注入取得IOptions服務
就可以用_options.Value.XXX,強型別的方式取得我們的組態設定了。
這樣的寫法可重複利用性很高,很適合需要使用httpclient去呼叫API需要帶入Api Key的場合。
Custom Json Configuration
最後想跟大家分享的是Custom Json Configuration,也就是自定義Json檔。
通常我們會使用上這樣的場合可能不多,可能我們想在另一個Json檔案中存放資料;亦或是原先的appsettings.json資料量太多難以管理時想開一個屬於自己的Json檔案,這時候我們就可以使用自定義Json檔。
我在專案檔內加入了MyConfig的json檔案,並且把剛剛的StripeSetting 複製了過來,改了它們的Value 好辨識是從我們新建立的MyConfig.json。
回到我們Program.cs
來自定義我們的json文檔
builder.Configuration.AddJsonFile("MyConfig.json", optional: true, reloadOnChange: true);
第一個參數是我們自定義json的檔名,第二個參數 optional: true 的意思代表該檔案是可選的,並不會因為找不到該文件而發生exception,reloadOnChange: true的意思是當程式在Runtime的時候,只要組態設定改變了程式就會重啟。
我們Controller的code並沒有更動,但是卻已經從MyConfig.json取得組態設訂了,這是因為我們新增了自定義組態的來源,我們的自定義設定有著較高的優先層級,這也是要特別注意的地方!
這次的Configuration分享大概就是這樣,有機會再跟大家分享Secret Manager 或是 Environment 環境變數的操作,倘若有任何問題或想分享的,歡迎留言給我~