ASP.net Core 2.0中的appsettings.json预览配置GetSection null
我试图从Startup.cs
注入配置调用GetSection
。 Value为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() .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"];
我首先检查了JsonConfigurationProvider.cs
1.1.1和2.x之间是否有任何变化,这些内部代码最终构建了JSON文件中的可检索值。 这个或任何其他代码最终都没有被你的this.Configuration.GetSection("MyConfig");
调用this.Configuration.GetSection("MyConfig");
。
检索值的方法是, Configuration
将按照代码中定义的相反顺序在每个配置提供程序中查找您的密钥MyConfig
,直到找到值。 在您的示例中,提供程序(json,环境变量,命令行参数)在Webhost.CreateDefaultBuilder()
中提供(请参见此处) 。
查看JsonConfigurationFileParser.cs的代码,它为键和值构建Dictionary
, 但仅用于原始值 。 也就是说,没有为MyConfig
存储密钥(在此级别它是一个对象),但是MyConfig:ConfigA
会有一个密钥MyConfig:ConfigA
,数组值看起来像MyConfig:ConfigA:0
, MyConfig:ConfigA:1
等。
最后,您会发现Configuration.GetSection("MyConfig")
总是返回一个 永远为null 的新构造的 ConfigurationSection
,最坏的情况是Value
属性为null
。
那么当您将鼠标hover在具有Intellisense的ConfigurationSection
上并查看Value
属性时会发生的情况是, 每个配置提供程序都已被搜索,并且没有发现任何“MyConfig”键的原始值转换为字符串以返回。
你至少需要打电话:
services.Configure(configuration.GetSection("MyConfig")); services.AddSingleton(cfg => cfg.GetService>().Value);
将它作为C#对象注入整个应用程序。 否则,使用冒号["MyConfig:ConfigA"]
分隔符语法或使用var mySection = this.Configuration.GetSection("MyConfig")["ConfigA"];
调用单个值var mySection = this.Configuration.GetSection("MyConfig")["ConfigA"];
,这是多余的,但说明它仅用于检索基元。
要绑定到C#对象并注入它们,我创建了以下扩展方法:
public static class IServiceCollectionExtensions { public static IServiceCollection AddConfigOptions(this IServiceCollection services, IConfiguration configuration, string section) where TOptions : class, new() { services.Configure (configuration.GetSection(section)); services.AddSingleton(cfg => cfg.GetService>().Value); return services; } }
可以像这样调用:
public class Startup { public Startup(IConfiguration configuration) => Configuration = configuration; public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddConfigOptions(Configuration, "Email")
并注入如下:
public class EmailSender : IEmailSender { private EmailOptions _emailOptions; public EmailSender(EmailOptions options) => _emailOptions = options;
我发现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任务,如下所示:
而这似乎完美无缺。
这显然仅在本地开发期间有用。 但是,现在的一般做法是首先不要在文件中进行配置,特别是因为它最终会成为您的回购历史的一部分。 相反,在部署应用程序时,这几天的两种常见做法是使用环境变量来覆盖您的值,甚至更好地使用像consul这样的键/值存储。
此外,我在网上看到了大量关于如何使用services.Configure<>()
的奇特示例。配置services.Configure<>()
这很好,但Startup.cs
已经使用DI为IConfiguration configuration
注入值。 这意味着IConfiguration
已经在.NET核心的IoC容器中注册,因此这实际上意味着您已经可以在应用程序的任何其他类中使用IConfiguration
,如下所示:
public JobsRepository(IConfiguration configuration) { this.configA = configuration.GetSection("MyConfig:ConfigA").Value; }
在我的情况下,我错过了一个包:
Microsoft.Extensions.Configuration.Binder
事实上它在这里被记录为一个微妙的代码注释
配置现在传递到构造函数的启动。 因为它被注入,它可以在Program.cs中提供给你的app 之前预先准备好。
所以你可以尝试使用Program.cs
public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((context, builder) => { IHostingEnvironment env = context.HostingEnvironment; builder.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); }) .UseStartup() .Build();
希望这可以帮助。
法比安
- Azure Notification Hubs包是否与.NET Core兼容?
- 在.NetCore项目中引用.Net 4.6.2项目(VS2017 15.4.4)
- 尝试使用Content-Type application / x-www-form-urlencoded来访问API
- 无法加载文件或程序集Microsoft.Extensions.DependencyInjection.Abstractions,Version = 1.1.0.0
- 在.NET Core中使用DataTable
- 添加迁移失败,因为未安装EntityFrameworkCore.Tools
- 替换ASP.NET Core内置DI容器中的服务注册?
- 缓存在Identity Server 4中似乎不起作用
- 任何方式来命名相同类型的倍数?