您好,登錄后才能下訂單哦!
這篇文章主要介紹了如何為ASP.NET Core強類型配置對象添加驗證,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
ASP.NET Core中的強類型配置
ASP.NET Core的配置系統非常的靈活,它允許你從多種數據源中讀取配置信息,例如Json文件,YAML文件,環境變量,Azure Key Vault等。官方推薦方案是使用強類型配置來獲取IConfiguration接口對象的值。
強類型配置使用POCO對象來呈現你的程序配置的一個子集,這與IConfiguration接口對象存儲的原始鍵值對不同。例如,現在你正在你的程序中集成Slack, 并且使用Web hooks向頻道中發送消息,你需要配置Web hook的URL, 以及一些其他的配置。
public class SlackApiSettings { public string WebhookUrl { get; set; } public string DisplayName { get; set; } public bool ShouldNotify { get; set; } }
你可以在Startup類中使用擴展方法Configure,將強類型配置對象和你程序配置綁定起來。
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.Configure<SlackApiSettings>(Configuration.GetSection("SlackApi")); } public void Configure(IApplicationBuilder app) { app.UseMvc(); } }
當你需要讀取配置的時候,你只需要在你當前方法所在類的構造函數中注入一個IOptions接口對象,即可使用這個對象的Value屬性,獲取到配置的值, 這里ASP.NET Core配置系統自動幫你完成了強類型對象和配置之間的綁定。
public class TestController : Controller { private readonly SlackApiSettings _slackApiSettings; public TestController(IOptions<SlackApiSettings> options) { _slackApiSettings = options.Value } public object Get() { return _slackApiSettings; } }
解除對IOptions接口的依賴
可能有些人和我一樣,不太喜歡讓自己創建的類依賴于IOptions接口,我們只希望自己創建的類僅依賴于配置對象。這里你可以使用如下所述的方法來解除對IOptions接口的依賴。這里我們可以在依賴注入容器中顯式的注冊一個SlackApiSetting配置對象,并將解析它的方法委托給一個IOptions對象
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.Configure<SlackApiSettings>(Configuration.GetSection("SlackApi")); services.AddSingleton(resolver => resolver.GetRequiredService<IOptions<SlackApiSettings>>().Value); }
現在你可以在不引用Microsoft.Extensions.Options程序集的情況下,注入了一個“原始”的配置對象了。
public class TestController : Controller { private readonly SlackApiSettings _slackApiSettings; public TestController(SlackApiSettings settings) { _slackApiSettings = settings; } public object Get() { return _slackApiSettings; } }
這個解決方案通常都非常有效, 但是如果配置出現問題,例如在JSON文件中出現了錯誤拼寫,這里會發生什么事情呢?
如果綁定失敗,程序會發生什么事情?
我們綁定強類型配置對象的時候有以下幾種錯誤的可能。
節點名稱拼寫錯誤
當你綁定配置的時候,你需要顯式的指定綁定的配置節點名稱,如果你當前使用的appsetting.json作為配置文件,json文件中的key即是配置的節點名稱。例如下面代碼中的"Logging"和“SlackApi”
{ "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "SlackApi": { "WebhookUrl": "http://example.com/test/url", "DisplayName": "My fancy bot", "ShouldNotify": true } }
為了綁定"SlackApi"節點的值到強類型配置對象SlackApiSetting, 你需要調用一下代碼
services.Configure<SlackApiSettings>(Configuration.GetSection("SlackApi"));
這時候,假設我們將appsettings.json中的"SlackApi"錯誤的拼寫為"SackApi"。現在我們去調用前面例子中的TestController中的GET方法,會得到一下結果
{ "webhookUrl":null, "displayName":null, "shouldNotify":false }
所有的key都是綁定了他們的默認值,但是沒有發生任何錯誤,這意味著他們綁定到了一個空的配置節點上。這看起來非常糟糕,因為你的代碼并沒有驗證webhookUrl是否是一個合法的Url。
屬性名拼寫錯誤
相似的,有時候拼寫的節點名稱正確,但是屬性名稱可能拼寫錯誤。例如, 我們將appSettings.json文件中的"WebhookUrl"錯誤的拼寫為"Url"。這時我們調用前面例子中的TestController中的GET方法,會得到以下結果
{ "webhookUrl":null, "displayName":"My fancy bot", "shouldNotify":true }
強類型配置類的屬性缺少SET訪問器
我經常發現一些初級程序員會遇到這個問題,針對屬性,他們只提供了GET訪問器,而缺少SET訪問器,在這種情況下強類型配置對象是不會正確綁定的。
public class SlackApiSettings { public string WebhookUrl { get; } public string DisplayName { get; } public bool ShouldNotify { get; } }
現在我們去調用前面例子中的TestController中的GET方法,會得到以下結果
{ "webhookUrl":null, "displayName":null, "shouldNotify":false }
不兼容的類型值
最后一種情況就是將一個不兼容的類型值,綁定到屬性上。在配置文件中,所有的配置都是以文本形式保存的,但是綁定器需要將他們轉換成.NET中支持的基礎類型。例如ShouldNotify屬性是一個布爾類型的值,我們只能將"True", "False"字符串綁定到這個值上,但是如果你在配置文件中,設置該屬性的值為"THE VALUE", 當程序訪問TestController時,程序就會報錯
使用IStartupFilter創建一個配置驗證
為了解決這個問題,我將使用IStartupFilter創建一個在應用啟動時運行的簡單驗證步驟,以確保你的設置正確無誤。
IStartupFilter接口允許你通過向依賴注入容器添加服務來間接控制中間件管道。 ASP.NET Core框架使用它來執行諸如“將IIS中間件添加到應用程序的中間件管道的開頭, 或添加診斷中間件之類”的操作。
雖然IStartupFilter經常用來向管道中添加中間件,但是我們也可以不這么做。相反的,我們可以在程序啟動時(服務配置完成之后,處理請求之前),使用它來執行一些簡單的代碼。
這里首先我們創建一個簡單的接口,強類型配置類可以通過實現這個接口來完成一些必要的驗證。
public interface IValidatable { void Validate(); }
下一步,我們創建一個SettingValidationStartupFilter類, 它實現了IStartupFilter接口
public class SettingValidationStartupFilter : IStartupFilter { readonly IEnumerable<IValidatable> _validatableObjects; public SettingValidationStartupFilter(IEnumerable<IValidatable> validatableObjects) { _validatableObjects = validatableObjects; } public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) { foreach (var validatableObject in _validatableObjects) { validatableObject.Validate(); } return next; } }
在構造函數中,我們從依賴注入容器中取出了所有實現IValidatable接口的強類型配置對象,并在Configure方法中依次調用他們的Validate方法。
SettingValidationStartupFilter并沒有修改任何中間件管道, Configure方法中直接返回了next對象。但是如果某個強類型配置類的驗證失敗,在程序啟動時,就會拋出異常,從而阻止了程序。
接下來我們需要在Startup類中注冊我們創建的服務SettingValidationStartupFilter
public void ConfigureServices(IServiceCollection services) { services.AddTransient<IStartupFilter, SettingValidationStartupFilter>() // 其他配置 }
最后你需要讓你的配置類實現IValidatable接口, 我們以SlackApiSettings為例,這里我們需要驗證WebhoolUrl和DisplayName屬性是否綁定成功,并且我們還需要驗證 WebhoolUrl是否是一個合法的Url。
public class SlackApiSettings : IValidatable { public string WebhookUrl { get; set; } public string DisplayName { get; set; } public bool ShouldNotify { get; set; } public void Validate() { if (string.IsNullOrEmpty(WebhookUrl)) { throw new Exception("SlackApiSettings.WebhookUrl must not be null or empty"); } if (string.IsNullOrEmpty(DisplayName)) { throw new Exception("SlackApiSettings.WebhookUrl must not be null or empty"); } // 如果不是合法的Url,就會拋出異常 var uri = new Uri(WebhookUrl); } }
當然我們還可以使用DataAnnotationsAttribute來實現上述驗證。
public class SlackApiSettings : IValidatable { [Required, Url] public string WebhookUrl { get; set; } [Required] public string DisplayName { get; set; } public bool ShouldNotify { get; set; } public void Validate() { Validator.ValidateObject(this, new ValidationContext(this), validateAllProperties: true); } }
無論你使用哪一種方式,如果綁定出現問題,程序啟動時都會拋出異常。
最后一步,我們需要將SlackApiSettings 以IValidatable接口的形式注冊到依賴注入容器中,這里我們同樣可以使用前文的方法解除對IOptions接口的依賴。
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddTransient<IStartupFilter, SettingValidationStartupFilter>() services.Configure<SlackApiSettings>(Configuration.GetSection("SlackApi")); services.AddSingleton(resolver => resolver.GetRequiredService<IOptions<SlackApiSettings>>().Value); services.AddSingleton<IValidatable>(resolver => resolver.GetRequiredService<IOptions<SlackApiSettings>>().Value); }
感謝你能夠認真閱讀完這篇文章,希望小編分享的“如何為ASP.NET Core強類型配置對象添加驗證”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。