MVC 6 配置验证

MVC 6 Configuration Validation

在 MVC 6 项目中,我有以下配置文件...

{
  "ServiceSettings" :
  {
    "Setting1" : "Value"
  }
}

...以及以下 class...

public class ServiceSettings
{
  public Setting1
  {
    get;

    set;
  }
}

Startup class 的 ConfigureServices 方法中,我添加了以下代码行...

services.Configure<ServiceSettings>(Configuration.GetConfigurationSection("ServiceSettings"));

如果需要 Setting1 的值,我该如何验证?我可以在实际使用 IOptions<ServiceSettings> 实例时进行验证,但如果 Setting1 的值对于服务的操作是必需的,我想尽早捕获它而不是进一步下游。旧的 ConfigurationSection 对象允许您指定规则,如果某些内容无效,这些规则将在读取配置数据时抛出异常。

您可以执行以下操作:

services.Configure<ServiceSettings>(serviceSettings =>
{
    // bind the newed-up type with the data from the configuration section
    ConfigurationBinder.Bind(serviceSettings, Configuration.GetConfigurationSection(nameof(ServiceSettings)));

    // modify/validate these settings if you want to
});

// your settings should be available through DI now

我在 ServiceSettings 中的任何强制性属性上卡住了 [Required],并在 Startup.ConfigureServices 中添加了以下内容:

services.Configure<ServiceSettings>(settings =>
{
    ConfigurationBinder.Bind(Configuration.GetSection("ServiceSettings"), settings);

    EnforceRequiredStrings(settings);
})

以及 Startup 的以下内容:

private static void EnforceRequiredStrings(object options)
{
    var properties = options.GetType().GetTypeInfo().DeclaredProperties.Where(p => p.PropertyType == typeof(string));
    var requiredProperties = properties.Where(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(RequiredAttribute)));

    foreach (var property in requiredProperties)
    {
        if (string.IsNullOrEmpty((string)property.GetValue(options)))
            throw new ArgumentNullException(property.Name);
    }
}

使用 ASP.Net-Core 2.0

验证选项的简洁方法

netcore2.0 开始,PostConfigure 很合适。这个函数也接受一个配置委托,但最后执行,所以一切都已经配置好了。

// Configure options as usual
services.Configure<MyOptions>(Configuration.GetSection("section"));

// Then, immediately afterwards define a delegate to validate the FINAL options later
services.PostConfigure<MyOptions>(myOptions => {
    // Take the fully configured myOptions and run validation checks...
    if (myOptions.Option1 == null) {
        throw new Exception("Option1 has to be specified");
    }
});

如果不怕向配置对象添加更多代码,可以像 Andrew Lock blog 中描述的那样在启动时实施验证。他创建了 NuGet 包以避免自己添加代码。 如果你想探索更多的可能性,还有 ConfigurationValidation 包提供了一些扩展的配置验证功能(自以为是:我是作者)。 如果您正在使用 FluentValidation 进行某些操作,there is possibility 也可以将其用于配置验证。