Reputation: 359
I need to use entity framework in my custom authorization handler. But it's not working. It fails on runtime. I am getting this error in response body:
<h2 class="stackerror">InvalidOperationException: Cannot consume scoped service 'SomeDbContext' from singleton 'Microsoft.AspNetCore.Authorization.IAuthorizationHandler'.</h2>
I can't inject DB Context like this. How can I use db context in my custom authorization handler?
In my custom authorization handler class:
public class CustomAuthorizationHandler : AuthorizationHandler<CustomAuthRequirement>
{
private readonly SomeDbContext _dbContext;
public CustomAuthorizationHandler(SomeDbContext context)
{
_dbContext = context;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomAuthRequirement requirement)
{
...
//Some datatable read operations with _dbContext
...
}
}
In my Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SomeDbContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));
services.AddSingleton<IAuthorizationPolicyProvider, CustomAuthPolicyProvider>();
services.AddSingleton<IAuthorizationHandler, CustomAuthorizationHandler>();
...
}
Upvotes: 5
Views: 2387
Reputation: 10335
Instead of creating a new scope, I piggybacked off the scope of the HttpContext.
var dbContext = (context.Resource as HttpContext)
?.Features?.Get<IServiceProvidersFeature>()
?.RequestServices.GetRequiredService<SomeDbContext>();
Upvotes: 0
Reputation: 2640
I had the same problem, it turned out all i needed to change was the scope, on startup if you do
services.AddTransient<IAuthorizationHandler, CustomAuthorizationHandler>();
it will probably fix it like it fixed my code, and that way i didn't need to add any extra code
Upvotes: 0
Reputation: 20116
You could just inject IServiceProvider serviceProvider
into the CustomAuthorizationHandler
.Try to use below code:
public class CustomAuthorizationHandler : AuthorizationHandler<CustomAuthRequirement>
{
private readonly IServiceProvider _serviceProvider;
public CustomAuthorizationHandler (IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
CustomAuthRequirement requirement)
{
using (var scope = _serviceProvider.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<SomeDbContext>();
//...
}
}
}
Upvotes: 8