runtime: Binding to non-null IEnumerable doesn't work

AB#1277574 When using the binding feature in the config system, for IEnumerable collections that have a default, non-null value, the collection is never assigned into the target model. For example:

For this json:

{
  "config": {
    "data": [ "a", "b" ]
  }
}

and this application code:

 public class Config
    {
        IEnumerable<string> _data = new List<string>();
        public IEnumerable<string> Data
        {
            get
            {
                return _data;
            }
            set
            {
                _data = value;
            }
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            var config = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("test.json")
                .Build();

            var val = config.GetSection("config").Get<Config>();
            Console.WriteLine(val?.Data?.Count());
        }
    }

The output is:

0
Press any key to continue . . .

I’d expect it to print “2”.

I’d argue the issue is in BindInstance and explicit handling for IEnumerable should be made (much like the check for IsArray https://github.com/aspnet/Configuration/blob/dev/src/Microsoft.Extensions.Configuration.Binder/ConfigurationBinder.cs#L281).

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 24 (17 by maintainers)

Commits related to this issue

Most upvoted comments

Hi @maryamariyan . Yes very happy to have another crack at this one. Will be great to get it done!

I have the same problem, and use this workaround to avoid analyzer complaint:

public class Config
{
    public IEnumerable<string> Data { get; set; } = null!;
}

But I agree to solve this. No one would understand to make it work without complain from analyzer.

This is my first PR on this repo and I’m stumbling around like a newborn Giraffe!

Not a problem. I’ve pinged you in discord, also feel free to post your questions here if you rather keep them in the open.

@safern thank you for your kind offer of help - I will take you up on that; any idea re. this? https://discord.com/channels/732297728826277939/732297728826277942/839396094618238996

This is my first PR on this repo and I’m stumbling around like a newborn Giraffe!

I’d like to look at this if it’s still ‘up-for-grabs’?

For .NET 5.0: https://github.com/dotnet/runtime/blob/master/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs#L327 For .NET Core 3.1.8: https://github.com/dotnet/extensions/blob/v3.1.8/src/Configuration/Config.Binder/src/ConfigurationBinder.cs#L328

@lbogdanov basically this is never going to be fixed because the team doesn’t care enough to do it. Instead of fixing bugs they would rather just keep piling on new features, because bugs are boring and don’t get blog posts written about them.

Can you handle the non-null and non empty collection case too?

e.g. IEnumerable<string> _data = new[] { “c” };

The Config data can have default value if it does not exist in the JSON and can be overwritten if it exists in the JSON.

I find this problem when I try to bind the IdentityServer4 Client

For version 1.5.2, the allowedGrantTypes is IEnumerable and has default value (it is changed to ICollection in latest dev version). I try to put the client settings in the JSON file but the AllowedGrantTypes can’t be overwritten because it is IEnumerable with default value. It works find if the IEnumberable is null or if it is ICollection

    private IEnumerable<string> _allowedGrantTypes = GrantTypes.Implicit; 

We could treat a non-null but empty collection as something that we add to. This way an empty collection would be treated the same as a null collection.