如何正确通知 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" />
<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);
我目前正在学习 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" />
<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);