Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding MVC-5 Identity

I created a new ASP.NET MVC-5 application with Individual User Accounts and then updated all the Nuget packages in the solution. Now I'm trying to follow some of the guidelines shown in some tutorials but I encountered some problems. The first one is that a class called ApplicationRoleManager which is being used throughout the application wasn't created (the ApplicationUserManager was created). The second problem is more about Entity-Framework: I've seen that for seeding the database with a user and role many people create a static constructor in the ApplicationDbContext class:

    static ApplicationDbContext()
    {
        Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
    }

So I added it, and the implementation of the ApplicationDbInitializer is:

public class ApplicationDbInitializer : DropCreateDatabaseIfModelChanges<ApplicationDbContext>
{
    protected override void Seed(ApplicationDbContext context)
    {
        InitializeIdentityForEF(context);
        base.Seed(context);
    }

    //Create [email protected] with password=Admin@123456 in the Admin role
    public static void InitializeIdentityForEF(ApplicationDbContext db)
    {
        var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
        var roleManager = HttpContext.Current.GetOwinContext().Get<ApplicationRoleManager>();
        const string name = "[email protected]";
        const string password = "Admin@123456";
        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);
        }
    }

After adding everything I opened the Package Manager Console and typed Enable-Migrations, then Add-Migration someName and then Update-Database. the results were that the database was created successfully but no data was inserted to the database.
After noticing the data wasn't inserted I moved the Seed logic to the Index method of the home controller and the data was inserted after running the application. I also needed to add this line: app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create); to the Startup.Auth.cs file.
So my questions are:

  1. Do I really need to enter the ApplicationRoleManager class manually?
  2. How do I make the seed method work?

UPDATE
I've changed the Seed method to:

protected override void Seed(ApplicationDbContext context)
    {
        var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();

        //since there is no ApplicationRoleManager (why is that?) this is how i create it
        var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));

        const string name = "[email protected]";
        const string password = "Admin@123456";
        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);
        }
        //app hangs here...
        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);
        }
        base.Seed(context);
    }

So now, the Admin role is created but when getting to var user = userManager.FindByName(name); the application hangs with no exception or any message...

like image 605
Yoav Avatar asked Aug 04 '14 14:08

Yoav


1 Answers

When using migrations you can use the built in initializer and the Seed method:

Database.SetInitializer<ApplicationDbContext>(new 
    MigrateDatabaseToLatestVersion<ApplicationDbContext, 
    APPLICATION.Migrations.Configuration>());

and in APPLICATION.Migrations.Configuration (this was created by the Enable-Migrations command):

protected override void Seed(ApplicationDbContext context)
{
    // seed logic
}

As a role manager you can also use the RoleManager<ApplicationRole> base implementation.

like image 58
Christoph Fink Avatar answered Oct 16 '22 04:10

Christoph Fink