Home > Back-end >  Using Options Pattern for settings .NET Core app not working; settings file always has null properti
Using Options Pattern for settings .NET Core app not working; settings file always has null properti

Time:11-10

I have a straight-forward .NET 6 app using full Program and Startup classes (nothing top-level). I have the following segment in Startup:

IConfigurationSection oauthSection = Configuration.GetSection("OAuth");
services.Configure<OAuthSettings>(oauthSection);
var oauthSettings = oauthSection.Get<OAuthSettings>();

This is OAuthSettings:

public class OAuthSettings
{
    public OAuthSettings()
    {
        CorsAllowedOrigins = new List<string>();
    }

    public string BaseUrl { get; set; }

    public string DefaultSchema { get; set; }

    public IEnumerable<string> CorsAllowedOrigins { get; set; }
}

I'm injecting the IOptions<OAuthSettings> object in another class from an adjacent library (but still part of the DI container), like the below:

private readonly IOptions<OAuthSettings> _oAuthOptions;

public IdentityServerDataProtectionDbContext(
    DbContextOptions<IdentityServerDataProtectionDbContext> options,
    IOptions<OAuthSettings> oAuthOptions)
    : base(options)
{
    _oAuthOptions = oAuthOptions;
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.HasDefaultSchema(_oAuthOptions.Value.DefaultSchema);
}

However, every single time I try to call _oAuthOptions.Value, all of the properties are null, and the implementation is of UnnamedOptionsManager. This is happening despite the fact that oauthSettings in the first snippet resolves the settings just fine, meaning it isn't a problem with deserialization.

Any ideas? Thanks in advance.

CodePudding user response:

Use IOptionsSnapshot<> or IOptionsMonitor<> instead.

This took me way too many hours to figure out, so I wanted to answer my own question here to hopefully prevent someone else the pain.

The documentation for the various Options interfaces explains the issue better than I could (emphasis mine):

IOptions:

  • Does not support:
    • Reading of configuration data after the app has started.
    • Named options
  • Is registered as a Singleton and can be injected into any service lifetime.

IOptionsSnapshot:

  • Is useful in scenarios where options should be recomputed on every injection resolution, in scoped or transient lifetimes. For more information, see Use IOptionsSnapshot to read updated data.
  • Is registered as Scoped and therefore cannot be injected into a Singleton service.
  • Supports named options

IOptionsMonitor:

  • Is used to retrieve options and manage options notifications for TOptions instances.
  • Is registered as a Singleton and can be injected into any service lifetime.
  • Supports:
    • Change notifications
    • Named options
    • Reloadable configuration
    • Selective options invalidation (IOptionsMonitorCache)
  • Related