MaxTheCoder
MaxTheCoder

Reputation: 135

Extending EF Core Identity UserStore with integer user ID

Using Blazor server, dotnet 5 and Entity Framework Core, I have successfully customised Identity using integer IDs

e.g

public class ApplicationUser : IdentityUser<int>
{
    [Required]
    [MaxLength(50)]
    public string FirstName { get; set; }

    [Required]
    [MaxLength(50)]
    public string LastName { get; set; }
}

I now want to extend UserStore for custom login to store password history to prevent duplication. The documented way of doing this seems to be:

public class ApplicationUserStore : UserStore<ApplicationUser>
{
    public ApplicationUserStore(ApplicationDbContext context, IdentityErrorDescriber describer = null) : base(context, describer)
    {
    }

    public override async Task<IdentityResult> CreateAsync(ApplicationUser appUser)
    {
        await base.CreateAsync(appUser);
        await AddToUsedPasswordAsync(appUser, appUser.PasswordHash);
    }

    public Task AddToUsedPasswordAsync(ApplicationUser appuser, string userpassword)  
    {  
        appuser.UserUsedPassword.Add(new UsedPassword() { UserID = appuser.Id, HashPassword = userpassword });  
        return UpdateAsync(appuser);  
    } 
} 

This works for the default GUID Id but when using an integer it throws the error:

The type ApplicationUser cannot be used as type parameter 'TUser' in the generic type or method 'UserStore'. There is no implicit reference conversion from ApplicationUser' to 'Microsoft.AspNetCore.Identity.IdentityUser'.

What is the correct way to do this?

EDIT:

Per @Yinqiu, modified for custom ApplicationRole to

public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, ApplicationDbContext, int> {

    public ApplicationUserStore(ApplicationDbContext context, IdentityErrorDescriber describer = null) : base(context, describer)
    {
    }

Builds successfully and creates users but gives run time error when trying to access ApplicationUserManager.IsInRoleAsync:

{"Cannot create a DbSet for 'IdentityUserRole' because this type is not included in the model for the context."}

However I have a custom User Role:

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

    public bool IsSystemEssential { get; set; }

}

With a definition in ApplicationDbContext :

public DbSet ApplicationUserRoles { get; set; }

Upvotes: 1

Views: 787

Answers (2)

MaxTheCoder
MaxTheCoder

Reputation: 135

SOLVED (provisionally)

After looking at the overloaded inheritance options you have to extend as follows:

public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, ApplicationDbContext, int, ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin, ApplicationUserToken, ApplicationRoleClaim>
{
    public ApplicationUserStore(ApplicationDbContext context, IdentityErrorDescriber describer = null) : base(context, describer)
    {
    }
}

This seems to work. Still need to check all role and claim updates.

Upvotes: 2

Yinqiu
Yinqiu

Reputation: 7190

You can change your ApplicationUserStore as following.

public class ApplicationUserStore : UserStore<ApplicationUser,IdentityRole<int>, ApplicationDbContext,int>
{
    public ApplicationUserStore(ApplicationDbContext context, IdentityErrorDescriber describer = null) : base(context, describer)
    {
    }
    //...
}

Upvotes: 1

Related Questions