ASP.net Core 2.0 Preview配置中的appsettings.json获取null

编程入门 行业动态 更新时间:2024-10-25 10:27:37
本文介绍了ASP Core 2.0 Preview配置中的appsettings.json获取null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我试图从Startup.cs中的注入配置中调用GetSection. 值是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"];

解决方案

我首先检查一下 1.1.1 和 2.x of JsonConfigurationProvider.cs,这是最终从JSON文件构造可检索值的内部代码.对该代码或您最终this.Configuration.GetSection("MyConfig");最终调用的其他任何代码都没有任何更改.

检索值的工作方式是Configuration将按照代码中的定义以相反的顺序在每个配置提供程序 中寻找密钥MyConfig,直到找到一个值为止.在您的示例中,在Webhost.CreateDefaultBuilder() (请参阅此处).

查看 JsonConfigurationFileParser.cs ,它为键和值(,但仅对于原始值)构建了Dictionary<string, string> .也就是说,没有存储MyConfig的键(在这个级别上它是一个对象),但是会有MyConfig:ConfigA的键,并且数组值看起来像MyConfig:ConfigA:0,MyConfig:ConfigA:1等.

最后,您会发现Configuration.GetSection("MyConfig") 始终会为您返回一个新构造的 ConfigurationSection,该构造绝不为空,最糟糕的是会具有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;

I was trying to call GetSection from injected configuration in the Startup.cs. The Value was null, while indexer to a concrete section value returns non-null value. It seems to me a bug behind the GetSection method or I am wrong with it?

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

解决方案

I first checked to see if there were any changes between 1.1.1 and 2.x of JsonConfigurationProvider.cs, the internal code that ultimately constructs retrievable values from your JSON file. There were no changes to this or any of the other code that ultimately gets called by your this.Configuration.GetSection("MyConfig");.

The way retrieving values works is that the Configuration will look for your key MyConfig in each config provider in reverse order as defined in code until a value is found. In your example, providers (json, envionment variables, command line args) are provided within Webhost.CreateDefaultBuilder() (see here).

Looking at the code for JsonConfigurationFileParser.cs, it builds a Dictionary<string, string> for keys and values, but only for primitive values. That is, no key is stored for MyConfig (at this level it is an object), but there will be a key for MyConfig:ConfigA, and array values would look like MyConfig:ConfigA:0, MyConfig:ConfigA:1, etc.

Lastly, you will find that Configuration.GetSection("MyConfig") always returns you a newly constructed ConfigurationSection that is never null, and at the very worst will have a Value property of null.

So what happens when you hover over a ConfigurationSection with Intellisense and look at the Value property is that every config provider had been searched and none was found to have a key of "MyConfig" with a primitive value converted to string to return.

You will at the very least need to call:

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

to have it injected throughout your app as a C# object. Otherwise, call individual values with the colon ["MyConfig:ConfigA"] separator syntax or with var mySection = this.Configuration.GetSection("MyConfig")["ConfigA"];, which is redundant but illustrates it is only used to retrieve primitives.

To bind to C# objects and inject them, I created the following extension method:

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; } }

which can be called like this:

public class Startup { public Startup(IConfiguration configuration) => Configuration = configuration; public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddConfigOptions<EmailOptions>(Configuration, "Email")

and injected like this:

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

更多推荐

ASP.net Core 2.0 Preview配置中的appsettings.json获取null

本文发布于:2023-11-02 15:05:06,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1552716.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Core   ASP   net   json   null

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!