我在将数据保存到 Blazor UI for Identity .NET 8 中的扩展用户属性时遇到问题。
我的问题是,在
OnValidSubmitAsync()
中的Components/Account/Pages/Manage/Index.razor
方法中,只保存了电话号码,但没有保存其他内容。
我已将问题范围缩小到
OnValidSubmitAsync()
内的这些行无法获取表单字段数据:
user.Introduction = Input.Introduction;
user.Website = Input.Website;
user.Instagram = Input.Instagram;
user.TwitterX = Input.TwitterX;
user.Facebook = Input.Facebook;
如果我尝试硬编码一个值,它就会成功保存:
user.Website = "www.test.com";
所以我猜这是一个数据绑定问题。
我已将
ApplicationUser
重命名为 User
,它继承自 IdentityUser
:
public class User : IdentityUser
{
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public bool HasProfileImage { get; set; }
public bool HasBackgropImage { get; set; }
public string Introduction { get; set; } = string.Empty;
public string? Website { get; set; }
public string? Instagram { get; set; }
public string? TwitterX { get; set; }
public string? Facebook { get; set; }
public List<Recipe> Recipes { get; set; } = [];
}
我的
DataContext
配置正确,并且模型中的所有属性都作为数据库中 AspNetUser
表中的列找到。
在
Program.cs
:
builder.Services.AddIdentityCore<User>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<DataContext>()
.AddSignInManager()
.AddDefaultTokenProviders();
我已在 SQL Server Management Studio 中手动输入测试数据,所有扩展字段都已成功加载到
OnInitializedAsync()
中并在表单字段中正确显示。
这是我的全部
Index.razor
:
@page "/Account/Manage"
@inject UserManager<User> UserManager
@inject SignInManager<User> SignInManager
@inject IdentityUserAccessor UserAccessor
@inject IdentityRedirectManager RedirectManager
<PageTitle>Profile</PageTitle>
<h3>Profile</h3>
<StatusMessage />
<div class="row">
<div class="col-md-6">
<EditForm Model="Input" FormName="profile" OnValidSubmit="OnValidSubmitAsync" method="post">
<DataAnnotationsValidator />
<ValidationSummary class="text-danger" role="alert" />
<div class="form-floating mb-3">
<input type="text" value="@username" class="form-control" disabled />
<label for="username" class="form-label"><i class="bi bi-envelope-at"></i> Brukernavn</label>
</div>
<div class="form-floating mb-3">
<InputText @bind-Value="Input.PhoneNumber" class="form-control" placeholder="Phone number" />
<label for="phone-number" class="form-label"><i class="bi bi-phone"></i> Phone number</label>
<ValidationMessage For="() => Input.PhoneNumber" class="text-danger" />
</div>
<div class="form-floating mb-3">
<InputText @bind-Value="Input.Introduction" class="form-control" placeholder="Introduction" />
<label for="introduction" class="form-label"><i class="bi bi-blockquote-left"></i> Introduction</label>
</div>
<div class="d-flex flex-row row row-cols-2">
<div class="form-floating mb-3">
<InputText @bind-Value="Input.Website" class="form-control" placeholder="Website" />
<label for="website" class="form-label ms-3"><i class="bi bi-globe"></i> Website</label>
</div>
<div class="form-floating mb-3">
<InputText @bind-Value="Input.Instagram" class="form-control" placeholder="Instagram" />
<label for="instagram" class="form-label ms-3"><i class="bi bi-instagram"></i> Instagram</label>
</div>
<div class="form-floating mb-3">
<InputText @bind-Value="Input.TwitterX" class="form-control" placeholder="Twitter/X" />
<label for="twitterX" class="form-label ms-3"><i class="bi bi-twitter-x"></i> Twitter/X</label>
</div>
<div class="form-floating mb-3">
<InputText @bind-Value="Input.Facebook" class="form-control" placeholder="Facebook" />
<label for="facebook" class="form-label ms-3"><i class="bi bi-facebook"></i> Facebook</label>
</div>
</div>
<button type="submit" class="w-100 btn btn-lg btn-success">
<i class="bi bi-save"></i>
Save
</button>
</EditForm>
</div>
</div>
@code {
private User user = default!;
private string? username;
private string? phoneNumber;
private string? introduction;
private string? website;
private string? instagram;
private string? twitterX;
private string? facebook;
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
[SupplyParameterFromForm(FormName = "profile")]
private InputModel Input { get; set; } = new();
protected override async Task OnInitializedAsync()
{
user = await UserAccessor.GetRequiredUserAsync(HttpContext);
username = await UserManager.GetUserNameAsync(user);
phoneNumber = await UserManager.GetPhoneNumberAsync(user);
// These are all working. All the data is loaded from DB:
Input.PhoneNumber ??= phoneNumber;
Input.Introduction = user.Introduction;
Input.Website = user.Website;
Input.Instagram = user.Instagram;
Input.TwitterX = user.TwitterX;
Input.Facebook = user.Facebook;
}
private async Task OnValidSubmitAsync()
{
if (Input.PhoneNumber != phoneNumber)
{
var setPhoneResult = await UserManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
if (!setPhoneResult.Succeeded)
{
RedirectManager.RedirectToCurrentPageWithStatus("Error: Could not set phone number.", HttpContext);
}
}
// The form field data is not being copied to the user-object here:
user.Introduction = Input.Introduction;
user.Website = Input.Website;
user.Instagram = Input.Instagram;
user.TwitterX = Input.TwitterX;
user.Facebook = Input.Facebook;
// Hard coded values are successfully saved:
user.Website = "www.test.com";
await UserManager.UpdateAsync(user); // This line is working
await SignInManager.RefreshSignInAsync(user);
RedirectManager.RedirectToCurrentPageWithStatus($"Your profile was updated.", HttpContext);
}
private sealed class InputModel
{
[Phone]
[Display(Name = "Phone number")]
public string? PhoneNumber { get; set; }
// Exxtended fields
public string? Introduction { get; set; }
public string? Website { get; set; }
public string? Instagram { get; set; }
public string? TwitterX { get; set; }
public string? Facebook { get; set; }
}
}
我认为你需要在绑定变量中使用
@
,否则它会将其作为字符串使用......
@bind-Value="Input.Facebook"
变成
@bind-Value="@Input.Facebook"