Search code examples
c#.net-coreconfigurationmanager

.net core 7: get a list with null-values from appsettings


I'm using dotnet core 6/7 and try to bind a list of Settings.

Imagine the following appsettings:

{
  "parameters": [
    null,
    null,
    {
       "name": "test"
    }
  ]
}

together with the following models:

public class ParameterDefinition : List<Parameter?> {}

public class Parameter {
  public string Name { get; set; }
}

which are configured somewhere in the ConfigureServices-Section:

services.Configure<ParameterDefinition>(Configuration.GetSection("parameters"));

The ConfigurationProvider shows the correct entries like:

"parameters:0": "",
"parameters:1": "",
"parameters:2:name": "test"

When getting the configuration via dependency injection (IOptions<ParameterDefinition>) the ParameterDefinition only contains one element, but it should have three, were the first two of them are null.

How can I correctly get the List including the null-values?


Solution

  • As you pointed out, the ConfigurationProvider holds all entries; the null ones have become an empty string. These somewhere get lost when being processed towards a settings class.

    To work around the issue:

    1. Declare that Parameter class as a struct.
    public struct Parameter
    {
        public Parameter()
        { }
    
        public string Name { get; set; } = default!;
    }
    

    UPDATE: As from your comment on this post, this suffices to solve the issue.

    Below steps 2 and 3 are optional. Leaving these here for future reference, in case someones settings model looks similar.


    1. Change the ParameterDefinition class from being/inheriting a List<T> to a class having an array (or List<T>) property of type Parameter?.
    public class ParameterDefinition
    {
        public Parameter?[] Parameters { get; set; } = default!;
    
        // Or public List<Parameter?> Parameters { get; set; } = default!;
    
    }
    
    1. Register the IOptions<ParameterDefinition> as below. The json structure can stay as-is.
    services.AddOptions<ParameterDefinition>().BindConfiguration("");
    

    Since you don't have a "ParameterDefinition" element/section in your json setup, an empty string is passed to BindConfiguration.

    Alternatively, you can call the Configure method that you are already using, but that does require an additional ParameterDefinition json wrapper element/section.

    services.Configure<ParameterDefinition>(Configuration.GetSection("ParameterDefinition"));
    
    "ParameterDefinition": {
      "Parameters": [
        {
          "Name": "test"
        },
        null,
        null
      ]
    }
    

    Now when an IOptions<ParameterDefinition> instance gets injected, it will hold 3 items; 1 Parameter instance and 2 null values.

    enter image description here