400

In appsettings.json

{
      "MyArray": [
          "str1",
          "str2",
          "str3"
      ]
}

In Startup.cs

public void ConfigureServices(IServiceCollection services)
{
     services.AddSingleton<IConfiguration>(Configuration);
}

In HomeController

public class HomeController : Controller
{
    private readonly IConfiguration _config;
    public HomeController(IConfiguration config)
    {
        this._config = config;
    }
    
    public IActionResult Index()
    {
        return Json(_config.GetSection("MyArray"));
    }
}

There is my code above. I got null. How do I get the array?

20 Answers 20

688

You can install the following two NuGet packages:

using Microsoft.Extensions.Configuration; 
using Microsoft.Extensions.Configuration.Binder;

And then you'll have the possibility to use the following extension method:

var myArray = _config.GetSection("MyArray").Get<string[]>();
Sign up to request clarification or add additional context in comments.

9 Comments

In my case, Aspnet core 2.1 web app, included these two nuget packages. SO its was just one line change. Thanks
It also works with array of objects, e.g. _config.GetSection("AppUser").Get<AppUser[]>();
I wonder why they could not make it work by simply using GetValue for that key: Configuration.GetValue<string[]>("MyArray").
I feel like completely changing how this answer is written. It should start out by saying to use GetSection followed by Get<string[]>. Because that's all most of us need to know. If we're using an old .NET version, then we might need the NuGet packages.
As of .NET 6.0 this works out of the box, no need for adding any nuget
|
205

If you want to pick value of first item then you should do like this-

var item0 = _config.GetSection("MyArray:0");

If you want to pick value of entire array then you should do like this-

IConfigurationSection myArraySection = _config.GetSection("MyArray");
var itemArray = myArraySection.AsEnumerable();

Ideally, you should consider using options pattern suggested by official documentation. This will give you more benefits.

6 Comments

If you have an array of objects like "Clients": [ {..}, {..} ], you should invoke Configuration.GetSection("Clients").GetChildren().
If you have an array of literals like "Clients": [ "", "", "" ], you should invoke .GetSection("Clients").GetChildren().ToArray().Select(c => c.Value).ToArray().
This answer will actually produce 4 items, the first being the the section itself with an empty value. It is incorrect.
I successfully invoke it like this: var clients = Configuration.GetSection("Clients").GetChildren() .Select(clientConfig => new Client { ClientId = clientConfig["ClientId"], ClientName = clientConfig["ClientName"], ... }) .ToArray();
None of these options work for me as the object is coming back null at the point of "Clients" using hallo's example. I am confident the json's well formed as it works with the offset inserted in the string ["item:0:childItem"] in the format "Item":[{...},{...}]
|
94

Add a level in your appsettings.json :

{
  "MySettings": {
    "MyArray": [
      "str1",
      "str2",
      "str3"
    ]
  }
}

Create a class representing your section :

public class MySettings
{
     public List<string> MyArray {get; set;}
}

In your application startup class, bind your model an inject it in the DI service :

services.Configure<MySettings>(options => Configuration.GetSection("MySettings").Bind(options));

And in your controller, get your configuration data from the DI service :

public class HomeController : Controller
{
    private readonly List<string> _myArray;

    public HomeController(IOptions<MySettings> mySettings)
    {
        _myArray = mySettings.Value.MyArray;
    }

    public IActionResult Index()
    {
        return Json(_myArray);
    }
}

You can also store your entire configuration model in a property in your controller, if you need all the data :

public class HomeController : Controller
{
    private readonly MySettings _mySettings;

    public HomeController(IOptions<MySettings> mySettings)
    {
        _mySettings = mySettings.Value;
    }

    public IActionResult Index()
    {
        return Json(_mySettings.MyArray);
    }
}

The ASP.NET Core's dependency injection service works just like a charm :)

4 Comments

I get an error that it needs a comma between "MySettings" and "MyArray".
Thanks for the info. I believe this answers the original question best.
What if instead of simple string array it is an array of arrays? For instance this array of report definitions and I want to retrieve cols array for each report: "reports": [ {"name":"reportA", "id": "1", "cols": [{"order":"1","name":"empid"},{"order":"2","name":"firstname"}]}, {"name":"reportB", "id": "2"}, "cols": [{"order":"1","name":"typeID"},{"order":"2","name":"description"}]]
Perhaps someone comes to this answer but uses modern .NET, you don't need an additional configuration level as IOptions<List<...>> works perfectly in .NET 6, see stackoverflow.com/a/75589607/3936440
81

If you have array of complex JSON objects like this:

{
  "MySettings": {
    "MyValues": [
      { "Key": "Key1", "Value":  "Value1" },
      { "Key": "Key2", "Value":  "Value2" }
    ]
  }
}

You can retrieve settings this way:

var valuesSection = configuration.GetSection("MySettings:MyValues");
foreach (IConfigurationSection section in valuesSection.GetChildren())
{
    var key = section.GetValue<string>("Key");
    var value = section.GetValue<string>("Value");
}

2 Comments

Exactly what I was looking for, worked like a charm thank you!
Simple and straightforward !
51

This worked for me to return an array of strings from my config:

var allowedMethods = Configuration.GetSection("AppSettings:CORS-Settings:Allow-Methods")
    .Get<string[]>();

My configuration section looks like this:

"AppSettings": {
    "CORS-Settings": {
        "Allow-Origins": [ "http://localhost:8000" ],
        "Allow-Methods": [ "OPTIONS","GET","HEAD","POST","PUT","DELETE" ]
    }
}

Comments

34

DotNet Core 3.1:

Json config:

"TestUsers": 
{
    "User": [
    {
      "UserName": "TestUser",
      "Email": "[email protected]",
      "Password": "P@ssw0rd!"
    },
    {
      "UserName": "TestUser2",
      "Email": "[email protected]",
      "Password": "P@ssw0rd!"
    }]
}

Then create a User.cs class with auto properties that corresponds to User objects in the Json config above. Then you can reference Microsoft.Extensions.Configuration.Abstractions and do:

List<User> myTestUsers = Config.GetSection("TestUsers").GetSection("User").Get<List<User>>();

Comments

27

For the case of returning an array of complex JSON objects from configuration, I've adapted @djangojazz's answer to use anonymous types and dynamic rather than tuples.

Given a settings section of:

"TestUsers": [
{
  "UserName": "TestUser",
  "Email": "[email protected]",
  "Password": "P@ssw0rd!"
},
{
  "UserName": "TestUser2",
  "Email": "[email protected]",
  "Password": "P@ssw0rd!"
}],

You can return the object array this way:

public dynamic GetTestUsers()
{
    var testUsers = Configuration.GetSection("TestUsers")
                    .GetChildren()
                    .ToList()
                    .Select(x => new {
                        UserName = x.GetValue<string>("UserName"),
                        Email = x.GetValue<string>("Email"),
                        Password = x.GetValue<string>("Password")
                    });

    return new { Data = testUsers };
}

Comments

19

Kind of an old question, but I can give an answer updated for .NET Core 2.1 with C# 7 standards. Say I have a listing only in appsettings.Development.json such as:

"TestUsers": [
  {
    "UserName": "TestUser",
    "Email": "[email protected]",
    "Password": "P@ssw0rd!"
  },
  {
    "UserName": "TestUser2",
    "Email": "[email protected]",
    "Password": "P@ssw0rd!"
  }
]

I can extract them anywhere that the Microsoft.Extensions.Configuration.IConfiguration is implemented and wired up like so:

var testUsers = Configuration.GetSection("TestUsers")
   .GetChildren()
   .ToList()
    //Named tuple returns, new in C# 7
   .Select(x => 
         (
          x.GetValue<string>("UserName"), 
          x.GetValue<string>("Email"), 
          x.GetValue<string>("Password")
          )
    )
    .ToList<(string UserName, string Email, string Password)>();

Now I have a list of a well typed object that is well typed. If I go testUsers.First(), Visual Studio should now show options for the 'UserName', 'Email', and 'Password'.

Comments

18

In ASP.NET Core 2.2 and later we can inject IConfiguration anywhere in our application like in your case, you can inject IConfiguration in HomeController and use like this to get the array.

string[] array = _config.GetSection("MyArray").Get<string[]>();

Comments

9

You can get the array direct without increment a new level in the configuration:

public void ConfigureServices(IServiceCollection services) {
    services.Configure<List<String>>(Configuration.GetSection("MyArray"));
    //...
}

Comments

7

This worked for me; Create some json file:

{
    "keyGroups": [
        {
            "Name": "group1",
            "keys": [
                "user3",
                "user4"
            ]
        },
        {
            "Name": "feature2And3",
            "keys": [
                "user3",
                "user4"
            ]
        },
        {
            "Name": "feature5Group",
            "keys": [
                "user5"
            ]
        }
    ]
}

Then, define some class that maps:

public class KeyGroup
{
    public string name { get; set; }
    public List<String> keys { get; set; }
}

nuget packages:

Microsoft.Extentions.Configuration.Binder 3.1.3
Microsoft.Extentions.Configuration 3.1.3
Microsoft.Extentions.Configuration.json 3.1.3

Then, load it:

using Microsoft.Extensions.Configuration;
using System.Linq;
using System.Collections.Generic;

ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();

configurationBuilder.AddJsonFile("keygroup.json", optional: true, reloadOnChange: true);

IConfigurationRoot config = configurationBuilder.Build();

var sectionKeyGroups = 
config.GetSection("keyGroups");
List<KeyGroup> keyGroups = 
sectionKeyGroups.Get<List<KeyGroup>>();

Dictionary<String, KeyGroup> dict = 
            keyGroups = keyGroups.ToDictionary(kg => kg.name, kg => kg);

Comments

6

Short form:

var myArray= configuration.GetSection("MyArray")
                        .AsEnumerable()
                        .Where(p => p.Value != null)
                        .Select(p => p.Value)
                        .ToArray();

It returns an array of string:

{"str1","str2","str3"}

2 Comments

Worked for me. Thanks. Using Microsoft.Extensions.Configuration.Binder works too, however I would like to stay away from referencing another Nuget package if a single line of code can do the job.
Thank you This answer correctly handles the case where the value is an empty array, such as MyArray: []
5

You can use Microsoft.Extensions.Configuration.Binder package like this:

In your appsettings.json

{
      "MyArray": [
          "str1",
          "str2",
          "str3"
      ]
}

Create your object to hold your configuration:

 public class MyConfig
 {
     public List<string> MyArray { get; set; }
 }

And in you controller Bind the config:

public class HomeController : Controller
{
    private readonly IConfiguration _config;
    private readonly MyConfig _myConfig = new MyConfig();

    public HomeController(IConfiguration config)
    {
        _config = config;
    }

    public IActionResult Index()
    {
        return Json(_config.Bind(_myConfig));
    }
}

Comments

4
public class MyArray : List<string> { }

services.Configure<ShipmentDetailsDisplayGidRoles>(Configuration.GetSection("MyArray"));

public SomeController(IOptions<MyArray> myArrayOptions)
{
    myArray = myArrayOptions.Value;
}

Comments

4

appsettings.json:

"MySetting": {
  "MyValues": [
    "C#",
    "ASP.NET",
    "SQL"
  ]
},

MySetting class:

namespace AspNetCore.API.Models
{
    public class MySetting : IMySetting
    {
        public string[] MyValues { get; set; }
    }

    public interface IMySetting
    {
        string[] MyValues { get; set; }
    }
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.Configure<MySetting>(Configuration.GetSection(nameof(MySetting)));
    services.AddSingleton<IMySetting>(sp => sp.GetRequiredService<IOptions<MySetting>>().Value);
    ...
}

Controller.cs

public class DynamicController : ControllerBase
{
    private readonly IMySetting _mySetting;

    public DynamicController(IMySetting mySetting)
    {
        this._mySetting = mySetting;
    }
}

Access values:

var myValues = this._mySetting.MyValues;

1 Comment

This looks correct. But the option pattern (as microsoft calls it) doesn't require an interface in the option class. You can get your options via injecting an IOptions<T> instead of adding the overhead of a singleton.
4

I found this simpler after the IOptions didn't work and much less to do when serializing.

//appsettings.json
"DatabaseModelCreationOptions": {
    "Users": [
      {
        "Id": "1",
        "UserName": "adminuser",
        "Email": "[email protected]",
        "Password": "!Ch4",
        "Player": "Admin",
        "PlayerInitials": "ADMIN",
        "ApiKey": "40753ey"
      }
    ],   
    "UserRoles": [
      {
        "Id": "af9986df",
        "Name": "Admin",
        "ConcurrencyStamp": "ddd53170"
      },
      {
        "Id": "03b82b0e",
        "Name": "Manager",
        "ConcurrencyStamp": "65da3f89"
      }
    ]
}

Class I needed, I shouldn't need to show you the nested class properties, you can see them above.

public class DatabaseModelCreationOptions
{
    public IEnumerable<User>? Users { get; set; }
    public IEnumerable<UserRole>? UserRoles { get; set; }
}

Then just invoke GetSection("").Get

var dbOptions = configuration.GetSection("DatabaseModelCreationOptions")
    .Get<DatabaseModelCreationOptions>();

Comments

1

Recently I also had a need to read a simple array of strings from an appsettings.json file (and other similar .json configuration files).

For my approach, I created a simple extension method that does the trick:

public static class IConfigurationRootExtensions
{
    public static string[] GetArray(this IConfigurationRoot configuration, string key)
    {
        var collection = new List<string>();
        var children = configuration.GetSection(key)?.GetChildren();
        if (children != null)
        {
            foreach (var child in children) collection.Add(child.Value);
        }
        return collection.ToArray();
    }
}

The original poster's .json file looked as follows:

{
      "MyArray": [
          "str1",
          "str2",
          "str3"
      ]
}

Using the above extension method, it makes reading this array a very simple one-line affair, as seen in the following example:

var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
string[] values = configuration.GetArray("MyArray");

At runtime, setting a breakpoint with a 'QuickWatch' on values verifies that we have successfully read the values from the .json configuration file into a string array:

QuickWatch on values context

Comments

1

To get all values of all sections from appsettings.json

        public static string[] Sections = { "LogDirectory", "Application", "Email" };
        Dictionary<string, string> sectionDictionary = new Dictionary<string, string>();

        List<string> sectionNames = new List<string>(Sections);
        
        sectionNames.ForEach(section =>
        {
            List<KeyValuePair<string, string>> sectionValues = configuration.GetSection(section)
                    .AsEnumerable()
                    .Where(p => p.Value != null)
                    .ToList();
            foreach (var subSection in sectionValues)
            {
                sectionDictionary.Add(subSection.Key, subSection.Value);
            }
        });
        return sectionDictionary;

Comments

1

setting.json file:

{
    "AppSetting": {
        "ProfileDirectory": "C:/Users/",
        "Database": {
            "Port": 7002
        },
        "Backend": {
            "RunAsAdmin": true,
            "InstallAsService": true,
            "Urls": [
                "http://127.0.0.1:8000"
            ],
            "Port": 8000,
            "ServiceName": "xxxxx"
        }
    }
}

code

code:

public static IConfigurationRoot GetConfigurationFromArgs(string[] args, string cfgDir)
{
    var builder = new ConfigurationBuilder()
            .SetBasePath(cfgDir)
            .AddCommandLine(args ?? new string[0]) // null  in UnitTest null will cause exception
            .AddJsonFile(Path.Combine(cfgDir, "setting.json"), optional: true, reloadOnChange: true)
            .AddEnvironmentVariables()
        // .AddInMemoryollection(configDictionary)
        ;
    var config = builder.Build();
    return config;
}

you can use services.AddOptions<AppSettingOption>("AppSetting") or directly get Object from IConfigurationRoot object.

var cfg = GetConfigurationFromArgs(args, appDataDirectory);
cfg.GetSection("AppSetting").Get<AppSettingOption>()

Output:

{App.AppSettingOption}
    Backend: {App.BackendOption}
    Database: {App.DatabaseOption}
    ProfileDirectory: "C:/Users/"

Comments

0

A different approach that works with objects in .Net Core 7.x

In appsettings.json:

{
      "People": [
          { "FirstName": "Glen", "LastName": "Johnson", "Age": 30 },
          { "FirstName": "Matt", "LastName": "Smith", "Age": 40 },
          { "FirstName": "Fred", "LastName": "Williams", "Age": 50 }
      ]
}

Person class:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

And in code:

var appConfig = App.Current.AppConfiguration;   // Or could be passed in through DI
var children = appConfig.GetSection("People")
    .GetChildren()
    .ToList();

var people = new List<Person>();
foreach (var child in children)
{
    var rec = new Person
    {
        FirstName = appConfig[$"{child.Path}:FirstName"],
        LastName = appConfig[$"{child.Path}:LastName"],
        Age = int.Parse(appConfig[$"{child.Path}:Age"]),
    };
    people.Add(rec);
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.