C
C#3w ago
Daniel

Inject User and Claims to DbContext using Factory

I've put the last 2 days trying to figure out how to solve a problem which I believe have to do with the combination of Blazor Server, State management and EF Core via Factory. I need to get TenantID from Users Claims to be able to resolve a connection string, dynamically. What I have come up to is that following registering of DbContext does not work when multiple users log in and out within same circuit i Blazor. The connection string is not updated:
builder.Services.AddDbContextFactory<TenantAppContext>((sp, option) =>
{
var tenantHelper = sp.GetRequiredService<ITenantHelper>();
var tenantConnectionString = tenantHelper.GetTenantConnectionString();
if (tenant != null)
{
option.UseSqlServer(tenantConnectionString);
}
});
builder.Services.AddDbContextFactory<TenantAppContext>((sp, option) =>
{
var tenantHelper = sp.GetRequiredService<ITenantHelper>();
var tenantConnectionString = tenantHelper.GetTenantConnectionString();
if (tenant != null)
{
option.UseSqlServer(tenantConnectionString);
}
});
One way I think I can get it to work is by injecting IHttpContextAccessor _httpContextAccessor; into the DbContext and get the claim that way. Would this be okay? according to the majority of the documentation I should use AuthenticationStateProvider but that is not possible to inject to the db context since I can't inject scoped services. In the end I need to add a global query filter to my context
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyGlobalFilter<BaseEntity>(e => !e.IsDeleted && e.TenantId == _helper.GetTenant());

}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyGlobalFilter<BaseEntity>(e => !e.IsDeleted && e.TenantId == _helper.GetTenant());

}
Appreciate any guidance and help solving this in a good way.
1 Reply
Daniel
DanielOP3w ago
If I try to injecy AuthenticationStateProvider into DbContext I get this error: System.InvalidOperationException: 'Cannot resolve scoped service 'Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider' from root provider.'
private AuthenticationStateProvider _AuthenticationStateProvider;

public TenantAppContext(DbContextOptions<TenantAppContext> options, ITenantHelper helper, AuthenticationStateProvider AuthenticationStateProvider) : base(options)
{
_helper = helper;
_AuthenticationStateProvider = AuthenticationStateProvider;
}
private AuthenticationStateProvider _AuthenticationStateProvider;

public TenantAppContext(DbContextOptions<TenantAppContext> options, ITenantHelper helper, AuthenticationStateProvider AuthenticationStateProvider) : base(options)
{
_helper = helper;
_AuthenticationStateProvider = AuthenticationStateProvider;
}

Did you find this page helpful?