5

Let's say I have a config.json like this:

{
  "CustomSection": {
    "A": 1,
    "B": 2
  }
}

I know I can use an IConfiguration object to get specific settings, i.e., configuration.Get("CustomSection:A"), but can I grab the whole hierarchy (in any type - even a raw string would be fine)? When I try configuration.Get("CustomSection"), I get a null result, so I think this isn't supported by default.

My use case is grabbing entire configuration dictionaries at once without having to grab each individual setting - some properties may not be known at compile time.

3
  • what type of online searching have you done.. here is an example from Dylan/JsonConfig GitHub Commented Aug 10, 2015 at 21:33
  • @MethodMan That's an interesting library, but I'm looking for something that can work with the built-in IConfiguration framework in ASP.NET 5. Basically I'm not so concerned with parsing the section I get out of the config so much as I want to know how to retrieve it in the first place. Commented Aug 10, 2015 at 21:36
  • 1
    Example: services.Configure<TypeHandlingCustomSection>(Configuration.GetConfigurationSection("CustomSection")); Commented Aug 10, 2015 at 21:36

6 Answers 6

4

I have solved a similar problem where I wanted to bind the entire IConfigurationRoot or IConfigurationSection to a Dictionary. Here is an extension class:

public class ConfigurationExtensions
{
    public static Dictionary<string, string> ToDictionary(this IConfiguration config, bool stripSectionPath = true)
    {
        var data = new Dictionary<string, string>();
        var section = stripSectionPath ? config as IConfigurationSection : null;
        ConvertToDictionary(config, data, section);
        return data;
    }

    static void ConvertToDictionary(IConfiguration config, Dictionary<string, string> data = null, IConfigurationSection top = null)
    {
        if (data == null) data = new Dictionary<string, string>();
        var children = config.GetChildren();
        foreach (var child in children)
        {
            if (child.Value == null)
            {
                ConvertToDictionary(config.GetSection(child.Key), data);
                continue;
            }

            var key = top != null ? child.Path.Substring(top.Path.Length + 1) : child.Path;
            data[key] = child.Value;
        }
    }
}

And using the extension:

IConfigurationRoot config;
var data = config.ToDictionary();
var data = config.GetSection("CustomSection").ToDictionary();

There is an optional parameter (stripSectionPath) to either retain the full section key path or to strip the section path out, leaving a relative path.

var data = config.GetSection("CustomSection").ToDictionary(false);
Sign up to request clarification or add additional context in comments.

Comments

2

configuration.Get is for getting a value to get a section you need

IConfiguration mysection = configuration.GetConfigurationSection("SectionKey");

2 Comments

I saw this method, but it returns another IConfiguration object; is there a way to enumerate all key/value pairs from an IConfiguration? I've seen the strongly typed example at weblog.west-wind.com/posts/2015/Jun/03/… but I'm looking for something more dynamic.
I'm not aware of a way to enumerate, you can get the sub key values using get but you have to know the keys unless you map the section to a type as far as I know.
1

I was able to load and bind multiple sub sections with unknown keys like this (the syntax has changed slightly since your post; I recommend keeping an eye on the github project and their unit tests to see how it is currently working):

var objectSections = Configuration.GetSection("CustomObjects").GetChildren();
var objects = objectSections.ToDictionary(x => x.Key, x =>
{
    var obj = new CustomObject();
    ConfigurationBinder.Bind(x, obj);
    return obj ;
});

Comments

1

Edit: updating this answer for the 1.0 release of Core.

This is possible now if you use a strongly typed object, for example:

public class CustomSection 
{
   public int A {get;set;}
   public int B {get;set;}
}

//In Startup.cs
services.Configure<CustomSection>(Configuration.GetSection("CustomSection"));
//You can then inject an IOptions instance
public HomeController(IOptions<CustomSection> options) 
{
    var settings = options.Value;
}

Comments

1

For a detailed explanation, see https://dotnetcodr.com/2017/01/20/introduction-to-asp-net-core-part-3-the-configuration-file/

Below is an example from the site:

Config file has this:

"Languages": {
  ".NET": [ "C#", "VB.NET", "F#" ],
  "JVM": ["Java", "Scala", "Clojure"]
}

Load this configuration as follows:

IConfigurationSection languagesSection = configRoot.GetSection("Languages");
IEnumerable<IConfigurationSection> languagesSectionMembers = languagesSection.GetChildren();
Dictionary<string, List<string>> platformLanguages = new Dictionary<string, List<string>>();
foreach (var platform in languagesSectionMembers)
{
    List<string> langs = (from p in platform.GetChildren() select p.Value).ToList();
    platformLanguages[platform.Key] = langs;
}

Comments

0

You can use the ConfigurationBinder and read everything as Dictionary<string, string>

Here are some test cases that you can use as example: https://github.com/aspnet/Configuration/blob/dev/test/Microsoft.Framework.Configuration.Binder.Test/ConfigurationCollectionBindingTests.cs

1 Comment

ConfigurationBinder is broken and what worse it won't be fixed. It cannot handle correctly arrays for example, instead of assigment it concatenates arrays.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.