就像 Web Api 介面可以對入參進行驗證,避免使用者傳入非法的或者不符合我們預期的引數一樣,選項也可以對配置源的內容進行驗證,避免配置中的值與選項類中的屬性不對應或者不滿足預期,畢竟大部分配置都是透過字串的方式,驗證是很有必要的。
1. 註解驗證
像入參驗證一樣,選項驗證也可以透過特性註解方便地對選項類中的某個屬性進行驗證,這種是最簡單便捷的方式。使用選項標籤註解驗證,需要引入 Microsoft.Extensions.Options.DataAnnotations Nuget 包。
在選項類中透過以下方式新增資料驗證規則:
public class BlogOptions
{
public const string Blog = "Blog";
[StringLength(10, ErrorMessage = "Title is too long. {0} Length <= {1}")]
public string Title { get; set; }
public string Content { get; set; }
public DateTime CreateTime { get; set; }
}
之後在進行選項類配置的時候就不能直接使用 Configure 方法了,而是要用以下方式:
builder.Services.AddOptions<BlogOptions>()
.Bind(builder.Configuration.GetSection(BlogOptions.Blog))
.ValidateDataAnnotations();
2. 自定義驗證邏輯
預定義的資料註解畢竟有限,在某些驗證邏輯比較複雜的情況下,資料註解可能並不能完全滿足我們的需求,我們可以透過 OptionsBuilder
builder.Services.AddOptions<BlogOptions>()
.Bind(builder.Configuration.GetSection(BlogOptions.Blog))
.Validate(options =>
{
// 標題中不能包含特殊字元
if (options.Title.Contains("eval"))
{
// 驗證失敗
return false;
}
// 驗證透過
return true;
});
3. IValidateOptions 驗證介面
如果邏輯更加複雜,透過 Validate 方法會導致程式碼臃腫,不好管理和維護,這時候我們可以透過 IValidateOptions
public class BlogValidation : IValidateOptions<BlogOptions>
{
public ValidateOptionsResult Validate(string name, BlogOptions options)
{
var failures = new List<string>();
if(options.Title.Length > 100)
{
failures.Add($"部落格標題長度不能超過100個字元。");
}
if(options.Content.Length > 10000)
{
failures.Add($"部落格內容太長,不能超過10000字。");
}
if (failures.Any())
{
return ValidateOptionsResult.Fail(failures);
}
return ValidateOptionsResult.Success;
}
}
然後將其注入到依賴注入容器中,可以同時注入針對同一個選項類的驗證邏輯類,這些驗證類都會被呼叫,只有全部驗證邏輯透過才能正常配置。
builder.Services.Configure<BlogOptions>(builder.Configuration.GetSection(BlogOptions.Blog));
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IValidateOptions<BlogOptions>, BlogValidation>());
參考文章:
ASP.NET Core 中的選項模式 | Microsoft Learn
選項模式 - .NET | Microsoft Learn
面向 .NET 庫建立者的選項模式指南 - .NET | Microsoft Learn
理解ASP.NET Core - 選項(Options)
ASP.NET Core 系列: