C#CreateAsync Paralell Identity

时间:2018-06-18 10:00:18

标签: asp.net-mvc thread-safety asp.net-identity factory

  

我尝试从excel导入用户并在表格中显示用户   在MVC观点。

     

为此我有我的上传方法

[HttpPost]
        public async Task<ActionResult> Upload(string postedFile)
        {
            List<Task<UsersImportViewModel>> tasks = new List<Task<UsersImportViewModel>>();
            List<UsersImportViewModel> usersImportViewModel = new List<UsersImportViewModel>();

            if (postedFile != null)
            {
                usersImportViewModel = GetUsersFromSheet(postedFile);

                //  AccountController accControl = new AccountController(userManager, signInManager, loggerService);

                foreach (var user in usersImportViewModel)
                {
                    ApplicationUser appUser = Mapper.Map<UsersImportViewModel, ApplicationUser>(user);

                    tasks.Add(Task.Run(() => CreateNewUser(appUser)));

                }
            }
            var results = await Task.WhenAll(tasks);

            return View("Index", results);
        }





public async Task<UsersImportViewModel> CreateNewUser(ApplicationUser user)
        {
            List<UsersImportViewModel> usersImportViewModel = new List<UsersImportViewModel>();

            var userimportviewModel = Mapper.Map<ApplicationUser, UsersImportViewModel>(user);


            string newPassword = PasswordCreater.CreatePassword(6);
            try
            {

      var result = await UserManager.CreateAsync(user, newPassword);

                    if (result.Succeeded)
                    {

     }
                    else
                    {
                        userimportviewModel.ErrorImport = true;
                        userimportviewModel.Msg = string.Join(",", result.Errors.ToArray());
                        //Error Creaeting user
                    }
                }
                catch (Exception ex)
                {

                }
    }
     

然而,当我调用UserManager.CreateAsync(user,newPassword)时   方法出现错误:

     
    

在上一次异步操作完成之前,在此上下文中启动了第二个操作。使用'await'确保任何     在调用另一个方法之前已完成异步操作     在这种背景下。任何实例成员都不能保证是线程     安全

  
     

我认为原因与使用_user的相同实例有关   经理,我从我当前的课程中获得,如示例中所示   以下

private ApplicationUserManager _userManager;
        public ApplicationUserManager UserManager
        {
            get
            {
                return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                _userManager = value;
            }
        }
     

但是我正在寻求帮助,因为我认为我不应该这样做,我   意思是,用户创建不应该对另一个类负责吗?   除了我为每个实体提供服务,但我无法创建一个   服务来封装身份。

更新1

我通过插入下面的一行解决了这个问题,但我不知道这是否是最优雅的解决方案,我仍然继续解决该方法不属于该控制器的问题

 var userManager = new ApplicationUserManager(new UserStore<ApplicationUser>(new AgendaEntities()));

                var result = await userManager.CreateAsync(user, newPassword);

更新2

现在我有另一个问题,已经在静态类中定义了userManager选项如果我必须再次创建所有内容而只是为每个线程创建一个上下文?

 public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
        {
            var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<AgendaEntities>()));
            // Configure validation logic for usernames
            manager.UserValidator = new UserValidator<ApplicationUser>(manager)
            {
                AllowOnlyAlphanumericUserNames = false,

                RequireUniqueEmail = true,

            };

            // Configure validation logic for passwords
            manager.PasswordValidator = new PasswordValidator
            {
                RequiredLength = 6,
                RequireNonLetterOrDigit = false,
                RequireDigit = false,
                RequireLowercase = false,
                RequireUppercase = false,
            };

            // Configure user lockout defaults
            manager.UserLockoutEnabledByDefault = true;
            manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
            manager.MaxFailedAccessAttemptsBeforeLockout = 5;

            // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
            // You can write your own provider and plug it in here.
            manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
            {
                MessageFormat = "Your security code is {0}"
            });
            manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
            {
                Subject = "Security Code",
                BodyFormat = "Your security code is {0}"
            });
            manager.EmailService = new EmailService();
            manager.SmsService = new SmsService();
            var dataProtectionProvider = options.DataProtectionProvider;
            if (dataProtectionProvider != null)
            {
                manager.UserTokenProvider =
                    new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
            }
            return manager;
        }

更新3

它奏效了,但情况越来越糟。

 var userManager = new ApplicationUserManager(new UserStore<ApplicationUser>(new AgendaEntities()));

                userManager.UserValidator = new UserValidator<ApplicationUser>(userManager)
                {
                    AllowOnlyAlphanumericUserNames = false,

                    RequireUniqueEmail = true,

                };

                var result = await userManager.CreateAsync(user, newPassword);

0 个答案:

没有答案