boblemar
boblemar

Reputation: 1153

ASP.Net Identity 2.1 inside MVC5 application using Unity

I'm upgrading my ASP.Net MVC5 application from Identity 1 to 2.1. After one day I made it run... but I can't verify roles for my users (by IsInRole or Authorize Attribute). I guess it is because MVC doesn't resolve the user and role manager since my application uses Unity DI and Identity 2 seems to be based on OwinContext with the following configuration :

app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

Is there a simple way, tutorial or documentation to have Identity 2 working with external dependency injection ?

[Edit] Now Unity DI seems to work a little (thanks to meep).

I modified Startup.Auth.cs, adding to ConfigureAuth(IAppBuilder app) function :

var container = UnityConfig.Container;
var dbContext = container.Resolve<ApplicationDbContext>();

container.RegisterInstance<IAppBuilder>(app, new ContainerControlledLifetimeManager());
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>();
container.RegisterType<UserManager<ApplicationUser>, ApplicationUserManager>();
container.RegisterType<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole>>();
container.RegisterType<RoleManager<IdentityRole>, ApplicationRoleManager>();

// [Edit 2]
app.CreatePerOwinContext<ApplicationDbContext>((options, owinContext) => container.Resolve<ApplicationDbContext>());
app.CreatePerOwinContext<UserManager<ApplicationUser>>((options, owinContext) => container.Resolve<UserManager<ApplicationUser>>());
app.CreatePerOwinContext<RoleManager<IdentityRole>>((options, owinContext) => container.Resolve<RoleManager<IdentityRole>>());

In my UnitiConfig.cs file I added the declaration for a Container singleton (used above).

In IdentityConfig.cs, I dropped the Create method and changed the ctor for

public ApplicationUserManager(IUserStore<ApplicationUser> store, ApplicationDbContext dbContext)
        : base(store)
{
    this.Initialize(dbContext);
}

private void Initialize(ApplicationDbContext dbContext)
{
    // Configurer la logique de validation pour les noms d'utilisateur
    this.UserValidator = new UserValidator<ApplicationUser>(this)
    {
        AllowOnlyAlphanumericUserNames = false,
        RequireUniqueEmail = true
    };
    // ... more code...
}

public class ApplicationRoleManager : RoleManager<IdentityRole>
{
    public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
        : base(roleStore)
    {
    }
}

I can authenticate the users... but UserManager.GetRoles() is always empty. Moreover [Authorize(Roles="myrole"] rejects every user...

Upvotes: 3

Views: 3856

Answers (1)

boblemar
boblemar

Reputation: 1153

OK... Thank you all ! I got it !

By profiling the query send to SQL Server (using Express Profiler) I saw that EF tryed to join Roles Table On a column named IdentityUser_Id. Back to the table definition in SQL Server I saw 2 fields : - UserId containing the ids - IdentityUser_Id... always null ! So that's why my Roles were always empty !

But why theses 2 columns for the same data ?

I took a look at the EF migration file. Here were some strange lines :

RenameColumn(table: "dbo.T_Securite_AspNetUserClaims", name: "User_Id", newName: "IdentityUser_Id");
AddColumn("dbo.T_Securite_AspNetUserLogins", "IdentityUser_Id", c => c.String(maxLength: 128));
AddColumn("dbo.T_Securite_AspNetUserRoles", "IdentityUser_Id", c => c.String(maxLength: 128));

So it looks like the EF Migration generator was lost. I changed the OnModelCreating method for ApplicationDbContext to help it a little by telling where the foreign keys are actually :

modelBuilder.Entity<IdentityUser>()
            .ToTable("T_Security_AspNetUsers"); // Yes... I changed the table name : maybe the source of the problem !

modelBuilder.Entity<IdentityUser>()
            .HasMany(u => u.Roles)
            .WithOptional()
            .HasForeignKey(r => r.UserId);

modelBuilder.Entity<IdentityUser>()
            .HasMany(u => u.Logins)
            .WithOptional()
            .HasForeignKey(l => l.UserId);

modelBuilder.Entity<IdentityUser>()
            .HasMany(u => u.Claims)
            .WithOptional()
            .HasForeignKey(c => c.UserId);

Now the EF Migration file is looking better. I have roles for my users and the [Authorize(Role="xxx")] seems to work !

Upvotes: 4

Related Questions