userManager.CreateAsync System.ObjectDisposedException не обработан

Мы пытаемся использовать проверку подлинности учетной записи Microsoft в проекте ASP.Net 5. Мы не требуем локальной аутентификации и не требуем имен пользователей.

В шаблоне ASP.Net 5 для веб-приложения после входа в систему с внешним поставщиком элемент управления возвращается к ExternalLoginCallback в AccountController.

Если пользователь не зарегистрирован локально ExternalLoginCallback возвращает пользователя на экран регистрации. Я пытался изменить ExternalLoginCallback для автоматической регистрации нового пользователя, как показано ниже.

        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 ответ

Решение

Используя async void метод редко является хорошей идеей и является лучшим способом представить странные условия гонки, подобные той, которую вы испытываете: так как ваш CreateUser метод не возвращает задачу, его нельзя ожидать ExternalLoginCallback и запрос завершается раньше CreateUser есть время для выполнения операций с базой данных (когда запрос завершается, системный вызов DI Dispose на зависимостях области действия, таких как ваш контекст EF).

Обновите свой CreateUser способ вернуть Task и ждать его от ExternalLoginCallback и это должно работать:

await CreateUser(info);
Другие вопросы по тегам