简体   繁体   中英

Configuration.GetSection always returns Value property null

Every time I call Configuration.GetSection , the Value property of the returned object is always null.

My Startup constructor

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

    this.Configuration = builder.Build();
}

My ConfigureServices method

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

    services.AddOptions();

    services.AddMvc();
}

My appsettings.json

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

The class I'm using to define 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
}

I was thinking the JSON might need to have the same amount of properties to match, or is it might be something to do with data type definitions, but maybe those are completely unrelated.

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 (eg int will be set to 0).

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

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.

如果所有其他答案都不能解决问题,另一个原因可能是 Options 类的属性是私有的(或者没有可访问的 setter)。

这在控制台应用程序中对我有用:

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

必须在所有services.Configure调用之后来。

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.

对于 Web Api Core 2.1,我需要项目根文件夹(与 Startup.cs 相同的文件夹)中的Program.cs

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.

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.

如果您有appsettings.Development.json文件,请确保appsettings.Development.jsonappsettings.json文件中的“ConnectionStrings:DefaultConnection”设置相同。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM