ASP.Net Identity 2.1 inside MVC5 application using Unity
I am upgrading my ASP.Net MVC5 Application from Identity 1 to 2.1. One day later, I launched it ... but I cannot check the roles for my users (by IsInRole or Authorize Attribute). I assume this is because MVC does not allow user and role manager as 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 an easy way, tutorial or documentation to make Identity 2 work with external dependency injection?
[Edit] Now Unity DI seems to work a bit (thanks to meep).
I modified Startup.Auth.cs by adding ConfigureAuth (IAppBuilder) 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 a declaration for the Singleton container (used above).
In IdentityConfig.cs I omitted the Create method and changed the ctor to
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 users ... but UserManager.GetRoles () is always empty. Also [Authorize (Roles = "myrol") rejects each user ...
source to share
OK ... Thanks everyone! I understood!
While profiling a query on SQL Server (using Express Profiler) I saw that EF tried to join the roles table in the IdentityUser_Id column. Let's go back to the definition of a table in SQL Server. I saw 2 fields: - UserId containing ids - IdentityUser_Id ... always null! So why my roles were always empty!
But why 2 columns theses for the same data?
I have looked at the EF migration file. There were some strange lines here:
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 has been lost. I modified the OnModelCreating method for ApplicationDbContext to help it a bit by specifying where the foreign keys are:
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);
The EF migration file looks better now. I have roles for my users and [Authorize (Role = "xxx")] is working!
source to share