如何正确通知 Blazor UI 我的用户状态已更改?

How do I correctly notify the Blazor UI that my user state has changed?

我目前正在学习 asp.net core 和 blazor,并且遇到了一个文档很少的问题。我有一个服务器端 Blazor 应用程序,并且正在执行身份验证以使用本地存储和 ServerAuthenticationStateProvider。此代码基于 this guide,这是我当前对状态提供程序的实现:

MyAuthenticationStateProvider.cs

namespace BlazorApp
{
    public class MyAuthenticationStateProvider : ServerAuthenticationStateProvider
    {
        private readonly HttpClient _httpClient;
        private readonly ILocalStorageService _localStorage;

        public MyAuthenticationStateProvider(HttpClient httpClient, ILocalStorageService localStorage)
        {
            _httpClient = httpClient;
            _localStorage = localStorage;
        }
        public override async Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            var savedToken = await _localStorage.GetItemAsync<string>("authToken");

            if (string.IsNullOrWhiteSpace(savedToken))
            {
                return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
            }

            var user = new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(savedToken), "jwt"));

            return new AuthenticationState(user);
        }

        public void MarkUserAsAuthenticated(string token)
        {
            var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt"));
            var authState = Task.FromResult(new AuthenticationState(authenticatedUser));
            NotifyAuthenticationStateChanged(authState);

        }

LoginControl.cs

@page "/loginControl"
@inject IAuthService AuthService
@inject NavigationManager NavigationManager

    <AuthorizeView>

        <Authorized>

            <b>Hello, @context.User.Identity.Name!</b>

            <a class="ml-md-auto btn btn-primary"
               href="logout?returnUrl=/"
               target="_top">Logout</a>

        </Authorized>

        <Authorizing>
            <b>Authentication in progress</b>
        </Authorizing>

        <NotAuthorized>

            <input type="text"
                   placeholder="Email"
                   @bind="@email" />

            &nbsp;&nbsp;

            <input type="password"
                   placeholder="Password"
                   @bind="@password" />

            <button class="ml-md-auto btn btn-primary"
                    @onclick="@createSession">
                Login
            </button>

        </NotAuthorized>

    </AuthorizeView>

@code {

    string email = "";

    string password = "";

    async void createSession()
    {

        var loginRequest = new LoginRequest
        {

            Email = email,
            Password = password

        };

        await AuthService.Login(loginRequest);
    }

}

我希望在调用 NotifyAuthenticationStateChanged(AuthState) 后,我的登录 UI 会刷新并显示 <Authorized> 内容。但是我的 UI 仍然显示 <NotAuthorized> 内容。我错过了与分派到主线程有关的事情吗?我对这一切都很陌生,但我的导师提到了一些与此有关的事情,这可能与后台线程不告诉 UI 重新渲染有关。

真的很简单。您需要做的就是:

StateHasChanged();

我昨天刚刚构建了一个登录控件,所以这里有一些您可能想知道的额外信息:

我的登录控件是这样的:

<Login OnLogin="LoginComplete"></Login>

/// <summary>
/// This method returns the LoginResponse object 
/// </summary>
/// <param name="loginResponse"></param>
private void LoginComplete(LoginResponse loginResponse)
{
    // if the login was successful
    if (loginResponse.Success)
    {
        // Set the player
        player = loginResponse.Player;

        // refresh the UI
        this.StateHasChanged();
    }
}

并在您的控件中调用 LoginResponse 委托

// Get the loginResponse
LoginResponse loginResponse = await PlayerService.Login(emailAddress, password);

// if the loginResponse exists
if (NullHelper.Exists(loginResponse))
{
   // set the player
   player = loginResponse.Player;

   // Perform the Login
  await OnLogin.InvokeAsync(loginResponse);
}

我做错了,服务器端 blazor 已经实现了 AuthenticationStateProvider,所以我需要做的就是实现设置 user.identity.isauthenticated 的东西,我正在使用 cookie 和 jet 令牌做这个。

我通过使用导航管理器重定向用户并强制重定向解决了这个问题(通过这样做,应用程序被迫更改 authState)。 我这样做只是因为 StateChanged() 无法正常工作。

NaviMngr.NavigateTo("/", true);