我是。net 6的新手,我在。net 6中创建了blazor WASM应用程序。其认证部分为JWT认证。当我要将令牌存储到本地存储时,发生了以下错误:
blazor.webassembly.js: 1系统。AggregateException:发生了一个或多个错误。(方法未找到:System.Threading.Tasks.ValueTask1<!!0> Blazored.LocalStorage.ILocalStorageService.GetItemAsync<!0>(string)) ---> System.MissingMethodException: Method not found: System.Threading.Tasks.ValueTask
1
Blazored.LocalStorage.ILocalStorageService.GetItemAsync 我program.cs
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args).AddRootComponents().AddClientServices();
var host = builder.Build();
var storageService = host.Services.GetRequiredService<ClientPreferenceManager>();
if (storageService != null)
{
CultureInfo culture;
var preference = await storageService.GetPreference() as ClientPreference;
}
builder.Services.AddMudServices();
builder.Services.AddTransient<ILocalItemStore,LocalItemStore>();
builder.Services.AddSingleton<IDataConnect, DataConnect>();
builder.Services.AddScoped<Service.InterData>();
await builder.Build().RunAsync();
}
ILocalStorageService.cs
public interface ILocalStorageService
{
event EventHandler<ChangingEventArgs> Changing;
event EventHandler<ChangedEventArgs> Changed;
ValueTask ClearAsync();
ValueTask<bool> ContainKeyAsync(string key);
ValueTask<string> GetItemAsStringAsync(string key);
ValueTask<T> GetItemAsync<T>(string key);
ValueTask<string> KeyAsync(int index);
ValueTask<int> LengthAsync();
ValueTask RemoveItemAsync(string key);
ValueTask SetItemAsync<T>(string key, T data);
}
import.razor中需要DI
@inject BL10StateProvider _stateProvider
@inject IAuthenticationManager _authenticationManager
login.razor
<div class="d-block">
<EditForm Model="@_tokenModel" OnValidSubmit="SubmitAsync">
<DataAnnotationsValidator />
<div class="@(f ? "invalid-box":"user-box")">
<InputText placeholder="Username" @bind-Value="_tokenModel.UserName" />
<ValidationMessage For="() => _tokenModel.UserName" />
@*<label class="body-default">Email</label>*@
</div>
<div class="@(f ? "invalid-box":"user-box")">
<InputText type="password" placeholder="Password" @bind-Value="_tokenModel.Password" />
<ValidationMessage For="() => _tokenModel.Password" />
@*<label class="body-default">Password</label>*@
</div>
<div>
<button type="submit" class="btn-block login-btn button-text"> Sign In</button>
</div>
</EditForm>
</div>
login.razor.cs
public partial class Login
{
bool f = false;
private TokenRequest _tokenModel = new();
protected override async Task OnInitializedAsync()
{
var state = await _stateProvider.GetAuthenticationStateAsync();
if (state != new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())))
{
_navigationManager.NavigateTo("/login");
}
await Task.FromResult(0);
}
private async Task SubmitAsync()
{
var result = await _authenticationManager.Login(_tokenModel);
if (result.Succeeded)
{
f = false;
_navigationManager.NavigateTo("/CompanySelection", true);
}
else
{
_tokenModel.Messaage = "UserName Or Password Incorrect";
f = true;
}
}
}
BL10StateProvider.cs
public class BL10StateProvider {
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var savedToken = await _localStorage.GetItemAsync<string>(StorageConstants.Local.AuthToken);
if (string.IsNullOrWhiteSpace(savedToken))
{
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", savedToken);
var state = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(GetClaimsFromJwt(savedToken), "jwt")));
AuthenticationStateUser = state.User;
return state;
}
}
AuthenticationManager.cs
public class AuthenticationManager{
public async Task<IResult> Login(TokenRequest model)
{
HttpResponseMessage response=null;
try
{
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), TokenEndpoints.Authenticate))
{
request.Headers.TryAddWithoutValidation("Timestamp", DateTime.Now.Ticks.ToString());
request.Content = JsonContent.Create(model);
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
response = await httpClient.SendAsync(request);
}
}
}
catch (Exception exp)
{
model.Messaage = "Login Falied";
model.IsTokenRequestFailed = true;
return await Result.FailAsync("Server Or API Host Not found");
}
//HttpRequestMessage req = new HttpRequestMessage();
//req.Method = HttpMethod.Post;
//req.RequestUri = TokenEndpoints.Authenticate;
//req.
////var response = await _httpClient.PostAsJsonAsync(TokenEndpoints.Authenticate, model);
// var response = await _httpClient.PostAsJsonAsync()
string responseBody = await response.Content.ReadAsStringAsync();
TokenResponse tokenRequest = JsonConvert.DeserializeObject<TokenResponse>(responseBody);
//var result = await response.ToResult<TokenResponse>();
if (tokenRequest.IsSuccess)
{
model.IsTokenRequestFailed = false;
model.Messaage = "Login Successful";
var token = tokenRequest.Token;
var refreshToken = tokenRequest.RefreshToken;
var userImageURL = tokenRequest.UserImageURL;
await _localStorage.SetItemAsync(StorageConstants.Local.AuthToken, token);
await _localStorage.SetItemAsync(StorageConstants.Local.RefreshToken, refreshToken);
if (!string.IsNullOrEmpty(userImageURL))
{
await _localStorage.SetItemAsync(StorageConstants.Local.UserImageURL, userImageURL);
}
((BL10StateProvider)this._authenticationStateProvider).MarkUserAsAuthenticated(model.UserName);
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
return await Result.SuccessAsync();
}
else
{
model.Messaage = "Login Falied";
model.IsTokenRequestFailed = true ;
return await Result.FailAsync(tokenRequest.Messages);
}
}
}
请使用上面的代码示例帮助我解决这个问题。
当你在Main()中,在。runasync()之前,JavaScript还没有加载。
错误在这一行:
var preference = await storageService.GetPreference() as ClientPreference;
无论你有什么逻辑,都必须稍后执行。
一个可能的位置是在App组件中,在OnAfterRenderAsync(true):
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var preference = await storageService.GetPreference() as ClientPreference;
...
}
}
但是请注意,在您设置首选项之前,您的第一个页面可能已经在初始化和渲染。