396

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

684

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[]>();
9
  • 21
    In my case, Aspnet core 2.1 web app, included these two nuget packages. SO its was just one line change. Thanks Commented Sep 27, 2018 at 13:48
  • 14
    It also works with array of objects, e.g. _config.GetSection("AppUser").Get<AppUser[]>(); Commented Feb 23, 2020 at 13:45
  • 15
    I wonder why they could not make it work by simply using GetValue for that key: Configuration.GetValue<string[]>("MyArray"). Commented Nov 15, 2020 at 8:16
  • 2
    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. Commented Apr 1, 2021 at 19:04
  • 2
    As of .NET 6.0 this works out of the box, no need for adding any nuget Commented Mar 31, 2022 at 7:02
203

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
  • 55
    If you have an array of objects like "Clients": [ {..}, {..} ], you should invoke Configuration.GetSection("Clients").GetChildren().
    – halllo
    Commented Apr 18, 2018 at 17:25
  • 96
    If you have an array of literals like "Clients": [ "", "", "" ], you should invoke .GetSection("Clients").GetChildren().ToArray().Select(c => c.Value).ToArray().
    – halllo
    Commented Apr 18, 2018 at 17:40
  • 18
    This answer will actually produce 4 items, the first being the the section itself with an empty value. It is incorrect. Commented Apr 26, 2018 at 22:32
  • 6
    I successfully invoke it like this: var clients = Configuration.GetSection("Clients").GetChildren() .Select(clientConfig => new Client { ClientId = clientConfig["ClientId"], ClientName = clientConfig["ClientName"], ... }) .ToArray();
    – halllo
    Commented May 14, 2018 at 11:51
  • 3
    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":[{...},{...}]
    – Clarence
    Commented May 23, 2018 at 16:19
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
  • I get an error that it needs a comma between "MySettings" and "MyArray".
    – Markus
    Commented Apr 16, 2019 at 12:16
  • Thanks for the info. I believe this answers the original question best.
    – RobV8R
    Commented Dec 3, 2020 at 20:50
  • 1
    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"}]]
    – joym8
    Commented Feb 3, 2021 at 20:25
  • 2
    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 Commented Feb 28, 2023 at 8:39
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
  • 4
    Exactly what I was looking for, worked like a charm thank you! Commented Feb 27, 2021 at 23:21
  • 2
    Simple and straightforward ! Commented Aug 5, 2021 at 14:10
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" ]
    }
}
33

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>>();
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 };
}
0
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'.

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[]>();
0
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"));
    //...
}
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);
0
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
  • 2
    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.
    – Sau001
    Commented May 16, 2019 at 10:16
  • Thank you This answer correctly handles the case where the value is an empty array, such as MyArray: []
    – AJ Morris
    Commented Aug 9, 2021 at 15:53
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));
    }
}
4
public class MyArray : List<string> { }

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

public SomeController(IOptions<MyArray> myArrayOptions)
{
    myArray = myArrayOptions.Value;
}
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
  • 2
    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. Commented Sep 21, 2020 at 9:06
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>();
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

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;
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/"
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);
}

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.