Inherit from IdentityUser I get an error on UserMa

2019-04-30 21:43发布

问题:

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));
  1. The best match of method overload for 'Microsoft.AspNet.Identity.UserManager.UserManager (Microsoft.AspNet.Identity.IUserStore )' has some invalid arguments-
  2. 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'.
  3. Argument 1: cannot be converted from 'Microsoft.AspNet.Identity.EntityFramework.UserStore' to 'Microsoft.AspNet.Identity.IUserStore'

How can I fix this new error?

回答1:

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.



回答2:

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 :)