ASP.NET Core 2 Identity中UserManager.CreateAsync始终无响应问题排查
我来帮你排查这个CreateAsync始终无法执行完成的问题,结合你的代码来看,大概率和EF Core的实体跟踪、上下文使用方式有关,下面是几个核心排查点和解决办法:
1. 同步+异步混合操作DbContext导致死锁
你在代码里用同步的FirstOrDefault查询用户:
var existingUser = _BygBookDataContext.Users.FirstOrDefault(u => u.NormalizedEmail.Equals(model.NormalizedEmail));
而后续调用的UserManager.CreateAsync是异步操作,且内部会复用同一个DbContext。同步查询会占用DbContext的线程资源,异步操作等待时就容易造成死锁——这是ASP.NET Core中使用EF Core常见的坑。
解决办法:把同步查询改成异步版本:
var existingUser = await _BygBookDataContext.Users.FirstOrDefaultAsync(u => u.NormalizedEmail.Equals(model.NormalizedEmail));
2. 手动设置NormalizedEmail干扰Identity内部逻辑
你的ViewModel构造函数里手动给NormalizedEmail赋值,但Identity的UserManager内部会自动处理Email和UserName的标准化(比如转大写)。提前手动设置这个字段,可能导致EF Core的实体跟踪状态混乱,进而阻塞异步操作。
解决办法:创建新用户时,不要手动设置NormalizedEmail,交给UserManager自动处理。同时别忘了把ViewModel里的FirstName和LastName同步到新用户对象里(你之前的代码漏了这一步):
existingUser = new Domain.User() { UserName = model.UserName, Email = model.Email, FirstName = model.FirstName, LastName = model.LastName };
3. 重复调用SaveChanges引发上下文状态异常
在更新用户的分支里,你调用UserManager.UpdateAsync后又手动调用了_BygBookDataContext.SaveChanges()——但UserManager的所有操作(包括UpdateAsync、ResetPasswordAsync)内部已经自动调用了SaveChanges,重复调用会导致DbContext的状态异常,虽然这不是Create分支卡住的直接原因,但会破坏上下文的稳定性,间接影响其他操作。
解决办法:去掉更新分支里手动的SaveChanges调用:
else { existingUser.UserName = model.UserName; existingUser.FirstName = model.FirstName; existingUser.LastName = model.LastName; existingUser.Email = model.Email; await _userManager.UpdateAsync(existingUser); // 移除这行:_BygBookDataContext.SaveChanges(); if(!string.IsNullOrEmpty(model.Password)) { var pwToken = await _userManager.GeneratePasswordResetTokenAsync(existingUser); await _userManager.ResetPasswordAsync(existingUser, pwToken, model.Password); // 移除这行:_BygBookDataContext.SaveChanges(); } }
4. 空密码的潜在问题
你的ViewModel里注释掉了Password的[Required]和[MinLength(8)]验证,如果model.Password是空字符串,UserManager.CreateAsync虽然不会卡住,但会返回验证失败结果。建议加上密码有效性判断,避免无效调用:
if (string.IsNullOrEmpty(model.Password) || model.Password.Length < 8) { ModelState.AddModelError("Password", "Password is required and must be at least 8 characters long."); return PartialView(model); }
额外排查点
- 确认你的
_BygBookDataContext生命周期是Scoped(ASP.NET Core默认配置),如果是Singleton会导致线程安全问题,阻塞异步操作。 - 查看应用日志,有没有EF Core抛出的异常(比如实体约束冲突),有些异常不会直接中断程序,但会导致异步操作无限等待。
内容的提问来源于stack exchange,提问作者rasmus91

