Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I extend IdentityRole using Web API 2 + AspNet Identity 2

I am attempting to extend the AspNet IdentityRole class provided in the Web API 2 (With Individual Accounts) template in the latest version of Visual Studio 2013. When I hit /api/roles it returns an empty array

Identity Models

namespace API.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<string, IdentityUserLogin, ApplicationUserRole, IdentityUserClaim>, IUser, IUser<string>
{
    [NotMapped]
    public virtual UserProfile Profile { get; set; }

    public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }

    //public virtual List<ApplicationUserRole> ApplicationRoles { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager,
        string authenticationType)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        ClaimsIdentity userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
        // Add custom user claims here
        return userIdentity;
    }
}

public class ApplicationRole : IdentityRole<string, ApplicationUserRole>
{
    public ApplicationRole() : base() { }

}

public class ApplicationUserRole : IdentityUserRole<string>
{
    public ApplicationUserRole()
        : base()
    { }

    public virtual ApplicationRole Role { get; set; }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser,ApplicationRole,string,IdentityUserLogin,ApplicationUserRole,IdentityUserClaim> 

{

     public ApplicationDbContext()
        : base("DefaultConnection")
    {
        base.Configuration.ProxyCreationEnabled = false;
    }

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

}

Identity Config

namespace API
{
// Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application.

public class ApplicationUserManager : UserManager<ApplicationUser, string>
{
    public ApplicationUserManager(IUserStore<ApplicationUser> store)
        : base(store)
    {
    }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options,
        IOwinContext context)
    {
        var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));

        // 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 = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };
        IDataProtectionProvider dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider =
                new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
        return manager;
    }
}



public class ApplicationRoleManager : RoleManager<ApplicationRole, string>
{
    public ApplicationRoleManager(IRoleStore<ApplicationRole, string> store)
        : base(store)
    {
    }

    public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options,
        IOwinContext context)
    {
        var manager = new ApplicationRoleManager(new RoleStore<ApplicationRole>(context.Get<ApplicationDbContext>()));
        return manager;
    }

}

}

like image 850
Dushan Perera Avatar asked Feb 12 '23 02:02

Dushan Perera


1 Answers

your mistake is in here

ApplicationDbContext : IdentityDbContext<ApplicationUser>

your db context is extent from IdentityDbContext<ApplicationUser> which is base from

IdentityDbContext<TUser, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>

ApplicationDbContext will generate IdentityRole when actualy you want ApplicationRole as your role.

Change your ApplicationDbContext to

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, IdentityUserLogin, ApplicationUserRole, IdentityUserClaim>
{

 public ApplicationDbContext()
    : base("DefaultConnection", false)
 {
    base.Configuration.ProxyCreationEnabled = false;
 }

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

you don't have to overide OnModelCreating and add property Roles in this point.

since you have navigation property in ApplicationUserRole you should add configurationmapping

protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.Entity<ApplicationUserRole>().HasRequired(ur => ur.Role).WithMany().HasForeignKey(ur => ur.RoleId);
}

IdentityModel.cs should be like this :

public class ApplicationUserRole : IdentityUserRole<string>
{
    public ApplicationUserRole()
        : base()
    { }

    public virtual ApplicationRole Role { get; set; }
}

public class ApplicationRole : IdentityRole<string, ApplicationUserRole>
{
    public ApplicationRole() : base() { }

    public ApplicationRole(string name, string description)
        : base()
    {
        this.Name = name;
        this.Description = description;
    }

    public string Description { get; set; }
}

public class ApplicationUser : IdentityUser<string, IdentityUserLogin, ApplicationUserRole, IdentityUserClaim>
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        return userIdentity;
    }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, IdentityUserLogin, ApplicationUserRole, IdentityUserClaim>
{

    public ApplicationDbContext()
        : base("DefaultConnection")
    {
        base.Configuration.ProxyCreationEnabled = false;
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<ApplicationUserRole>().HasRequired(ur => ur.Role).WithMany().HasForeignKey(ur => ur.RoleId);
    }
}

identityconfig.cs should be like this:

public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, string, IdentityUserLogin, ApplicationUserRole, IdentityUserClaim>, IUserStore<ApplicationUser>
{
    public ApplicationUserStore(ApplicationDbContext context)
        : base(context)
    {
    }   
}

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    public ApplicationUserManager(IUserStore<ApplicationUser> store)
        : base(store)
    {
    }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    {
        var manager = new ApplicationUserManager(new ApplicationUserStore(context.Get<ApplicationDbContext>()));
        ....
    }
}
public class ApplicationRoleStore : RoleStore<ApplicationRole, string, ApplicationUserRole>
{
    public ApplicationRoleStore(ApplicationDbContext context)
        : base(context)
    {

    }
}
public class ApplicationRoleManager : RoleManager<ApplicationRole, string>
{
    public ApplicationRoleManager(IRoleStore<ApplicationRole, string> store)
        : base(store)
    {
    }

    public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options,
        IOwinContext context)
    {
        var manager = new ApplicationRoleManager(new ApplicationRoleStore(context.Get<ApplicationDbContext>()));
        return manager;
    }
}
like image 74
Aiska Hendra Avatar answered Feb 15 '23 14:02

Aiska Hendra