我正在创建一个Blazor UI应用程序来与API对话。目前,我正试图获得一个自定义的提供程序,我得到了一些错误。
这是客户AuthenticationStateProvider
public class APIAuthenticationStateProvider : AuthenticationStateProvider
{
private readonly HttpClient _httpClient;
private readonly ILocalStorageService _localStorage;
public APIAuthenticationStateProvider(HttpClient httpClient, ILocalStorageService localStorage)
{
_httpClient = httpClient;
_localStorage = localStorage;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var token = await _localStorage.GetItemAsync<string>("authToken");
if (string.IsNullOrWhiteSpace(token))
{
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("bearer", token);
var claims = ParseClaims(token);
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims,"jwt")));
}
}
Startup.cs文件中的"配置服务"功能类似于以下
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddBlazoredLocalStorage();
services.AddScoped<AuthenticationStateProvider, APIAuthenticationStateProvider>();
services.AddTransient<IAuthRepository, AuthRepository>();
services.AddHttpClient();
}
当我执行时,我得到以下异常
InvalidOperationException: JavaScript interop calls cannot be issued at this time. This is because the component is being statically rendererd. When prerendering is enabled, JavaScript interop calls can only be performed during the OnAfterRenderAsync lifecycle method.
Microsoft.AspNetCore.Components.Server.Circuits.RemoteJSRuntime.BeginInvokeJS(long asyncHandle, string identifier, string argsJson)
Microsoft.JSInterop.JSRuntime.InvokeAsync<TValue>(string identifier, CancellationToken cancellationToken, object[] args)
Microsoft.JSInterop.JSRuntime.InvokeWithDefaultCancellation<T>(string identifier, object[] args)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Runtime.CompilerServices.ValueTaskAwaiter<TResult>.GetResult()
Blazored.LocalStorage.LocalStorageService.GetItemAsync<T>(string key)
BookStore_UI.Providers.APIAuthenticationStateProvider.GetAuthenticationStateAsync() in APIAuthenticationStateProvider.cs
我不确定错误是否清楚,这就是错误的真正所在,或者我是否遗漏了其他潜在的步骤。我认为这可能与使用本地存储有关。
在_Host.cshtml中,更改渲染模式
render mode="ServerPrerender">
至渲染模式="服务器">
错误与JS代码在加载所有资源之前被触发有关。。。简而言之
为了防止它崩溃,我在一次尝试中封装了Task GetAuthenticationStateAsync((函数。。。catch并且没有抛出异常。
此代码:var token = await _localStorage.GetItemAsync<string>("authToken");
在JavaScript还不可用的情况下执行。当您尝试访问本地存储时,请查阅文档中如何处理此类情况。它们专门展示了如何完成这样的任务。
您的ConfigureServices应该如下所示:
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddBlazoredLocalStorage();
services.AddHttpClient();
services.AddScoped<APIAuthenticationStateProvider>();
services.AddScoped<AuthenticationStateProvider>(provider =>
provider.GetRequiredService<APIAuthenticationStateProvider>());
services.AddTransient<IAuthRepository, AuthRepository>();
_httpClient。DefaultRequestHeaders。授权=新的AuthenticationHeaderValue("承载",令牌(;
GetAuthenticationStateAsync方法应该有一个目标:返回Authentication State对象,这就是为什么不应该使用它来配置HttpClient对象。您应该在要调用HttpClient服务的方法的位置执行此操作(从本地存储读取Jwt令牌,并将其分配给请求的Authorization标头(。
希望这能帮助。。。