昨天我們新增了一個 UserServiceWithFile 操作本地端檔案來管理使用者資料,而檔案的路徑是寫死在程式碼裡面的。這種寫死的設定有幾個缺點:
比較好的作法是把組態設定寫在設定檔(appsettings.json)裡,再讓我們的程式從這裡讀取設定。我們今天要來介紹如何在 .NET Web API 專案中,中讀取組態設定。
appsettings.json 是 .NET 5 Web API 專案預設的設定檔,我們的程式在執行的時候,會從這裡取得組態設定。但仔細看一下右邊的方案總管,會發現 appsettings.json 其實可以展開,展開後會看到 appsettings.Development.json。這兩者的差別是,debug 模式下 appsettings.Development.json 會蓋掉 appsettings.json 的設定。
由於 appsettings.Development.json 不會進版控(因為正式環境不會用它),我們就能放心的把資料庫連線等機密資訊存在這邊,愉快的 debug。等到程式部屬到正式環境之後,再用加密連線的方式,把機密資訊寫到正式的 appsettings.json。如此一來,我們就能避免因為版控洩漏機密資訊。
現在,讓我們把測試用的設定加入這兩個檔案:
// appsettings.json
{
"Logging": {
// 這個區塊不變
},
"TestConfiguration": {
"EnableLog": false,
"FileName": "" // 這邊先挖空才進版控,以後部屬的時候再補上去
}
}
// appsettings.Development.json
{
"Logging": {
// 這個區塊不變
},
"TestConfiguration": {
"EnableLog": false,
"FileName": "D:/TestUsers.csv"
}
}
要取得設定檔,一個最簡單的做法是直接把 Startup.cs 的 public 屬性 「Configuration」,以 IConfiguration 的形式註冊到服務容器。下面這行程式碼把 IConfiguration 這個介面以 singleton 的生命週期註冊到服務容器讓別人依賴,而實作這個介面的是「Configuration」這個屬性。
public void ConfigureServices(IServiceCollection services)
{
// 其他部分不變
services.AddSingleton<IConfiguration>(Configuration); // 加入這一行
services.AddScoped<IUserCRUD, UserServiceWithFile>();
}
然後一樣注入給 Controller,再從注入的IConfiguration 介面取得設定值
public class UserServiceWithFile : IUserCRUD
{
private readonly string _fileName;
private readonly List<User> _users;
private readonly IConfiguration _config;
public UserServiceWithFile(IConfiguration config)
{
_config = config;
_fileName = _config.GetSection("TestConfiguration:FileName").Value;
_users = ReadUsersFromFile(_fileName);
}
// 其他部分不變
}
上面的程式碼使用 GetSection 這個方法,從 appsettings.json 取得設定值。用 GetSection("xxx").Value 取得設定有幾點要注意
改完之後,我們就成功的從設定檔中取得資訊了!
上面的做法很簡單而且已經能滿足我們的需求,但是筆者更喜歡接下來要介紹的作法。這個做法可以直接取得強型別的設定物件。這個方法也很簡單,只需要以下三個步驟
1 宣告一個用來儲存設定的類別,這邊要注意類別的屬性名稱要與 json 物件的 key 值一致,但不分大小寫。
public class UserServiceOptions
{
public bool EnableLog { get; set; }
public string FileName { get; set; }
}
2 在 Startup.cs 抽取設定檔的區段,將它對應到剛剛宣告的類別,接著註冊到服務容器
public void ConfigureServices(IServiceCollection services)
{
// 其他部分不變
services.Configure<UserServiceOptions>( // 改成這一行
Configuration.GetSection("TestConfiguration"));
services.AddScoped<IUserCRUD, UserServiceWithFile>();
}
上面那段程式碼代表從 appsettings.json 中抽取 “TestConfiguration” 區段,然後把這個 json 物件對應到 UserServiceOptions 這個類別,最後以 IOptions 的介面註冊到服務容器。
3 注入到 Controller 並使用。
public class UserServiceWithFile : IUserCRUD
{
private readonly string _fileName;
private readonly List<User> _users;
private readonly IOptions<UserServiceOptions> _option;
public UserServiceWithFile(IOptions<UserServiceOptions> option)
{
_option = option;
_fileName = _option.Value.FileName;
_users = ReadUsersFromFile(_fileName);
}
// 其他部分不變
}
改完收工,我們的 API 程式就能從設定檔讀取設定。以後要變更設定,只要修改 appsettings.json 裡的值,然後重啟程式就可以了。
明天開始,我們將一步一步地介紹怎麼把目前完成的專案丟上雲端執行。