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)