ChatGPT解决这个技术问题 Extra ChatGPT

ASP.NET Core Get Json Array using IConfiguration

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 are my codes above, I got null How to get the array?


R
Ray

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[]>();

This is much more straightforward than the other answers.
This is the best answer by far.
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").
a
ahsteele

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.


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":[{...},{...}]
C
Community

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 :)


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"}]]
D
Dmitry Pavlov

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

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

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" ]
    }
}

B
Bjarki B

DotNet Core 3.1:

Json config:

"TestUsers": 
{
    "User": [
    {
      "UserName": "TestUser",
      "Email": "Test@place.com",
      "Password": "P@ssw0rd!"
    },
    {
      "UserName": "TestUser2",
      "Email": "Test2@place.com",
      "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>>();

j
jaycer

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": "Test@place.com",
  "Password": "P@ssw0rd!"
},
{
  "UserName": "TestUser2",
  "Email": "Test2@place.com",
  "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 };
}

This is awesome
Your answer is perfect.
s
sandy

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[]>();

N
Nateowami

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": "Test@place.com",
    "Password": "P@ssw0rd!"
  },
  {
    "UserName": "TestUser2",
    "Email": "Test2@place.com",
    "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'.


A
Andreas Friedel

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

R
Roland Roos

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);

m
mojtaba karimi

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"}


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: []
V
Vasily Ivanov
public class MyArray : List<string> { }

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

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

N
Ngô Thanh Tùng

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;

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.
K
Kinjal Shah

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;

s
shine

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/"

w
worldwildwebdev

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

L
Lemonseed

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:

https://i.stack.imgur.com/JyUPS.png