dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.24k stars 4.73k forks source link

Double Array members with Microsoft.Extensions.Configuration.Get and Records #99080

Closed bartkemps closed 8 months ago

bartkemps commented 8 months ago

Description

I'm using records for my configuration / option classes. This worked fine until I decided to add an array: now the content of the array is doubled. I'm guessing array members are added in the constructer and later again though reflection.

Reproduction Steps

In a .net 8 web api application (at least, that's what I'm using) add an options record:

public record MyOptions ( int Foo, string[] Bar);

Add appsetings.json

{ MySettings: { Foo: 1, Bar: ["Fizz", "Buzz"]}

Add Program.cs:

var builder = WebApplication.CreateBuilder(args);
var myOptions = builder.Configuration.GetSection("MySettings").Get<MyOptions>()
// set a breakpoint here to inspect the value of myOptions
services.AddScoped(_=>Options.Create(vbpApiOptions));

NOTE: this does not work either because an empty constructor is expected. This should be fixed too.

services.Configure<VbpApiOptions>("AppSettings", configuration);

Expected behavior

The value of myOptions.Bar should be string[] {"Fizz", "Buzz"}

Actual behavior

The value of myOptions.Bar is string[] {"Fizz", "Buzz", "Fizz", "Buzz"}

Regression?

No response

Known Workarounds

Configuration

No response

Other information

No response

ghost commented 8 months ago

Tagging subscribers to this area: @dotnet/area-extensions-options See info in area-owners.md if you want to be subscribed.

Issue Details
### Description I'm using records for my configuration / option classes. This worked fine until I decided to add an array: now the content of the array is doubled. I'm guessing array members are added in the constructer and later again though reflection. ### Reproduction Steps In a .net 8 web api application (at least, that's what I'm using) add an options record: ``` public record MyOptions ( int Foo, string[] Bar);` ``` Add appsetings.json ``` { MySettings: { Foo:1, Bar[] {"Fizz", "Buzz" }} ``` Add Program.cs: ``` var builder = WebApplication.CreateBuilder(args); var myOptions = builder.Configuration.GetSection("MySettings").Get() // set a breakpoint here to inspect the value of myOptions services.AddScoped(_=>Options.Create(vbpApiOptions)); ``` _NOTE: this does not work either because an empty constructor is expected. This should be fixed too._ ``` services.Configure("AppSettings", configuration); ``` ### Expected behavior The value of `myOptions.Bar` should be `string[] {"Fizz", "Buzz"}` ### Actual behavior The value of `myOptions.Bar` should be `string[] {"Fizz", "Buzz", "Fizz", "Buzz"}` ### Regression? _No response_ ### Known Workarounds * Don't use arrays where repeated values cause problems. * Don't use record types ### Configuration _No response_ ### Other information _No response_
Author: bartkemps
Assignees: -
Labels: `area-Extensions-Options`
Milestone: -
bartkemps commented 8 months ago

This may be the same issue as this one: https://github.com/dotnet/runtime/issues/83803

tarekgh commented 8 months ago

Yes this is a duplicate of https://github.com/dotnet/runtime/issues/83803. The work around is not using record for now.