Search code examples
c#asp.netasp.net-identityasp.net-identity-2

Get the UserManager instance outside of ASP.NET web application?


I have an ASP.NET MVC 5 web app with ASP.NET Identity (Individual Accounts). But I need to be able to register new users from a console app.

So I'm moving some of the ASP.NET Identity classes from the web app into a class library to be shared between the web app and the CLI.

I have successfully moved the following:

public class PortalDbContext : IdentityDbContext<PortalUser>
{
    public PortalDbContext(string connectionString)
        : base(connectionString, throwIfV1Schema: false)
    {
    }

    public static PortalDbContext Create(string connectionString)
    {
        return new PortalDbContext(connectionString);
    }
}

public class PortalUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<PortalUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);

        // Add custom user claims here
        return userIdentity;
    }
}

public class PortalUserManager : UserManager<PortalUser>
{
    public PortalUserManager(IUserStore<PortalUser> store) : base(store)
    {
    }

    public async Task<IdentityResult> RegisterUser(string email, string password)
    {
        PortalUser user = new PortalUser { UserName = email, Email = email };

        return await this.CreateAsync(user, password);
    }
}

But I have no idea where to get the IUserStore<PortalUser> the PortalUserManager needs from.

In the web app, this manager is retrieved from HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>() which I clearly can't use in a class library.


Solution

  • I've ended up adding a static method Create(string connectionString) to PortalUserManager that will create the UserStore and DbContext and return a new instance of the manager.

    public class PortalDbContext : IdentityDbContext<PortalUser>
    {
        public PortalDbContext(string connectionString)
            : base(connectionString, throwIfV1Schema: false)
        {
        }
    
        public static PortalDbContext Create(string connectionString)
        {
            return new PortalDbContext(connectionString);
        }
    }
    
    public class PortalUser : IdentityUser
    {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<PortalUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
    
            // Add custom user claims here
            return userIdentity;
        }
    }
    
    public class PortalUserManager : UserManager<PortalUser>
    {
        public PortalUserManager(IUserStore<PortalUser> store) : base(store)
        {
        }
    
        public static PortalUserManager Create(string connectionString)
        {
            UserStore<PortalUser> userStore = new UserStore<PortalUser>(PortalDbContext.Create(connectionString));
    
            PortalUserManager manager = new PortalUserManager(userStore);
    
            // Configure validation logic for usernames
            manager.UserValidator = new UserValidator<PortalUser>(manager)
            {
                AllowOnlyAlphanumericUserNames = true,
                RequireUniqueEmail = true                
            };
    
            // Configure validation logic for passwords
            manager.PasswordValidator = new PasswordValidator
            {
                RequiredLength = 6,
                RequireNonLetterOrDigit = true,
                RequireDigit = true,
                RequireLowercase = true,
                RequireUppercase = true,
            };
    
            return manager;
        }
    
        public async Task<IdentityResult> RegisterUser(string email, string password)
        {
            PortalUser user = new PortalUser { UserName = email, Email = email };
    
            return await this.CreateAsync(user, password);
        }
    }