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

Blazor项目扩展AspNetUsers表字段时触发多个Identity报错

报错根因

你遇到的所有报错核心原因是扩展ASP.NET Core Identity用户字段时操作逻辑不符合框架约定:

  • 直接给默认IdentityUser类加字段的方式不被EF Core支持,必须通过自定义派生用户类实现字段扩展
  • 你的ApplicationDbContext继承的是非泛型版本IdentityDbContext,没有绑定自定义用户类型,导致Identity关联表(如IdentityUserLogin)的主键配置缺失
  • 服务注册、控制器注入的UserManager/SignInManager全用了默认IdentityUser类型,和上下文模型不匹配
  • 之前生成的不完整迁移文件、残留缓存会触发资源类型物化失败的鉴别器报错

正确实现步骤

第一步:创建自定义用户实体

在项目Entities目录下新建ApplicationUser类,继承默认IdentityUser,新增需要的3个字段:

using Microsoft.AspNetCore.Identity;

namespace LoginAndAuthProj.Server.Entities
{
    public class ApplicationUser : IdentityUser
    {
        public string UsersAddress { get; set; }
        public int CityID { get; set; }
        public byte[] PictureOfUser { get; set; }
    }
}

第二步:修改DbContext绑定自定义用户类型

将原来的非泛型IdentityDbContext替换为泛型版本,绑定自定义用户类,注意OnModelCreating中必须先调用基类方法完成Identity默认表配置,再写自定义逻辑:

using LoginAndAuthProj.Server.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.InMemory.ValueGeneration.Internal;
using System;

namespace LoginAndAuthProj.Server.MainDbContext
{
    // 泛型参数依次为:自定义用户类、角色类、用户主键类型(默认string)
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser, IdentityRole, string>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // 必须优先调用基类配置,否则Identity内置表的主键、索引配置不会生效
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<MyEventUserLog>(entity =>
            {
                var pb = entity.Property(e => e.UId).ValueGeneratedOnAdd();
                if (Database.IsInMemory())
                {
                    pb.HasValueGenerator<InMemoryIntegerValueGenerator<decimal>>();
                }
            });

            // 可选:给新增字段配置数据库映射规则
            modelBuilder.Entity<ApplicationUser>(entity =>
            {
                entity.Property(e => e.UsersAddress).HasMaxLength(256);
                entity.Property(e => e.PictureOfUser).HasColumnType("varbinary(max)");
            });
        }

        public DbSet<MyEventUserLog> MyEventUserLogs { get; set; }
    }
}

第三步:修改Startup的Identity服务注册

将注册Identity时使用的默认IdentityUser替换为自定义的ApplicationUser:

// 替换原来的 services.AddIdentity<IdentityUser, IdentityRole>()
services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

第四步:修改AccountController的依赖注入和用户逻辑

将控制器中所有用到IdentityUser的地方替换为ApplicationUser:

  1. 调整注入的Manager泛型参数:
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly IConfiguration _configuration;
    
    public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager,
        IConfiguration configuration)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _configuration = configuration;
    }
    
  2. 调整创建用户的实例化逻辑,给新增字段赋初始值:
    [HttpPost("Create")]
    public async Task<ActionResult<UserToken>> CreateUser([FromBody] UserInfo model)
    {
        var user = new ApplicationUser 
        { 
            UserName = model.Email, 
            Email = model.Email, 
            PhoneNumber = "00000011110000", 
            EmailConfirmed = true, 
            PhoneNumberConfirmed = true, 
            TwoFactorEnabled = false, 
            LockoutEnabled = false, 
            AccessFailedCount = 0,
            // 新增字段初始值,后续可根据业务从请求参数传值
            UsersAddress = string.Empty,
            CityID = 0,
            PictureOfUser = Array.Empty<byte>()
        };
    
        try
        {
            var result = await _userManager.CreateAsync(user, model.StrPassword);
            if (result.Succeeded)
            {
                return BuildToken(model);
            }
            else
            {
                return BadRequest("用户名或密码格式不符合要求");
            }
        }
        catch (Exception ex)
        {
            return BadRequest(ex.Message);
        }
    }
    

其余查询、登录逻辑不需要修改,_userManager的返回值会自动映射为ApplicationUser类型。

第五步:清理旧迁移同步数据库结构

  1. 删除项目Migrations文件夹下所有历史迁移文件
  2. 打开包管理器控制台依次执行命令生成新迁移、更新数据库:
    Add-Migration AddCustomUserFields
    Update-Database
    

执行完成后AspNetUsers表就会自动新增你需要的3个字段。


残留报错排查
  • 如果还提示discriminator鉴别器相关错误,删除数据库中__EFMigrationsHistory表的所有记录,重新执行迁移即可,该错误是历史不完整迁移导致的配置缺失
  • 如果提示类型不匹配,清理项目bin、obj文件夹后重新生成解决方案
  • 不要直接手动修改数据库表加字段,必须通过EF Core迁移同步结构,否则会出现模型与数据库结构不匹配的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:18:23