首页 > 解决方案 > 将 AuthenticationStateProvider 注入 IDbContextFactory

问题描述

我想将 AuthenticationStateProvider 注入 DatabaseContext。我的代码如下所示:

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();

    services.AddDbContextFactory<DatabaseContext>(options =>
    {
        options.UseSqlServer(Configuration.GetConnectionString("MyCon"));
        options.EnableSensitiveDataLogging();
    });

    services.AddScoped<DatabaseContext>(p =>
        p.GetRequiredService<IDbContextFactory<DatabaseContext>>()
        .CreateDbContext());

    services.AddIdentity<User, Role>()
        .AddEntityFrameworkStores<DatabaseContext>()
        .AddDefaultTokenProviders()
        .AddErrorDescriber<MultilanguageIdentityErrorDescriber>();

}

public DatabaseContext : IdentityDbContext
{
    private readonly AuthenticationStateProvider _authenticationStateProvider;

    public DatabaseContext(DbContextOptions options, AuthenticationStateProvider authenticationStateProvider)
    {
        _authenticationStateProvider = authenticationStateProvider;
    }
}

一旦我启动应用程序,我就会遇到以下错误:

InvalidOperationException:无法从根提供程序解析范围服务“Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider”。在 Startup.cs

{ options.UseSqlServer(Configuration.GetConnectionString("MyCon"));
  options.EnableSensitiveDataLogging();
});
services.AddScoped<DatabaseContext>(p =>
    p.GetRequiredService<IDbContextFactory<DatabaseContext>>()
    .CreateDbContext());

我做错了什么?

谢谢你的帮助!

标签: c#entity-framework-coreblazor

解决方案


我找到了解决方案!在我看来,这是错误!问题是因为 services.AddDbContextFactory 注册为 Singleton。我创建了自己的 IDbContext 工厂实现并将其注册为 Scoped。在此更改之后,一切都完美无缺。当我将 DbContextFactory 的注册范围更改为单例时,出现错误:GetAuthenticationStateAsync 在 SetAuthenticationState 之前被调用。

我的 DbContextFactory

public class BlazorContextFactory<TContext> : IDbContextFactory<TContext> where TContext : DbContext
    {
        private readonly IServiceProvider provider;

        public BlazorContextFactory(IServiceProvider provider)
        {
            this.provider = provider;
        }

        public TContext CreateDbContext()
        {
            if (provider == null)
            {
                throw new InvalidOperationException(
                    $"You must configure an instance of IServiceProvider");
            }

            return ActivatorUtilities.CreateInstance<TContext>(provider);
        }
    }

我的创业

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped<ApplicationDbContext>();
            services.AddScoped<IDbContextFactory<ApplicationDbContext>, BlazorContextFactory<ApplicationDbContext>>();

            services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
            services.AddSingleton<WeatherForecastService>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }
    }

推荐阅读