You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8 Blazor Server中Identity UI无法保存扩展用户属性

问题原因与解决方案

核心问题

你在OnInitializedAsync中获取的user是**ClaimsPrincipal类型**(用户身份凭证对象),而非数据库中被EF Core跟踪的ApplicationUser实体。直接给ClaimsPrincipal赋值自定义属性不会被EF Core识别为实体变更,自然无法保存到数据库。而电话号码能正常保存,是因为SetPhoneNumberAsync是Identity内置方法,内部会正确获取并更新数据库中的用户实体。

修正步骤

1. 正确获取数据库中的ApplicationUser实体

修改OnInitializedAsync方法,通过UserManager从数据库中加载真正的ApplicationUser实例:

// 先确保user变量的声明为ApplicationUser类型:
private ApplicationUser? user;

protected override async Task OnInitializedAsync()
{
    var claimsUser = await UserAccessor.GetRequiredUserAsync(HttpContext);
    // 通过用户ID从数据库获取跟踪的ApplicationUser实体
    user = await UserManager.FindByIdAsync(await UserManager.GetUserIdAsync(claimsUser));
    
    if (user == null)
    {
        RedirectManager.RedirectToPage("/Account/Login");
        return;
    }

    username = await UserManager.GetUserNameAsync(user);
    phoneNumber = await UserManager.GetPhoneNumberAsync(user);

    Input.PhoneNumber ??= phoneNumber;
    Input.FirstName = user.FirstName;
    Input.LastName = user.LastName;
}

2. 完善更新逻辑并添加错误检查

在OnValidSubmitAsync中使用数据库实体进行修改,并添加更新结果校验,方便排查问题:

private async Task OnValidSubmitAsync()
{
    if (user == null) return;

    if (Input.PhoneNumber != phoneNumber)
    {
        var setPhoneResult = await UserManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
        if (!setPhoneResult.Succeeded)
        {
            RedirectManager.RedirectToCurrentPageWithStatus("错误:设置电话号码失败。", HttpContext);
            return;
        }
    }

    // 修改跟踪实体的属性
    user.FirstName = Input.FirstName;
    user.LastName = Input.LastName;
    // 执行更新并检查结果
    var updateResult = await UserManager.UpdateAsync(user);
    
    if (!updateResult.Succeeded)
    {
        var errorMsg = string.Join(",", updateResult.Errors.Select(e => e.Description));
        RedirectManager.RedirectToCurrentPageWithStatus($"错误:更新资料失败。{errorMsg}", HttpContext);
        return;
    }

    await SignInManager.RefreshSignInAsync(user);
    RedirectManager.RedirectToCurrentPageWithStatus("你的资料已更新", HttpContext);
}

3. 可选:添加属性验证(提升用户体验)

给ApplicationUser和InputModel的自定义属性添加验证特性,确保输入有效性:

// ApplicationUser.cs
using System.ComponentModel.DataAnnotations;

public class ApplicationUser : IdentityUser
{
    [Required]
    [StringLength(50)]
    public string FirstName { get; set; } = string.Empty;
    
    [Required]
    [StringLength(50)]
    public string LastName { get; set; } = string.Empty;
}
// Index.razor中的InputModel
private sealed class InputModel
{
    [Phone]
    [Display(Name = "Phone number")]
    public string? PhoneNumber { get; set; }

    [Required]
    [StringLength(50)]
    public string FirstName { get; set; } = string.Empty;
    
    [Required]
    [StringLength(50)]
    public string LastName { get; set; } = string.Empty;
}

内容的提问来源于stack exchange,提问作者Stian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 07:47:39