就像 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 系列:
目录:ASP.NET Core 系列总结
上一篇:ASP.NET Core - 选项系统之选项使用