I have an issue with MudBlazor and AspNetCore UserManager.
In my Application I have a profile menu dropdown in the top right corner.
When i click on "Edit Profile" I get routed to my edit profile page.
So in this scenario both components are loaded at the same time.
I have created a small TryMudBlazor to test it...
When I hit the refresh button MudBlazor tries to load both components in parrallel.
Both components get the current user via AspNetCore UserManager inside the OnInitializedAsync
Problem:
Both UserManager requests work on the same DbContext so i get an error that the ApplicationUser Instance is already beeing tracked.
As the UserManager is a scoped service shouldn't there be something like thread safety by default?
I have implemented a working solution that uses a self implemented UserService with a TaskCompletionSource but I am still wondering if I am just missing something to get the thread safety by default.
public class UserService(SignInManager<ApplicationUser> signInManager, IHttpContextAccessor httpContextAccessor) : IUserService{ public SignInManager<ApplicationUser> SignInManager { get; } = signInManager; private readonly TaskCompletionSource<ApplicationUser?> _taskCompletionSource = new(); private int _isInitialized = 0; public async Task<ApplicationUser?> GetUserAsync(ClaimsPrincipal claimsPrincipal) { if (Interlocked.CompareExchange(ref _isInitialized, 1, 0) == 0) { var user = await SignInManager.UserManager.GetUserAsync(claimsPrincipal); _taskCompletionSource.SetResult(user); return user; } return await _taskCompletionSource.Task; } public async Task<ApplicationUser?> GetUserAsync() { var user = httpContextAccessor.HttpContext?.User; if (user != null) { return await GetUserAsync(user); } return null; }}Add it to Program.cs like so:
services.AddScoped<IUserService, UserService>();