c# - 如何在 ASP.NET Core 5 运行时动态重新配置服务?

标签 c# entity-framework asp.net-core dependency-injection

我在我的网络应用程序中使用 Google 身份验证,并且 OAuth key 当前在 ConfigureServices 中硬编码:

services.AddAuthentication()
    .AddGoogle(options =>
    {
        options.ClientId = "my-client-id";
        options.ClientSecret = "my-client-secret";
    });
但是,我想让站点管理员有机会从 Web 应用程序的设置页面更改 ClientId 和 ClientSecret,最好不必重新启动服务器。
为此,当用户在设置页面上点击“保存”时,我必须以某种方式触发 Google 服务和 GoogleOptions 对象的重新配置。这就是我遇到的麻烦。另外,我想将这些设置存储在 EF Core DbContext 中,而不是物理配置文件中。
到目前为止,我已经尝试将设置移动到实现 IPostConfigureOptions 的单独类中。这应该允许我注入(inject)我的数据库上下文,因为根据文档, PostConfigure 应该在所有其他配置发生后运行。设置已从这个新类正确加载,但数据库上下文的注入(inject)失败,并出现以下异常:
System.InvalidOperationException: Cannot consume scoped service 'AppDatabase' from singleton 'IOptionsMonitor`1[GoogleOptions]'
这很奇怪,因为 ConfigureGoogleOptions 注册为 Scoped,而不是 Singleton。
这是我的选项类:
public class ConfigureGoogleOptions : IPostConfigureOptions<GoogleOptions>
{
    private readonly AppDatabase database;

    public ConfigureGoogleOptions(AppDatabase database)
    {
        this.database = database;
    }
    
    public void PostConfigure(string name, GoogleOptions options)
    {
        options.ClientId = "my-client-id.apps.googleusercontent.com";
        options.ClientSecret = "my-client-secret";
    }
}
并在 ConfigureServices 中注册:
services.AddScoped<IPostConfigureOptions<GoogleOptions>, ConfigureGoogleOptions>();
即使数据库注入(inject)有效,还有第二个问题。 PostConfigure我的类中的函数只在应用程序启动后被调用一次,并且再也不会被调用。我假设它将设置缓存在某处,我不知道如何使此缓存无效或禁用,以便我可以动态提供值。
简短摘要/tl;博士:
我想从我自己的数据库中加载 Google OAuth 服务的 ClientId 和 ClientSecret 设置,并且我希望能够在服务器运行时动态更改它们。

最佳答案

在内部,谷歌处理程序将使用 IOptionsMonitor<GoogleOptions>获取 GoogleOptions 一次或者直到它被重新加载(例如从配置文件绑定(bind)选项并保存文件将触发重新加载)。 IOptionsMonitor内部将使用 IOptionsMonitorCache并且这个缓存被注册为单例。因此,您从 IOptionsMonitor<GoogleOptions> 获得的选项实例与 AuthenticationHandler<GoogleOptions>.Options 相同(引用)它用于处理程序内部的各种操作。如果使用该选项,即使是其他代码也应该正确地从 IOptionsMonitor<GoogleOptions> 获取它。 .
所以要在运行时更改选项,就像这样简单:

//inject the IOptionsMonitor<GoogleOptions> into _googleOptionsMonitor;
var runtimeOptions = _googleOptionsMonitor.Get(GoogleDefaults.AuthenticationScheme);
//you change properties of runtimeOptions here
//...
这里的重点是我们需要使用 GoogleDefaults.AuthenticationScheme作为获得正确选项实例的关键。 IOptionsMonitor.CurrentValue将使用 Options.DefaultName 的默认 key (这是一个空字符串)。

关于c# - 如何在 ASP.NET Core 5 运行时动态重新配置服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66791061/

相关文章:

c# - 在类中存储不同泛型类型的列表

entity-framework - 将 ChangeTracker 与 EntityState.Modified 结合使用

c# - 如何在 Entity Framework 中查询名字和姓氏?

c# - EF code first many to many with payload, compound key or surrogate key

c# - 为什么我的工具提示不显示它的提示?

c# - 编辑 winForm VS2012 时丢失 UserControl

c# - 类型转换会创建新对象吗?

c# - ASP.NET Core - 提供静态文件

c# - Entity Framework 核心 : Update relation with Id only without extra call

asp.net-core - 获取注入(inject)的 IOptions<AppSettings>