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

Sil*_*ows 4 c# asp.net-core blazor-server-side

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

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);

        }
Run Code Online (Sandbox Code Playgroud)

登录控件.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);
    }

}
Run Code Online (Sandbox Code Playgroud)

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

小智 6

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

StateHasChanged();
Run Code Online (Sandbox Code Playgroud)

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

我的登录控件有这个:

<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();
    }
}
Run Code Online (Sandbox Code Playgroud)

并在您的控件中调用 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);
}
Run Code Online (Sandbox Code Playgroud)


小智 5

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

NaviMngr.NavigateTo("/", true);
Run Code Online (Sandbox Code Playgroud)