I am using Blazor with .NET 9.
The project is configured as a Blazor Auto project.
I have a Login page where the user can type their email and password.
Issue is, if the user is quick and starts typing, whatever they typed gets lost after about 1s and they have to start over.
It's like the page re-hydrates and the state gets blown away.
What causes this and how can I prevent it from happening?
@page "/Authentication/Login"@inject IUserService UserService@inject NavigationManager NavigationManager<PageTitle>Login</PageTitle><EditForm class="box-border flex flex-grow flex-col items-center justify-center p-8" FormName="LoginForm" Model="Model" OnInvalidSubmit="HandleInvalidSubmit" OnValidSubmit="HandleValidSubmitAsync"><DataAnnotationsValidator /><div class="box-border flex w-full max-w-xs flex-col p-8 shadow"><h1 class="text-lg">Login</h1><div class="mt-4 flex flex-col"><label class="text-xs opacity-75">Email</label><DxTextBox name="Model.Email" CssClass="mt-1" autofocus Text="@Model.Email" TextExpression="@(() => Model.Email)" ShowValidationIcon="true" /></div><div class="mt-2 flex flex-col"><label class="text-xs opacity-75">Password</label><DxTextBox name="Model.Password" CssClass="mt-1" Text="@Model.Password" TextExpression="@(() => Model.Password)" ShowValidationIcon="true" Password="true" /></div> @if (EditContext.GetValidationMessages().Distinct().Any()) {<ul class="text-[var(--invalid-color)] mt-4 list-inside list-disc"> @foreach (var message in EditContext.GetValidationMessages().Distinct()) {<li>@message</li> }</ul> }<DxButton CssClass="mt-4" Text="Login" SubmitFormOnClick="true" /><a href="@($"{NavigationManager.BaseUri}Authentication/ForgotPassword")" class="dxbl-btn dxbl-btn-outline-primary dxbl-btn-standalone mt-2">Forgot Password</a></div></EditForm>@code { [Parameter] [SupplyParameterFromQuery] public string RedirectUri { get; set; } = string.Empty; [Parameter] [SupplyParameterFromQuery] public string Code { get; set; } = string.Empty; [Parameter] [SupplyParameterFromQuery(Name = "RequestedScopes")] public string RequestedScopesAsString { get; set; } = string.Empty; [Parameter] [SupplyParameterFromQuery] public string Nonce { get; set; } = string.Empty; [Parameter] [SupplyParameterFromQuery] public string State { get; set; } = string.Empty; public List<string> RequestedScopes => RequestedScopesAsString.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(); public EditContext EditContext { get; set; } public ValidationMessageStore ValidationMessageStore { get; set; } [SupplyParameterFromForm] public LoginModel Model { get; set; } public Login() { Model ??= new LoginModel(); EditContext ??= new EditContext(Model); ValidationMessageStore ??= new ValidationMessageStore(EditContext); } public void HandleInvalidSubmit() { ValidationMessageStore.Clear(); if (string.IsNullOrEmpty(Model.Email)) { ValidationMessageStore.Add(EditContext.Field(nameof(Model.Email)), "Email is required."); } if (string.IsNullOrEmpty(Model.Password)) { ValidationMessageStore.Add(EditContext.Field(nameof(Model.Password)), "Password is required."); } if (EditContext.GetValidationMessages().Distinct().Any()) { return; } } public async Task HandleValidSubmitAsync() { ValidationMessageStore.Clear(); OpenIdConnectLoginRequest openIdConnectLoginRequest = new() { Code = Code, Nonce = Nonce, Password = Model.Password, RedirectUri = RedirectUri, RequestedScopes = RequestedScopes, Email = Model.Email }; var openIdConnectLoginResponse = await UserService.SignInAsync(openIdConnectLoginRequest); if (!openIdConnectLoginResponse.IsSuccess) { ValidationMessageStore.Add(EditContext.Field(nameof(Model.Email)), "Invalid email or password."); ValidationMessageStore.Add(EditContext.Field(nameof(Model.Password)), "Invalid email or password."); } if (EditContext.GetValidationMessages().Distinct().Any()) { return; } NavigationManager.NavigateTo($"{RedirectUri}&state={State}&code={Code}", forceLoad: true); } public class LoginModel { [Required] public string Email { get; set; } = string.Empty; [Required] public string Password { get; set; } = string.Empty; }}