代码之家  ›  专栏  ›  技术社区  ›  Vague

userManager。创建异步系统。ObjectDisposedException未处理

  •  4
  • Vague  · 技术社区  · 10 年前

    我们正在尝试在ASP中使用Microsoft帐户身份验证。Net 5项目。我们不需要本地身份验证,也不需要用户名。

    在ASP。Net 5 web应用程序模板,在与外部提供程序登录后,控件返回到 ExternalLoginCallback 在AccountController中。

    如果用户未在本地注册 外部登录回拨 将用户返回到注册屏幕。我试图修改 外部登录回拨 以如下自动注册新用户。

            public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null)
        {
            var info = await _signInManager.GetExternalLoginInfoAsync();
            if (info == null)
            {
                return RedirectToAction(nameof(Login));
            }
    
            // Sign in the user with this external login provider if the user already has a login.
            var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
            if (result.Succeeded)
            {
                _logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider);
                return RedirectToLocal(returnUrl);
            }
            if (result.RequiresTwoFactor)
            {
                return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl });
            }
            if (result.IsLockedOut)
            {
                return View("Lockout");
            }
            else
            {
                // If the user does not have an account, then ask the user to create an account.
                //ViewData["ReturnUrl"] = returnUrl;
                //ViewData["LoginProvider"] = info.LoginProvider;
                //var email = info.ExternalPrincipal.FindFirstValue(ClaimTypes.Email);
                //return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
    
                // The user has not previously logged in with an external provider. Create a new user.
                CreateUser(info);
                return RedirectToLocal(returnUrl);
            }
        }
    

    CreateUser实现从复制的代码 ExternalLoginConfirmation 正如它在ASP。网络应用程序的Net 5模板。

            private async void CreateUser(ExternalLoginInfo info)
        {
            var email = info.ExternalPrincipal.FindFirstValue(ClaimTypes.Email);
            var user = new ApplicationUser { UserName = email, Email = email };
            var result = await _userManager.CreateAsync(user);
            if (result.Succeeded)
            {
                result = await _userManager.AddLoginAsync(user, info);
                if (result.Succeeded)
                {
                    await _signInManager.SignInAsync(user, isPersistent: false);
                    _logger.LogInformation(6, "User created an account using {Name} provider.", info.LoginProvider);
                }
            }
            AddErrors(result);
        }
    

    在线上抛出错误

    var result = await _userManager.CreateAsync(user);
    

    错误是

    System.ObjectDisposedException was unhandled Message: An unhandled exception of type 'System.ObjectDisposedException' occurred in mscorlib.dll. Additional information: Cannot access a disposed object.
    

    我重新启动了我的机器,以防它“只是其中之一”,但错误再次出现。

    1 回复  |  直到 10 年前
        1
  •  11
  •   Kévin Chalet    10 年前

    使用 async void 这种方法很少是一个好主意,而且是引入像你所经历的那种奇怪的比赛条件的最佳方法: CreateUser 方法不返回任务,无法等待 ExternalLoginCallback 并且请求在之前完成 创建用户 有时间执行数据库操作(当请求完成时,DI系统调用 Dispose 在EF上下文等作用域依赖项上)。

    更新您的 创建用户 方法返回 Task 等待它 外部登录回拨 并且它应该起作用:

    await CreateUser(info);
    
    推荐文章