Am using EF Core 3.1.7 and have implemented some global query filters to control user access to some data in a couple of tables. The query filters need the currently logged in user id (an int in my implementation of identity) which I am holding in a variable within the DBContext class.
I am accessing the HttpContext within the DBContext constructor, via an injected IHttpContextAccessor, but find that sometimes when the DBContext is constructed, via DI (controller => data access service => DBContext), that the claims list for the user is empty and I cannot read the user id - and hence the global query filter fails as the param value is 0.
I don't understand why the following fails sometimes to set CurrentUserId to the current user's id (am certainly logged in). I would have thought that the same IHttpContextAccessor was used all the time and would always contain the current user.
public int CurrentUserId { get; set; }
public MyDbContext(DbContextOptions<MyDbContext> options, IHttpContextAccessor httpContextAccessor
) : base(options)
{
if (httpContextAccessor.HttpContext != null)
{
CurrentUserId = 0;
var claimValue = httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier);
if (claimValue != null)
{
CurrentUserId = Convert.ToInt32(claimValue);
}
}
}
I have broken things down to the simplest scenario to attempt to remove as much clutter as possible but still find that when created the claimValue is sometimes null.
The IHttpContextAccessor is configured in startup using:
services.AddHttpContextAccessor();
And the DBContext is configured like:
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString));