配置。 GetSection 始终返回 Value 属性 null

每次调用 Configuration.GetSection时,返回对象的 Value属性始终为 null。

我的 Startup构造函数

public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();


this.Configuration = builder.Build();
}

我的 ConfigureServices方法

public void ConfigureServices(IServiceCollection services)
{
services.Configure<SqliteSettings>(opts => Configuration.GetSection("SqliteSettings").Bind(opts));


services.AddOptions();


services.AddMvc();
}

我的 appsettings.json

{
"SqliteSettings": {
"DataSource": "C:\\db.sqlite",
"NewDatabase": true,
"Version": 3
}
}

我用来定义 SqliteSettings 的类

public class SqliteSettings
{
public string DataSource { get; set; }


public bool? NewDatabase { get; set; }


public int? Version { get; set; }


public string Password { get; set; }


public long? CacheSize { get; set; }


// More properties
}

我认为 JSON 可能需要相同数量的属性来匹配,或者它可能与数据类型定义有关,但是这些可能是完全不相关的。

73956 次浏览

Just modify your ConfigureServices method to be like following:

public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();


services.Configure<SqliteSettings>(Configuration.GetSection("SqliteSettings"));


services.AddMvc();
}

and it should work.

This worked for me in a console application:

var connectionString = config["ConnectionStrings:DefaultConnection"]
var serviceProvider = services.BuildServiceProvider();

must come after all services.Configure calls.

In my case for Web Api Core 2.1, I needed Program.cs in the project root folder (the same folder as Startup.cs).

If you have an appsettings.Development.json file, make sure the "ConnectionStrings:DefaultConnection" settings are the same in both the appsettings.Development.json and appsettings.json files.

  1. Right-click on appsettings.json and go to Properties.
  2. Select Copy to output directory = Copy always.

According to the Microsoft Docs:

When GetSection returns a matching section, Value isn't populated. A Key and Path are returned when the section exists.

If you want to see the values of that section you will need to call the GetChildren() method: Configuration.GetSection("SqliteSettings").GetChildren();

Or you can use: Configuration.GetSection("SqliteSettings").Get<SqliteSettings>(). The JSON does not need to have the same amount of properties to match. Unmatched nullable properties will be set to null and non-nullable unmatched properties will be set to their default value (e.g. int will be set to 0).

Try add ConfigurationProvider to ConfigurationBuilder.

App configuration is provided from:

  • appsettings.json using the File Configuration Provider.
  • appsettings.{Environment}.json using the File Configuration Provider.

If all the other answers do not fix the problem, another reason could be that the properties of the Options class are private (or do not have accessible setters).

My problem was that the .bind() method's object instance was not intialized.

services.Configure<SqliteSettings>(opts => Configuration.GetSection("SqliteSettings").Bind(opts));

So before calling .bind(opts); I initialized the value:

SqlliteSettings opts = new SqliteSettings();

Binded the local settings variable:

Configuration.GetSection(AppSettingsSectionName).Bind(opts);

And did the container registration separately:

services.Configure<AppSettings>(Configuration.GetSection("SqlliteSettings"));

This solved the problem since the .Bind() method will just return null when the instance provided is null.

If your dependency injection is failing and you have concluded that this method is the problem after debugging it, it's not!

This is enough for registration:

services.Configure<SqliteSettings>(Configuration.GetSection("SqliteSettings"));

You have to inject your configuration class in IOptions interface. That will solve the DI issue. I have wasted a few hours on the issue, hope it helps someone else.

Make sure you are not accidentally nesting your variables within the default Logging object. I had been sticking all sorts of variables in the wrong level of brackets (but it was accidentally correct in the default appsettings.json), resulting in mysteriously absent keys/values.

In my case I was using VS Code and .net core 3.x webapp.

I was facing similar issue that GetSection() or Configuraton["Section:KeyName"] returned null, I checked GetSection().Exists() which also returned false.

So I tried Adding configbuilder inside ConfigureServices which helped me fix this,

  public void ConfigureServices(IServiceCollection services)
{
//Initialize the builder
var builder = new ConfigurationBuilder()
.SetBasePath(Environment.CurrentDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true)//To specify environment
.AddEnvironmentVariables();//You can add if you need to read environment variables.


//Build the configuration
IConfiguration Configuration = builder.Build();


       

services.Configure<SqliteSettings>(Configuration.GetSection("SqliteSettings"));
//Similar to below
//services.Configure<EntityClass>(Configuration.GetSection("EntityConfigSection"));
      

}

Note: Please make sure the value cwd and program under .VScode/launch.json has the right values. The code picks the current working directory from the cwd Value so we need to make sure its set correct.

{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "X.X.X",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/<ProjectLocation>/bin/<BuildType>/<Version>/<ProjectDll>",
"args": [],
"cwd": "${workspaceFolder}/<ProjectLocation>",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
}


]}

Make sure you have property accessors on your configuration object, otherwise it won't bind properly. Knowing this would have saved me 2 hours today.

public class MyConfiguration
{
public string ConfigurationOption1; // BAD
public string ConfigurationOption2 { get; set; } // GOOD
}

Make sure you add the code in correct appsettings.json file. There might be multiple appsettings.json files like appsettings.Development.json, appsettings.QA.json depending on the project and thus based on the environment, your code will be executed.