-
Notifications
You must be signed in to change notification settings - Fork 4.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Microsoft.Extensions.Configuration App binding adding to the initialized Collections, not replacing #46988
Comments
Tagging subscribers to this area: @safern Issue DetailsDescriptionExample Repo: https://github.com/Cazzar/ConfigurationArrayTest The issue itself seems to occur that if you have an initialization for an IEnumerable instead of having the option to Replace the contents on deserialization, it will append to the contents, making it impossible to use a strongly typed configuration instance with defaults in the case that they are not provided. Testing this, it seems to show both a pattern within both System.Net.Json and the Newtonsoft.Json versions of configuration loading. Configuration
Other informationExample output from my repo above:
In this case, I would expect only From further speculation, this might not be specifically bound to the input type but by the Binding options not having the option to replace runtime/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs Lines 423 to 447 in 796cbee
|
@Cazzar Funny I just ran into this too. It seems to be working as designed given there are unit tests for the behavior, for example: Lines 305 to 332 in e3247ad
What I ran into is in the case of public class Test
{
public IReadOnlyCollection<string> ReadOnlyValues { get; set; } = new[] { "default" };
} ...configuration is completely ignored because you can't add to an existing My expectation was that "ReadOnlyValues" would be completely replaced if something was specified in the configuration. |
@CodeBlanch Interesting, even if it was a binding option that might be a reasonable solution, since if you were to use raw JSON parsing, it is possible, at least with Newtonsoft.JSON that you can replace instead of update. I've got a potential workaround idea that I will try later today and update here for the solution. Given that it is an expected pattern, breaking the current API would not be a good idea, I wouldn't be against some sort of binding options. |
Tagging subscribers to this area: @maryamariyan Issue DetailsDescriptionExample Repo: https://github.com/Cazzar/ConfigurationArrayTest The issue itself seems to occur that if you have an initialization for an IEnumerable instead of having the option to Replace the contents on deserialization, it will append to the contents, making it impossible to use a strongly typed configuration instance with defaults in the case that they are not provided. Testing this, it seems to show both a pattern within both System.Net.Json and the Newtonsoft.Json versions of configuration loading. Configuration
Other informationExample output from my repo above:
In this case, I would expect only From further speculation, this might not be specifically bound to the input type but by the Binding options not having the option to replace runtime/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs Lines 423 to 447 in 796cbee
|
@Cazzar this definitely looks like by design and it would be a breaking change to "fix" this. What I might suggest if we wanted to support this scenario would be adding an option to BindingOptions that is something like: Anyway, were you able to find a workaround for this? If not I can help finding one. I think we might be able to close this issue? |
@safern I, unfortunately, couldn't find something that worked well enough for my use-case (though it may also relate to the need of the configuration being serialised back in place which was a dirty bit of code, to begin with). Since I was using it with Given it does look like intended functionality as I mentioned in #46988 (comment) an option within BindingOptions would probably be a good idea in the long run. |
Would you mind submitting a formal API proposal to add that BindingOption as part of this or a new issue? Here are the instructions on how to do that: https://github.com/dotnet/runtime/blob/master/docs/project/api-review-process.md |
Because I would have just referenced this issue, I have updated the above description based off the process @safern |
Thank you, @Cazzar. Based on the proposed API, would it be reasonable that the flag is named something like: |
@safern The behavior right now is to add to the list, if possible, otherwise it does nothing (the readonly case). The behavior we want to enable is to override whatever is there. |
Sorry I mixed up things. You're right. The proposal looks good. |
namespace Microsoft.Extensions.Configuration
{
public partial class BinderOptions
{
// Already exists:
// public bool BindNonPublicProperties { get; set; }
public bool OverrideLists { get; set; }
}
} |
Background and Motivation
When defining a configuration that has some defaulted options that are a
List<T>
or anarray
type we might want to have the ability to provide a default list, but completely replaces the enumerable's contents with what is in the configuration file.Proposed API
namespace Microsoft.Extensions.Configuration { public class BinderOptions { public bool BindNonPublicProperties { get; set; } + public bool OverrideLists { get; set; } } }
Usage Examples
Expanding upon my original repo as a base
Alternative Designs
This gives a similar action to
Newtonsoft.JSON
's ObjectCreationHandling option with the value ofReplace
which when handling an Object when deserializing to a class, it uses a new class with no contents at all.Original issue
Description
Example Repo: https://github.com/Cazzar/ConfigurationArrayTest
To show the issue itself, simply running
dotnet run
should workThe issue itself seems to occur that if you have an initialization for an IEnumerable instead of having the option to Replace the contents on deserialization, it will append to the contents, making it impossible to use a strongly typed configuration instance with defaults in the case that they are not provided.
Testing this, it seems to show both a pattern within both System.Text.Json and the Newtonsoft.Json versions of configuration loading.
Configuration
Other information
Example output from my repo above:
In this case, I would expect only
Item 2
to exist in the arrays, effectively overwriting the bound object with the contents of the configuration.From further speculation, this might not be specifically bound to the input type but by the Binding options not having the option to replace
An initial thought would be for this using Add without clearing the collection first:
runtime/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Lines 423 to 447 in 796cbee
The text was updated successfully, but these errors were encountered: