ASP.net Core 2.0中的appsettings.json预览配置GetSection null

时间:2017-07-11 09:20:42

标签: c# json configuration .net-core

我试图从GetSection中的注入配置中调用Startup.cs。 值为null,而具体部分值的indexer返回non-null值。在我看来GetSection方法背后有一个错误,或者我错了吗?

appsettings.json:

  

{" MyConfig":{       " ConfigA":" valueA",       " ConfigB":" valueB" }}

的Program.cs:

    public static void Main(string[] args)
    {
        var host = BuildWebHost(args);
        host.Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();

Startup.cs:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        var mySection = this.Configuration.GetSection("MyConfig");

        var myVal = this.Configuration["MyConfig:ConfigA"];

3 个答案:

答案 0 :(得分:12)

我首先检查了JsonConfigurationProvider.cs的{​​{3}}和1.1.1之间是否有任何变化,这些内部代码最终构建了JSON文件中的可检索值。对于您或this.Configuration.GetSection("MyConfig");最终调用的此代码或任何其他代码,没有任何更改。

检索值有效的方法是Configuration将在代码中定义的每个配置提供程序中以相反顺序查找密钥MyConfig,直到找到值。在您的示例中,提供程序(json,环境变量,命令行参数)在Webhost.CreateDefaultBuilder() 2.x中提供。

查看(see here)的代码,它为键和值构建Dictionary<string, string>,但仅针对原始值。也就是说,MyConfig没有存储密钥(在此级别它是一个对象),但是MyConfig:ConfigA会有一个密钥,数组值看起来像MyConfig:ConfigA:0,{{ 1}}等等。

最后,您会发现MyConfig:ConfigA:1 JsonConfigurationFileParser.cs Configuration.GetSection("MyConfig") 永不为空,最糟糕的情况是ConfigurationSection < Value的em> property 。

那么当您将鼠标悬停在null上并使用智能感知并查看ConfigurationSection属性时,会发现每个配置提供程序都已被搜索,并且没有一个被发现有&#34; MyConfig&#34;的关键将原始值转换为字符串以返回。

您至少需要致电:

Value

将它作为C#对象注入整个应用程序。否则,使用冒号services.Configure<MyConfigOptions>(configuration.GetSection("MyConfig")); services.AddSingleton(cfg => cfg.GetService<IOptions<MyConfigOptions>>().Value); 分隔符语法或["MyConfig:ConfigA"]调用单个值,这是多余的,但说明它仅用于检索基元。

要绑定到C#对象并注入它们,我创建了以下扩展方法:

var mySection = this.Configuration.GetSection("MyConfig")["ConfigA"];

可以像这样调用:

public static class IServiceCollectionExtensions
{
    public static IServiceCollection AddConfigOptions<TOptions>(this IServiceCollection services,
        IConfiguration configuration, string section) where TOptions : class, new()
    {
        services.Configure<TOptions>(configuration.GetSection(section));
        services.AddSingleton(cfg => cfg.GetService<IOptions<TOptions>>().Value);
        return services;
    }
}

并像这样注入:

public class Startup
{
    public Startup(IConfiguration configuration) => Configuration = configuration;

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddConfigOptions<EmailOptions>(Configuration, "Email")

答案 1 :(得分:1)

就我而言,我错过了一个包裹:

Microsoft.Extensions.Configuration.Binder

事实上它被记录为here

中的一个微妙的代码注释

答案 2 :(得分:0)

我发现AspNetCore 2.0在配置方面要比1.x简单得多。

如果在Startup(IConfiguration configuration)构造函数中放置断点,则会注意到configuration变量有大约5个提供程序。

JsonConfigurationProvider是您对 appsettings.json 文件感兴趣的提供程序,但您可能会注意到Data属性有{Count=0 1}}。这很可能是因为您的应用程序正在JsonConfigurationProvider.Source.FileProvider.Root(默认为wwwroot)中指定的目录中查找 appsettings.json 文件。

我所做的就是在.csproj文件中添加一个MSBuild任务,如下所示:

<Copy SourceFiles="appsettings.json" DestinationFolder="wwwroot" />

这似乎完美无缺。

这在 仅限本地开发 期间显然非常有用。但是,现在的一般做法是首先不要在文件中进行配置,特别是因为它最终会成为您的回购历史的一部分。相反,在部署您的应用时,这些天的两种常见做法是使用环境变量来覆盖您的值,甚至更好地使用像领事这样的键/值存储。

此外,我在网上看到了大量关于如何使用services.Configure<>()的奇特示例,但是Startup.cs已经使用DI将值注入IConfiguration configuration。这意味着IConfiguration已经在.NET核心的IoC容器中注册,这实际上意味着您已经可以在应用程序的任何其他类中使用IConfiguration,如下所示:

public JobsRepository(IConfiguration configuration)
{
    this.configA = configuration.GetSection("MyConfig:ConfigA").Value;
}