我有一个 Blazor/.NET8 Web 应用程序,但我正在努力处理用户注册组件。问题是我似乎无法创建一种方法来有条件地阻止任务运行或禁用后续单击的按钮。
我尝试添加一个私有 bool 并根据其值有条件地运行任务,但提交似乎以某种方式将 bool 重置回 false。此时,我扩展了这一理论并创建了一个“StateService”,认为这将保留该值,但其行为相同:
namespace TripSuite.Service
{
public interface IStateService
{
bool IsSubmitting { get; set; }
}
public class StateService : IStateService
{
public bool IsSubmitting { get; set; } = false;
}
}
在程序.cs中:
builder.Services.AddSingleton<IStateService, StateService>();
组件:
<EditForm Model="Input" asp-route-returnUrl="@ReturnUrl" method="post" OnValidSubmit="HandleSubmit" FormName="register">
<DataAnnotationsValidator />
<hr />
<ValidationSummary class="text-danger" role="alert" />
<div class="form-floating mb-3">
<InputText @bind-Value="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="[email protected]" />
<label for="email">Email</label>
<ValidationMessage For="() => Input.Email" class="text-danger" />
</div>
<div class="form-floating mb-3">
<InputText type="password" @bind-Value="Input.Password" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
<label for="password">Password</label>
<ValidationMessage For="() => Input.Password" class="text-danger" />
</div>
<div class="form-floating mb-3">
<InputText type="password" @bind-Value="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
<label for="confirm-password">Confirm Password</label>
<ValidationMessage For="() => Input.ConfirmPassword" class="text-danger" />
</div>
<MudButton ButtonType="ButtonType.Submit" Disabled="@stateService.IsSubmitting">Register</MudButton>
</EditForm>
CS:
private async void HandleSubmit()
{
if (!stateService.IsSubmitting)
{
stateService.IsSubmitting = true;
StateHasChanged();
await RegisterUser();
}
}
我不太明白的是,如果我注释掉“await RegisterUser();”然后 UI 按预期运行,提交按钮被禁用。
我不认为这一切都是相关的,但这是创建用户并设置一些默认值的 RegisterUser 方法。
public async Task RegisterUser()
{
var user = CreateUser();
await UserStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
var emailStore = GetEmailStore();
await emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
var result = await UserManager.CreateAsync(user, Input.Password);
if (!result.Succeeded)
{
identityErrors = result.Errors;
return;
}
var userId = await UserManager.GetUserIdAsync(user);
var code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = NavigationManager.GetUriWithQueryParameters(
NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri,
new Dictionary<string, object?> { ["userId"] = userId, ["code"] = code, ["returnUrl"] = ReturnUrl });
await EmailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));
var usersCount = await UserManager.Users.CountAsync();
if (usersCount == 1) // The first user has just been created.
{
var adminRoleExists = await RoleManager.RoleExistsAsync("Admin");
if (!adminRoleExists)
{
await RoleManager.CreateAsync(new IdentityRole("Admin"));
}
await UserManager.AddToRoleAsync(user, "Admin");
await UserManager.AddClaimAsync(user, new Claim("Permission", "CanAccessEverything"));
}
var newUserSettings = new UserSettings
{
UserID = userId,
SelectedTheme = "Dark"
};
var newEntity = new Entities
{
Email = user.Email,
UserID = userId,
EntityType = Enums.EntityTypes.WebUser
};
DB.Entities.Add(newEntity);
DB.UserSettings.Add(newUserSettings);
await DB.SaveChangesAsync();
if (UserManager.Options.SignIn.RequireConfirmedAccount)
{
RedirectManager.RedirectTo(
"Account/RegisterConfirmation",
new() { ["email"] = Input.Email, ["returnUrl"] = ReturnUrl });
}
await SignInManager.SignInAsync(user, isPersistent: false);
RedirectManager.RedirectTo(ReturnUrl);
}
我在这里不知所措,看来这应该是一件简单的事情
这一行:
private async void HandleSubmit()
应该是
private async Task HandleSubmit()
请参阅有关原因的更多信息 - Blazor UI Update Async void 与 Async Task