【问题标题】:appsettings.json in ASP.net Core 2.0 Preview configuration GetSection nullASP.net Core 2.0 Preview 配置中的 appsettings.json GetSection null
【发布时间】:2017-12-15 06:29:21
【问题描述】:

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

appsettings.json:

{ “我的配置”:{ “配置A”:“值A”, “配置B”:“值B”}}

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"];

【问题讨论】:

    标签: c# json configuration .net-core


    【解决方案1】:

    我首先检查了JsonConfigurationProvider.cs1.1.12.x 之间是否有任何变化,这是最终从您的JSON 文件构造可检索值的内部代码。您的this.Configuration.GetSection("MyConfig"); 最终调用的此代码或任何其他代码都没有更改。

    检索值的工作方式是Configuration 将在每个配置提供程序中按代码中定义的相反顺序 查找您的密钥MyConfig,直到找到一个值。在您的示例中,Webhost.CreateDefaultBuilder()(see here) 中提供了提供程序(json、环境变量、命令行参数)。

    查看JsonConfigurationFileParser.cs 的代码,它为键和值构建了一个Dictionary&lt;string, string&gt;但仅用于原始值。也就是说,没有为MyConfig 存储键(在此级别它是一个对象),但将有一个用于MyConfig:ConfigA 的键,并且数组值看起来像MyConfig:ConfigA:0MyConfig:ConfigA:1 等。

    最后,你会发现Configuration.GetSection("MyConfig")always returns you a newly constructedConfigurationSection永远不会为空,最坏的情况是Value属性 null.

    那么,当您使用 Intellisense 将鼠标悬停在 ConfigurationSection 上并查看 Value 属性时会发生什么情况,即 每个 配置提供程序都已被搜索,但没有找到具有“MyConfig”键的" 将原始值转换为要返回的字符串。

    您至少需要致电:

    services.Configure<MyConfigOptions>(configuration.GetSection("MyConfig"));
    services.AddSingleton(cfg => cfg.GetService<IOptions<MyConfigOptions>>().Value);
    

    将其作为 C# 对象注入整个应用程序。否则,使用冒号 ["MyConfig:ConfigA"] 分隔符语法或 var mySection = this.Configuration.GetSection("MyConfig")["ConfigA"]; 调用单个值,这是多余的,但说明它仅用于检索原语。

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

    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")
    

    并像这样注入:

    public class EmailSender : IEmailSender
    {
        private EmailOptions _emailOptions;
    
        public EmailSender(EmailOptions options) => _emailOptions = options;
    

    【讨论】:

    • 这行得通,而且从 MS 文档中看不出来。
    • 那是因为这违背了微软的承诺。您应该将 IOptions 注入到您的类中,而不是尝试注入您的配置实例。
    【解决方案2】:

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

    Microsoft.Extensions.Configuration.Binder

    事实上,它在here 中被记录为一个微妙的代码注释

    【讨论】:

      【解决方案3】:

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

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

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

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

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

      这似乎很有效。

      这在仅限本地开发期间显然很有用。然而,现在的一般做法是从一开始就永远不要在文件中进行配置,特别是因为它最终会成为你的回购历史的一部分。相反,在部署您的应用程序时,目前两种常见做法是使用环境变量来覆盖您的值,或者使用 consul 之类的键/值存储更好。

      此外,我在网上看到一大堆关于如何使用services.Configure&lt;&gt;() 的精美示例,这很好,但Startup.cs 已经使用DI 将值注入IConfiguration configuration。这意味着 IConfiguration 已经在 .NET core 的 IoC 容器中注册,因此这实质上意味着您已经可以在应用程序的任何其他类中使用 IConfiguration,如下所示:

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

      【讨论】:

      • 您永远不想将 appsettings.json 复制到 wwwroot。如果您这样做,您将公开(可查看)它。你为什么要这样公开你的配置?
      • 在启动期间,它会在您的 WebRoot 中查找 appSettings.json。这在仅在本地开发 期间显然很有用。然而,现在的一般做法是从一开始就永远不要在文件中进行配置,特别是因为它最终会成为你的回购历史的一部分。相反,在部署您的应用程序时,如今两种常见做法是使用环境变量来覆盖您的值,或者甚至更好地使用像 consul 这样的键/值存储......如果没有先澄清就没有必要投反对票。
      • 即使是本地开发,也不应该去那里。该文件属于其他二进制文件旁边的 /bin 编译输出目录。 Aspnetcore 将从那里加载它。
      猜你喜欢
      • 2017-10-13
      • 2017-10-22
      • 1970-01-01
      • 2017-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多