Search code examples
dependency-injectionentity-framework-coreblazorblazor-server-sideasp.net-core-identity

Service dependency resets when the page is refreshed


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?


Solution

  • 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.