我试图从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"];
答案 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)
答案 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;
}