I'm developing a Web Api 2.2 application with .NET Framework 4.5.1 and Asp.Net Identity 2.1.0.
I'm not sure what I'm doing, but I want to merge my database with ASP.NET Identity database and I have done this:
My own dbContext
.
public class EFDbContext : IdentityDbContext, IUnitOfWork
My own User
class.
public class User :
IdentityUser<long,
IdentityUserLogin<long>,
IdentityUserRole<long>,
IdentityUserClaim<long>
>
But when I do this:
UserManager<User> _userManager;
I get this error:
The type Data.Models.User
cannot be used as parameter of type TUser
. There isn't any explicit conversion from Data.Models.User
to Microsoft.AspNet.Identity.IUser<string>
.
I'm doing this because I want to have IdentityUser.Id
as long
instead of string
.
How can I fix this error?
UPDATE
After updating UserManager with:
UserManager<User, long> _userManager;
I get the three errors here:
EFDbContext_ctx = context as EFDbContext;
_userManager = new UserManager<User, long>(new UserStore<User>(_ctx));
- The best match of method overload for 'Microsoft.AspNet.Identity.UserManager.UserManager (Microsoft.AspNet.Identity.IUserStore )' has some invalid arguments-
- The type 'Data.Models.User' cannot be used as parameter of type 'TUser' type or generic method
'Microsoft.AspNet.Identity.EntityFramework.UserStore '. There is no conversion from implicit reference from 'Data.Models.User' to 'Microsoft.AspNet.Identity.EntityFramework.IdentityUser'.
- Argument 1: cannot be converted from 'Microsoft.AspNet.Identity.EntityFramework.UserStore' to 'Microsoft.AspNet.Identity.IUserStore'
How can I fix this new error?
Use the other UserManager
UserManager<User, long> _userManager;
You are using this UserManager which:
Represents the user manager for users where the primary key for the user is of type string.
When you extend with your own User class you have to provide all of the types that Identity uses.
Here is my context class, notice that i use string as key:
public class EarlyDetectionContext
: IdentityDbContext<User, Role, string, EDLogin, RoleUserAssociation, EDClaim>
Of course you also need to make classes for role userlogin, userclaim and userroles.
Here is mine:
public class EDClaim : IdentityUserClaim<string>
{
}
public class EDLogin : IdentityUserLogin<string>
{
}
[Table("Roles", Schema = "ED")]
public class Role : IdentityRole<string, RoleUserAssociation>
{
[Required, Column("DisplayName")]
public string DisplayName { get; set; }
[Required, Column("Created")]
public DateTime Created { get; set; }
[Required, Column("Updated")]
public DateTime Updated { get; set; }
[Required, Column("Deleted")]
public bool Deleted { get; set; }
}
[Table("RoleUserAssociations", Schema = "ED")]
public class RoleUserAssociation : IdentityUserRole<string>
{
//
// Due to Identity 2 the Id needs to of string type
//
[Key]
[Required]
public string ID { get; set; }
//[Required, Column("User_Id")]
//public User User { get; set; }
//[Required, Column("Role_Id")]
//public Role Role { get; set; }
[Required, Column("Created")]
public DateTime Created { get; set; }
[Required, Column("Updated")]
public DateTime Updated { get; set; }
[Required, Column("Deleted")]
public bool Deleted { get; set; }
}
[Table("Users", Schema = "ED")]
public class User : IdentityUser<string, EDLogin, RoleUserAssociation, EDClaim>
{
// This is needed for the new Identity 2 framework
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User, string> 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;
}
[Required, Column("Municipality_Id")]
public Municipality Municipality { get; set; }
public string PasswordSalt { get; set; }
[Required, Column("FirstName")]
public string FirstName { get; set; }
[Required, Column("LastName")]
public string LastName { get; set; }
[Column("Title")]
public string Title { get; set; }
[Required, Column("Created")]
public DateTime Created { get; set; }
[Required, Column("Updated")]
public DateTime Updated { get; set; }
[Required, Column("Deleted")]
public bool Deleted { get; set; }
public bool Complete { get; set; }
[Required]
public DateTime Activated { get; set; }
}
You need to specify the key type on every class, in my case a string, in your case a long.
Also notice that my claim and login classes are empty. That's ok, i don't have to add any functionality or properties in my case, but i do need to specify them.
And the GenerateUserIdentityAsync method in the User class is needed to.
In the Startup.Auth.cs file you need to add:
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(EarlyDetectionContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
You also need the OWIN startup class (can be added via Right-click - Add - New Item) and the Identity.cs files.
If you can read German the take a look at this blog
It basically describes what you're trying to do. (with a db-first approach though)
Also watch his video (he speaks good english).
And part 2 of it also.
I hope this gives you enough info to move forward :)