WebAssembly新手求助:登录提交后页面刷新无法捕获HttpClient响应
登录页面自动刷新,无法展示HttpClient响应提示信息
我是WebAssembly新手,输入登录凭据后,登录页面总是自动刷新,导致无法测试HttpClient的响应。执行到var authResult = await _httpClient.PostAsync("api/Login", bodyContent);这行代码后,页面就会刷新初始化,无法展示服务器离线、凭据错误等提示信息。以下是我的相关代码:
program.cs
var apiUrl = new Uri(configuration["apiUrl"]); //builder.Services.AddTransient<SkyPulsarAuthorizationMessageHandler>(); builder.Services.AddHttpClient("EdiRPX", httpClient => { httpClient.BaseAddress = apiUrl; }) .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5) })); //.AddHttpMessageHandler<SkyPulsarAuthorizationMessageHandler>(); builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>() .CreateClient("EdiRPX")); builder.Services.AuthClientSetup(); //* builder.Services.AddBlazoredLocalStorage(); builder.Services.AddAuthorizationCore(); builder.Services.AddScoped<AuthenticationStateProvider, ApiAuthenticationStateProvider>(); //* builder.Services.AddSingleton<SignalRClientService>(); builder.Services.AddTransient<IHelloService, HelloService>(); builder.Services.AddOidcAuthentication(options => { // Configure your authentication provider options here. // For more information, see https://aka.ms/blazor-standalone-auth builder.Configuration.Bind("Local", options.ProviderOptions); options.ProviderOptions.DefaultScopes.Add(builder.Configuration["apiUrl"]); }); await builder.Build().RunAsync();
Login.razor.cs的提交处理
public partial class Login { private string? hello { get; set; } public IEnumerable<string> Errors { get; set; } private LoginModel model = new LoginModel(); string backgroundUrl = "./resources/bg02.jpg"; private LoginResult user; private bool loading; private bool ShowErrors; private bool ShowHello; [CascadingParameter] public Error? Error { get; set; } protected override void OnInitialized() { // redirect to home if already logged in backgroundUrl = "./resources/bg02.jpg"; StateHasChanged(); } public Login() { user = new LoginResult(); } private void ChangeBackground() { backgroundUrl = "./resources/2.jpg"; StateHasChanged(); } private async void HandleValidSubmit() { loading = true; ShowErrors = false; try { //hello = await helloService.Run(); //ShowHello = true; //loading = false; user = await AuthService.Login(model); //var returnUrl = navigationManager.QueryString("returnUrl") ?? ""; //navigationManager.NavigateTo(returnUrl); if (user.Success) { navigationManager.NavigateTo("/"); } else { Errors = user.Errors; ShowErrors = true; //StateHasChanged(); } } catch (Exception ex) { Error?.ProcessError(ex); //ShowErrors = true; //Errors = new[] { ex.Message }; loading = false; //StateHasChanged(); } } } }
处理HttpClient请求的AuthService
public async Task<LoginResult> Login(LoginModel loginModel) { var content = JsonSerializer.Serialize(loginModel); var bodyContent = new StringContent(content, Encoding.UTF8, "application/json"); var _httpClient = _httpFactory.CreateClient("EdiRPX"); var loginResult = new LoginResult(); try { var authResult = await _httpClient.PostAsync("api/Login", bodyContent); if (!authResult.IsSuccessStatusCode) { ; loginResult.Errors = new List<string>() { authResult.StatusCode.ToString() }; loginResult.Success = false; return loginResult; } var authContent = await authResult.Content.ReadAsStringAsync(); loginResult = JsonSerializer.Deserialize<LoginResult>(authContent, _options); await _localStorage.SetItemAsync("authToken", loginResult.Token); ((ApiAuthenticationStateProvider)_authenticationStateProvider).MarkUserAsAuthenticated(loginModel.Email); _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", loginResult.Token); loginResult.Success = true; return loginResult; } catch (Exception ex) { if (loginResult != null) { loginResult.Errors = new List<string>() { ex.Message }; loginResult.Success = false; return loginResult; } else { return new LoginResult(); } } //StateHasChanged(); }
问题分析与解决方法
核心错误:异步事件处理方法使用async void
HandleValidSubmit方法定义为async void,这是Blazor组件异步事件处理的典型错误。async void会让Blazor框架无法追踪异步操作的执行状态,当异步代码(比如HttpClient请求)开始执行后,框架无法等待其完成,可能触发页面意外刷新,导致后续的错误提示逻辑无法执行。
修正方案
将async void改为async Task,Blazor完全支持返回Task的异步事件处理方法,这样框架能正确等待异步操作完成,确保后续UI更新逻辑正常执行:
private async Task HandleValidSubmit() { loading = true; ShowErrors = false; try { user = await AuthService.Login(model); if (user.Success) { navigationManager.NavigateTo("/"); } else { Errors = user.Errors; ShowErrors = true; } } catch (Exception ex) { Error?.ProcessError(ex); ShowErrors = true; Errors = new[] { ex.Message }; } finally { loading = false; // 确保无论请求成功/失败都重置加载状态 StateHasChanged(); // 手动通知组件更新UI } }
额外注意事项
- 确保Login.razor中的表单使用
EditForm组件并绑定OnValidSubmit="HandleValidSubmit",EditForm会自动阻止原生表单的默认提交行为,避免页面刷新。 - AuthService中每次创建新的HttpClient实例后设置的Authorization头,仅对当前实例有效。如果需要全局生效,建议通过自定义
HttpMessageHandler实现,或者在ApiAuthenticationStateProvider中维护全局的认证令牌。
内容的提问来源于stack exchange,提问作者João Rodrigues
相关产品推荐
相关产品推荐

