C#C
C#2y ago
Lukaa

Proper way to do per user state management in Blazor with Identity

Hi. I am attempting to have state management with blazor & identity. So basically I want to acquire the current user in the ManageLayout and then reuse the data in navmenu or in @body. I was thinking of just passing them as parameters, but you need some kind of synchronization due to asynchronous user retrieval. this is my state code :

    internal sealed class AccountDataState
    {
        public string? Username { get; private set; }
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly IdentityUserAccessor _userAccessor;

        public AccountDataState(IHttpContextAccessor httpContextAccessor, UserManager<ApplicationUser> userManager, IdentityUserAccessor userAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
            _userManager = userManager;
            _userAccessor = userAccessor;
        }

        public event Action OnChange;
        public async Task InitializeAsync()
        {
            var user = await _userAccessor.GetRequiredUserAsync(_httpContextAccessor.HttpContext);
            Username = await _userManager.GetUserNameAsync(user);
            NotifyStateChanged();
        }
        private void NotifyStateChanged() => OnChange?.Invoke();
    }


Currently this doesn't work in another component, when Username is initialized it doesn't really notify all components even though the state is injected, I assume that's due to service being Scoped. How is the conventional way to approach this issue?

ManageLayout.razor :
    protected override async void OnInitialized()
    {
        State.OnChange += StateHasChanged;
        await State.InitializeAsync();
    }


Index.razor

<h1>@username</h1>
@code{
    protected override async Task OnInitializedAsync()
    {
        username = State.Username;
    }
Was this page helpful?