user5241307
user5241307

Reputation:

ASP.NET Identity with MySQL database - How to add Admin user on start?

I have finished doing this tutorial/sample, on how to use MySQL database with ASP.NET identity:
http://www.asp.net/identity/overview/getting-started/aspnet-identity-using-mysql-storage-with-an-entityframework-mysql-provider
Now I would like to add functionality wich creates Admin user on start with role Admin. In the past I was using SimpleMembership and local 'SQL Server Database'and it was quite simple, now I'm trying to do this by adding user in 'MySqlInitializer'. Here's a code I'm trying to make work:

MySqlInitializer

    namespace IdentityMySQLDemo
{
    public class MySqlInitializer : IDatabaseInitializer<ApplicationDbContext>
    {
        public void InitializeDatabase(ApplicationDbContext context)
        {
            if (!context.Database.Exists())
            {
                // if database did not exist before - create it
                context.Database.Create();
            }
            else
            {
                // query to check if MigrationHistory table is present in the database 
                var migrationHistoryTableExists = ((IObjectContextAdapter)context).ObjectContext.ExecuteStoreQuery<int>(
                string.Format(
                  "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '{0}' AND table_name = '__MigrationHistory'",
                  "17817412_kontadb"));

                // if MigrationHistory table is not there (which is the case first time we run) - create it
                if (migrationHistoryTableExists.FirstOrDefault() == 0)
                {
                    context.Database.Delete();
                    context.Database.Create();
                }
            }
            Seed(context);
        }

        protected void Seed(ApplicationDbContext context)
        {
            var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
            var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
            const string name = "[email protected]";
            const string password = "Password";
            const string roleName = "Admin";

            //Create Role Admin if it does not exist
            var role = roleManager.FindByName(roleName);
            if (role == null)
            {
                role = new IdentityRole(roleName);
                var roleresult = roleManager.Create(role);
            }

            var user = userManager.FindByName(name);
            if (user == null)
            {
                user = new ApplicationUser { UserName = name, Email = name };
                var result = userManager.Create(user, password);
                result = userManager.SetLockoutEnabled(user.Id, false);
            }

            // Add user admin to Role Admin if not already added
            var rolesForUser = userManager.GetRoles(user.Id);
            if (!rolesForUser.Contains(role.Name))
            {
                var result = userManager.AddToRole(user.Id, role.Name);
            }
        }
    }
}

IdentityModels

using System.Data.Entity;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace IdentityMySQLDemo.Models
{
    // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
    public class ApplicationUser : IdentityUser
    {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> 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 ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        static ApplicationDbContext()
        {
          Database.SetInitializer(new MySqlInitializer());
        }

        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
    }
}

I don't know why it don't want to create Admin user on application start, I was trying to move this code to "Configuration" or 'MySQLConfiguration" in Migrations folder. I was also trying to create all table first and than add Admin user with this, but it still didn't work. Please tell me where is my stupid mistake in this code?

Upvotes: 3

Views: 4681

Answers (1)

Chris
Chris

Reputation: 637

It looks like ther maybe a missing context.SaveChanges() or three.

Is the problem with your seed method? If the issue is when your running your update-database command in the NuGet package manager console, if there is no call to context.SaveChanges() then it won't update the DB.

You'll also need to call it 3 times..

  • after the role is created
  • after the user is created
  • after the user is assigned to the role

I'm a relatively newbie myself to C# / ASP.NET MVC so am not 100% if this is the correct fix as unable to test my thoughts currently, but seems to be a similar problem I've faced in the past.

UPDATE

I've had a play around and this successfully updated the 3 tables as part of the seed method.

I think one of the other problems is that rather than calling a method in a couple of places, you were just assigning them into a variable and then not using. For example in this snippet:

        var rolesForUser = userManager.GetRoles(user.Id);
        if (!rolesForUser.Contains(role.Name))
        {
            var result = userManager.AddToRole(user.Id, role.Name);
        }

I changed it to:

        var rolesForUser = userManager.GetRoles(user.Id);
        if (!rolesForUser.Contains(role.Name))
        {
            userManager.AddToRole(user.Id, role.Name);
        }

Thus removing var result =

Here is the full code:

    protected override void Seed( MySqlInitializer context)
    {
        var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext("DefaultConnection")));
        var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext("DefaultConnection")));
        const string name = "[email protected]";
        const string password = "Password";
        const string roleName = "Admin";

        //Create Role Admin if it does not exist
        var role = roleManager.FindByName(roleName);
        if (role == null)
        {
            role = new IdentityRole(roleName);
            roleManager.Create(role);
        }
        context.SaveChanges();
        var user = userManager.FindByName(name);
        if (user == null)
        {
            user = new ApplicationUser { UserName = name, Email = name };
            userManager.Create(user, password);
            userManager.SetLockoutEnabled(user.Id, false);
        }
        context.SaveChanges();
        // Add user admin to Role Admin if not already added
        var rolesForUser = userManager.GetRoles(user.Id);
        if (!rolesForUser.Contains(role.Name))
        {
            userManager.AddToRole(user.Id, role.Name);
        }
        context.SaveChanges();
    }

In some ways I would like to thank you as by helping you, I've helped myself :)

Upvotes: 3

Related Questions