'IConfiguration.GetSection.Bind returning null when array is present in json environment variables

I'm working with Azure Functions and am having trouble reading in some environment variables (in the form of a json file for local testing). My local.settings.json file that contains some values

{
  "IsEncrypted": false,
  "Values": {
    "TokenValidationSettings:Audience": "AnAudience",
    "TokenValidationSettings:Secret": "ASecret",
    "TokenValidationSettings:ValidIssuers": [ "Issuer1", "Issuer2],
  }
}

I have a C# object that I want to bind that section to, so that I can inject the settings following the IOptions pattern. I've done this before without an array and it hasn't been a problem, but all the values are null when I include the ValidIssuers array in json file.

public class TokenValidationSettings
{
    public string Secret { get; set; }
    public string Audience { get; set; }
    public string[] ValidIssuers { get; set; }
}

In Program.cs I set up the host and services.

    var host = new HostBuilder()
        .ConfigureFunctionsWorkerDefaults()
        .ConfigureServices((hostBuilderContext, services) => services
            .AddLogging()
            .InjectConfigSectionsAsIOptions())
        .Build();

InjectConfigSectionsAsIOptions looks like this.

public static IServiceCollection InjectConfigSectionsAsIOptions(this IServiceCollection services)
{
    services.AddOptions<TokenValidationSettings>().Configure<IConfiguration>((settings, configuration) => {
        configuration.GetSection(nameof(TokenValidationSettings)).Bind(settings);
    });

    return services;
}

Am I going to have to do things a bit more manually here instead of being able to just use GetSection > Bind, or is there something I'm missing?



Solution 1:[1]

Firstly your json is not formatted correctly. Change this line

"TokenValidationSettings:ValidIssuers": [ "Issuer1", "Issuer2],

to this

"TokenValidationSettings:ValidIssuers": [ "Issuer1", "Issuer2"]

Secondly you need to scope down to the section from the top level node. Change this line

configuration.GetSection(nameof(TokenValidationSettings)).Bind(settings);

to this line

configuration.GetSection($"Values:{nameof(TokenValidationSettings)}").Bind(settings);

Lastly, and this part depends on where the json file lives, but if it's a separate json file in your application you need to register it. Here is a simple example.

        public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
                webBuilder.UseConfiguration(new ConfigurationBuilder()
                    .AddJsonFile("local.settings.json").Build());
            });

Happy coding!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Geoffrey Fook