Microsoft.Extensions.Configuration has had ConfigurationKeyNameAttribute since .NET 6 which it lets you rename the key a property maps to. But there was never an official way to say "don't bind this property at all." That gap is finally closed in .NET 11 with ConfigurationIgnoreAttribute.
The Problem
Let's say you have an options class that looks roughly like this:
public class CsvIngestionOptions
{
// Computed after load — should NOT come from configuration
public CsvFormatOptions DefaultFormat { get; set; }
// The raw section we bind and process ourselves
public IConfigurationSection? DefaultFormatSection { get; set; }
internal void OnConfigurationLoaded()
{
DefaultFormat = new CsvFormatOptions();
DefaultFormatSection?.Bind(DefaultFormat);
DefaultFormat.EnsureEncodingDefined();
}
}
DefaultFormat is derived from DefaultFormatSection after some post-processing. It should never be populated directly by the binder. But because it has a public getter and setter, the configuration system happily tries to bind it.
The only workaround before .NET 11 was to abuse ConfigurationKeyNameAttribute with an intentionally garbage key:
// The hacky way
[ConfigurationKeyName("__ignored_" + nameof(DefaultFormat))]
public CsvFormatOptions DefaultFormat { get; set; }
That's fragile, misleading, and creates a weird surface in your configuration schema. Not great.
The Fix: ConfigurationIgnoreAttribute
.NET 11 adds a dedicated attribute in Microsoft.Extensions.Configuration:
namespace Microsoft.Extensions.Configuration;
[AttributeUsage(AttributeTargets.Property)]
public sealed class ConfigurationIgnoreAttribute : Attribute { }
Easy peasy. Just add the property now to the property in question that should not be bound:
public class CsvIngestionOptions
{
[ConfigurationIgnore]
public CsvFormatOptions DefaultFormat { get; set; }
[ConfigurationKeyName(nameof(DefaultFormat))]
public IConfigurationSection? DefaultFormatSection { get; set; }
internal void OnConfigurationLoaded()
{
DefaultFormat = new CsvFormatOptions();
DefaultFormatSection?.Bind(DefaultFormat);
DefaultFormat.EnsureEncodingDefined();
}
}
Another Common Scenario
Post-processing is the most obvious use case, but not the only one. A parsed representation of a raw value is another classic:
public class FeatureFlags
{
public string RawFlags { get; set; } = string.Empty;
[ConfigurationIgnore]
public IReadOnlyDictionary<string, bool> ParsedFlags { get; set; }
= new Dictionary<string, bool>();
}
Can't I Just Use [JsonIgnore]?
Nope and this is the catch. System.Text.Json.Serialization.JsonIgnoreAttribute has no effect on the configuration binder.
GitHub
The issue is described here: https://github.com/dotnet/runtime/issues/125111
