Skip to content

[API Proposal]: Expose a new Configuration API to help in Null values binding #116700

@tarekgh

Description

@tarekgh

Background and motivation

Currently, the configuration binder does not differentiate between null and missing values—if a configuration value is explicitly set to null, it's treated as if it doesn't exist.

To enable this distinction, we're introducing a new API in the ConfigurationSection class. This API will return the configuration value and explicitly indicate whether the value is present in the configuration or truly missing.

API Proposal

namespace Microsoft.Extensions.Configuration

public class ConfigurationSection : IConfigurationSection
{
    public virtual bool TryGetValue(string? key, out string? value);
}

API Usage

The new API is intended to be used internally by the configuration binder, so user code—such as the example below—won’t require any changes but will start behaving as expected:

            string jsonConfig = @"
            {
                ""NullConfiguration"": {
                    ""StringProperty1"": ""New Value!"",
                    ""StringProperty2"": null,
                    ""StringProperty3"": """",
                    ""IntProperty1"": 42,
                    ""IntProperty2"": null,
                },
            }";

            var configuration = new ConfigurationBuilder()
                        .AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(jsonConfig)))
                        .Build().GetSection("NullConfiguration");

            NullConfiguration result = configuration.Get<NullConfiguration>();


        public class NullConfiguration
        {
            public NullConfiguration()
            {
                // Initialize with non-default value to ensure binding will override these values
                StringProperty1 = "Initial Value 1";
                StringProperty2 = "Initial Value 2";
                StringProperty3 = "Initial Value 3";

                IntProperty1 = 123;
                IntProperty2 = 456;
            }
            public string? StringProperty1 { get; set; }
            public string? StringProperty2 { get; set; }
            public string? StringProperty3 { get; set; }

            public int? IntProperty1 { get; set; }
            public int? IntProperty2 { get; set; }
        }

Details

Today, the binder relies on IConfigurationSection, which does not indicate whether a null return value means the key exists with a null value or is entirely missing. Since we support netfx and netstandard2.0, extending the interface would introduce a breaking change for those platforms which we need to avoid.
To solve this:

  • We’ll enhance the existing public ConfigurationSection class (which implements IConfigurationSection) with the new functionality.
  • The binder will detect if the configuration object is a ConfigurationSection and use the new capability when available.
  • For custom implementations of IConfigurationSection, consumers can subclass ConfigurationSection to gain the new behavior.
  • If needed in the future, we still have the option to introduce a new interface or abstract base class.

Alternative Designs

One option was to expose a new abstract class that extends IConfigurationSection and includes the new API, then have ConfigurationSection inherit from it. However, we prefer to add the new API directly to ConfigurationSection itself, rather than introducing a new class.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions