ASP.net Core 2.0 Preview 配置中的 appsettings.json GetSection null
Posted
技术标签:
【中文标题】ASP.net Core 2.0 Preview 配置中的 appsettings.json GetSection null【英文标题】:appsettings.json in ASP.net Core 2.0 Preview configuration 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"];
【问题讨论】:
【参考方案1】:我首先检查了JsonConfigurationProvider.cs
的1.1.1 和2.x 之间是否有任何变化,这是最终从您的JSON 文件构造可检索值的内部代码。您的this.Configuration.GetSection("MyConfig");
最终调用的此代码或任何其他代码都没有更改。
检索值的工作方式是Configuration
将在每个配置提供程序中按代码中定义的相反顺序 查找您的密钥MyConfig
,直到找到一个值。在您的示例中,Webhost.CreateDefaultBuilder()
(see here) 中提供了提供程序(json、环境变量、命令行参数)。
查看JsonConfigurationFileParser.cs 的代码,它为键和值构建了一个Dictionary<string, string>
,但仅用于原始值。也就是说,没有为MyConfig
存储键(在此级别它是一个对象),但将有一个用于MyConfig:ConfigA
的键,并且数组值看起来像MyConfig:ConfigA:0
、MyConfig: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<>()
的精美示例,这很好,但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 将从那里加载它。以上是关于ASP.net Core 2.0 Preview 配置中的 appsettings.json GetSection null的主要内容,如果未能解决你的问题,请参考以下文章
.NET 6 Preview 5 中的 ASP.NET Core 更新
.NET Core 3.0 Preview 6中对ASP.NET Core和Blazor的更新
Asp.Net Core 7 preview 4 重磅新特性--限流中间件
.NET 6 Preview 4 已发布,ASP.NET Core 更新内容