ASP.NET Core: JSON Configuration GetSection returns null

Viewed 16662

I have a file appsettings.json that looks like this:

{
    "MyConfig": {
        "ConfigA": "value",
        "ConfigB": "value"
    }
}

In my Startup.cs I'm building my IConfiguration:

public ConfigurationRoot Configuration { get; set; }

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

      Configuration = builder.Build();
}

public void ConfigureServices(IServiceCollection services)
{
      //GetSection returns null...
      services.Configure<MyConfig>(Configuration.GetSection("MyConfig"));
}

But Configuration.GetSection("MyConfig") always returns null, although the value exists in my JSON file. Configuration.GetSection("MyConfig:ConfigA") works just fine.

What am I doing wrong?

5 Answers

For anyone who happens upon this and is trying to do this same thing in a test project, this is what worked for me:

other = config.GetSection("OtherSettings").Get<OtherSettings>();

Please refer to this below code

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)
    {
        var config = Configuration.GetSection("MyConfig");
        // To get the value configA
        var value = config["ConfigA"];

        // or direct get the value
        var configA = Configuration.GetSection("MyConfig:ConfigA");

        var myConfig = new MyConfig();
        // This is to bind to your object
        Configuration.GetSection("MyConfig").Bind(myConfig);
        var value2 = myConfig.ConfigA;
    }
}

I just ran into this. The values are there if you use the full path, but I needed to auto-bind them to a configuration class.

The .Bind(config) started working after I added auto-property accessors to my class's properties. i.e.

public class MyAppConfig {
  public string MyConfigProperty { get; set;} //this works
  public string MyConfigProperty2; //this does not work
}

This worked for me.

public void ConfigureServices(IServiceCollection services)  
{  
     services.Configure<MyConfig>(con=> Configuration.GetSection("MyConfig").Bind(con));  
}

I am used to use fields instead of properties on my classes and i faced the same issue than you...

Turns out that they need to be properties, otherwise it doesn't complete the values of the class but leaves them as default.

Based on this MSDN article an options class:

  1. Must be non-abstract with a public parameterless constructor.
  2. All public read-write properties of the type are bound.
  3. Fields are not bound. In the preceding code, Position is not bound. The Position property is used so the string "Position" doesn't need to be hard coded in the app when binding the class to a configuration provider.
Related