I have an asp.net-core, Blazor Server Side application, using entity framework core for database operations, and microsoft identity for authentication.
I am trying to get the current user in my application, and then access the user object directly from my DbContext.
I added the DbContext as a service
// Program.cs
builder.Services.AddDbContext<DataContext>(options =>
{
options.UseSqlServer(connectionString);
});
Then used constructor injection to get the httpcontext, and set the user object
// Constructor injection
public DataContext(IHttpContextAccessor httpContextAccessor)
{
// Find the current user
var userId = httpContextAccessor.HttpContext.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
CurrentUser = this.Users.Where(x => x.Id == userId).Include(x => x.Location).FirstOrDefault();
}
This works fine, until I refresh the page. When I do, the httpcontext gets reset, and is unable to find the current user. Is there a way to get around this problem, or another way to achieve this?
You could store and fetch the userid
from the LocalStorage if you want this value to persist during refresh.
If the user reloads the page or closes and re-opens the browser, the state persists. If the user opens multiple browser tabs, the state is shared across the tabs. Data persists in localStorage until explicitly cleared.
Take a look at the Service Lifetimes. What your experiencing is the default behavior for a scoped service.
In the following component scenarios on the client, scoped services are reconstructed because a new circuit is created for the user:
- The user closes the browser's window. The user opens a new window and navigates back to the app.
- The user closes a tab of the app in a browser window. The user opens a new tab and navigates back to the app.
- The user selects the browser's reload/refresh button.
You could also define your service as a Singleton
but you'll have to keep in mind this instance will be shared across all users. Depending on your needs / application it may be simpler to just use LocalStorage
.