Lee Reitz
Lee Reitz

Reputation: 105

Configuration section null in Startup but populates in service

I come across some strangeness while debugging another issue and wondering if someone with more knowledgeable could explain. Here is some quick test code (I apologies for any errors)

AppSetting

{  
  "A": {
    "B": 123,
    "C": "ABC"
  }
}

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    var config1 = Configuration.GetSection("A");
    //config1.value <- Null
    var config2 = Configuration.GetSection("A:B");
    //config2.value <- 123
    var config3 = Configuration.GetSection("A:C");
    //config3.value <- "ABC"
    services.Configure<ABC>(config1);
    services.AddTransient<ABCService>();
}

public class ABC
{
    public int B {get;set;}
    public string c {get;set;}
}

public class ABCService
{
        public ABCService(IOptions<ABC> abcConfig)
        {
            //abcConfig.Value.B <- 123
            //abcConfig.Value.C <- "ABC"
        }
}

Why is config1.value null in ConfigureServices but after dependency injection abcConfig in ABCService has values?

Upvotes: 0

Views: 446

Answers (2)

Kirk Larkin
Kirk Larkin

Reputation: 93153

config1.value is null simply because, in your example JSON, there is no value for A. The configuration system works with simple key value pairs. For example, in your built Configuration object, you have the following (key => value):

A =>
A:B => 123
A:C => ABC

You can see this for yourself if you run the following sample code, which generates the output shown above:

Configuration.AsEnumerable()
    .ToList()
    .ForEach(x => Console.WriteLine("{0} => {1}", x.Key, x.Value));

This shows that the value for A is null, which is what you have described. There are values for both A:B and A:C, which are part of the A section as denoted by the : hierarchy separator. When you use services.Configure, it's really just matching anything under A: against your ABC class, where it finds B and C accordingly.

By using GetSection("A"), you've created a different view of your Configuration instance that will only include anything rooted at A. In your example, it's the same in both cases as you only have A.

The docs do a great job of describing how the configuration system works.

Upvotes: 1

Zoxive
Zoxive

Reputation: 116

You can add a constructor to your startup class and put IConfiguration as a dependency. that will be the resolved configuration object. You can then use that in your ConfigureServices method.

You can see an example here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-2.1

Upvotes: 0

Related Questions