2017-06-12 4 views
0

Il y a quelques mois, j'ai créé ma propre implémentation de l'identité ASP.NET, remplaçant le UserStore pour utiliser dapper et une connexion SQL personnalisée au lieu de Entity Framework. Cela a bien fonctionné à l'époque.Est-ce que ASP.NET Identity UserManager.CreateAsync() a été mis à jour avec des modifications de rupture récemment?

Maintenant j'ai mis à jour tous les paquets de nuget aujourd'hui et j'ai lutté contre des problèmes depuis. Principalement quand j'enregistrer un nouvel utilisateur en appelant var result = await UserManager.CreateAsync(user, newAccount.Password); Il crée l'utilisateur et effectue tous les autres contrôles très bien, mais alors une erreur jette bizarre en disant Invalid operation. The connection is closed.

Son comme si UserManager.CreateAsync a une nouvelle méthode qui doit être surchargée, mais je n'ai absolument aucune idée de ce que cela pourrait être.

Pour référence, voici les parties de ma mise en œuvre:

compte du contrôleur:

 [Authorize] 
      public class AccountController : Controller 
      { 

       public UserManager<User> UserManager { get; private set; } 
       public UserTokenProvider UserTokenProvider { get; set; } 

       public AccountController() : this(new UserManager<User>(new UserStore(ConfigurationManager.ConnectionStrings["DBConn"].ConnectionString))) 
       { 
       } 

       public AccountController(UserManager<User> userManager) 
       { 
        UserManager = userManager; 
        UserManager.PasswordHasher = new NoPasswordHasher(); 

       } 

... 

     [HttpPost] 
     [AllowAnonymous] 
     [ValidateAntiForgeryToken] 
     public async Task<ActionResult> Register(RegistrationModel newAccount) 
     { 
      try 
      { 
       if (DbConfig.MaintenanceMode) return RedirectToAction("ComingSoon", "Home"); 
       if (ModelState.IsValid) 
       { 
        var user = new User(newAccount); 

        var result = await UserManager.CreateAsync(user, newAccount.Password); 
        if (result.Succeeded) 
        { 
         await SignInAsync(user, isPersistent: false); 
         var userIn = await UserManager.FindByEmailAsync(newAccount.UserName); 
         if (!userIn.EmailConfirmed) 
         { 
          await SendValidationEmail(userIn); 
          return RedirectToAction("ConfirmationSent", new {userName = user.UserName}); 
         } 
         return RedirectToAction("Index", "Home"); 
        } 
        else 
        { 
         AddErrors(result); 
        } 
       } 

       // If we got this far, something failed, redisplay form 
       return View(newAccount); 
      } 
      catch (Exception ex) 
      { 
       var msg = ex.Message; 

       return View(newAccount); 
      } 
     } 

Store utilisateur:

public class UserStore : IUserStore<User>, IUserLoginStore<User>, IUserPasswordStore<User>, IUserSecurityStampStore<User>, IUserRoleStore<User>, IUserEmailStore<User> 
     { 
      private readonly string _dbConn; 


      public UserStore(string conn = null) 
      { 
       if (conn != null) 
        _dbConn = conn; 
       else 
        _dbConn = DbConfig.ConnectionString; 
      } 

      public void Dispose() 
      { 
      } 



      public virtual Task CreateAsync(User user) 
      { 
       using (var _conn = new SqlConnection(_dbConn)) 
       { 
        if (_conn.State == ConnectionState.Closed) _conn.Open(); 
        return _conn.ExecuteAsync("users_UserCreate", 
         new 
         { 
          @UserId = user.Id, 
          @UserName = user.UserName, 
          @PasswordHash = user.PasswordHash, 
          @SecurityStamp = user.SecurityStamp 
         }, commandType: CommandType.StoredProcedure); 

       } 
      } 

... Remaining methods omitted for brevity ... 

Vous remarquerez que le UserStore. La fonction CreateAsync() a if (_conn.State == ConnectionState.Closed) _conn.Open(); car c'était la suggestion à partir de plusieurs threads concernant la connexion fermée erreur. Même sans cette ligne, la requête fonctionne correctement et insère correctement un nouvel utilisateur dans la base de données.

L'erreur provient de quelque part après UserStore.CreateAsync() est appelée par UserManager.CreateAsync().

Une idée de ce qui manque?

Répondre

0

La réponse est non, ASP.NET Identity n'a pas changé avec des changements de rupture. Utilisation de DotNetPeek J'ai regardé la bibliothèque d'identité pour voir quelles méthodes étaient appelées pendant UserManager.CreateAsync() et elle appelle uniquement UserStore.CreateSync et une mise à jour du mot de passe. Après avoir joué avec le code, je me suis rendu compte que pendant que UserManager.CreateSync est attendu, les appels internes à UserStore.CreateSync ne le sont pas. Réservé à devoir surcharger public virtual Task CreateAsync(User user) et devoir retourner une tâche qui n'est pas attendue, nous devons jongler avec du code pour attendre la réponse de Dapper avant de le renvoyer dans le cadre d'une tâche. Donc, voici le remplacement de UserStore.CreateAsync qui fonctionne. Note: if (_conn.State == ConnectionState.Closed) _conn.Open(); n'est pas réellement nécessaire car la connexion était fermée avant que la méthode ait fini, Dapper fait un excellent travail de gestion des connexions pour vous.

public virtual Task CreateAsync(User user) 
{ 
    using (var _conn = new SqlConnection(_dbConn)) 
    { 
     var result = _conn.ExecuteAsync("users_UserCreate", new 
        { 
         @UserId = user.Id, 
         @UserName = user.UserName, 
         @PasswordHash = user.PasswordHash, 
         @SecurityStamp = user.SecurityStamp 
        }, commandType: CommandType.StoredProcedure).ConfigureAwait(true); 

     return Task.FromResult(result); 
    } 
} 

Espérons que cela aidera quelqu'un d'autre à faire face au même genre de problème.