Why does this violate the type constraint?
Asked Answered
E

3

21

I'm trying to customise ASP.NET Identity 3 so that it uses integer keys:

public class ApplicationUserLogin : IdentityUserLogin<int> { }
public class ApplicationUserRole : IdentityUserRole<int> { }
public class ApplicationUserClaim : IdentityUserClaim<int> { }

public sealed class ApplicationRole : IdentityRole<int>
{
  public ApplicationRole() { }
  public ApplicationRole(string name) { Name = name; }
}

public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, ApplicationDbContext, int>
{
  public ApplicationUserStore(ApplicationDbContext context) : base(context) { }
}

public class ApplicationRoleStore : RoleStore<ApplicationRole, ApplicationDbContext, int>
{
  public ApplicationRoleStore(ApplicationDbContext context) : base(context) { }
}

public class ApplicationUser : IdentityUser<int>
{
}

public sealed class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>
{
  private static bool _created;

  public ApplicationDbContext()
  {
    // Create the database and schema if it doesn't exist
    if (!_created) {
      Database.AsRelational().Create();
      Database.AsRelational().CreateTables();
      _created = true;
    }
  }
}

This compiles okay, but then throws a runtime error:

System.TypeLoadException

GenericArguments[0], 'TeacherPlanner.Models.ApplicationUser', on 'Microsoft.AspNet.Identity.EntityFramework.UserStore`4[TUser,TRole,TContext,TKey]' violates the constraint of type parameter 'TUser'.

The signature for UserStore is:

public class UserStore<TUser, TRole, TContext, TKey>
where TUser : Microsoft.AspNet.Identity.EntityFramework.IdentityUser<TKey>
where TRole : Microsoft.AspNet.Identity.EntityFramework.IdentityRole<TKey>
where TContext : Microsoft.Data.Entity.DbContext
where TKey : System.IEquatable<TKey>

ApplicationUser is precisely an IdentityUser<int>. Isn't this what it's looking for?

Elspet answered 3/5, 2015 at 19:1 Comment(1)
Did you by accident declare a new type in your project with the same name as IdentityUser? I do this sometimes by picking "declare type" instead of "add using statement" in CodeRush.Standup
E
45

Ran into this problem. It was crashing on the startup.cs file. changed

services.AddIdentity<ApplicationUser, ApplicationIdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

to

services.AddIdentity<ApplicationUser, ApplicationIdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext,int>()
                .AddDefaultTokenProviders();

declaring the key type seemed to get past the crash

Electrotype answered 4/5, 2015 at 11:26 Comment(1)
I was afraid I`ll have to override all the Identity classes and methods because I have long keys, but everything works with this little fix. Thanks!Cudgel
D
9

Ran into this problem as well. I had to add IdentityRole key type also, because it was still throwing the same error.

        services.AddIdentity<ApplicationUser, IdentityRole<int>>()
            .AddEntityFrameworkStores<ApplicationDbContext,int>()
            .AddDefaultTokenProviders();
Diaconate answered 9/1, 2016 at 20:13 Comment(0)
C
3

Note for EF Core Users

Just to add to the above, if you are using .Net core 3.0 (not sure about earlier versions), there is no longer a AddEntityFrameworkStores<TContext,TKey> method.

Instead there is a generic variant of IdentityDbContext so instead you derive your DbContext from IdentityDbContext<TUser,TRole,TKey>

e.g. in my case

class ApplicationUser : IdentityUser<int> {...}
class ApplicationDbContext : IdentityDbContext<ApplicationUser, IdentityRole<int>, int> {...}

then in your startup you can use services.AddDefaultIdentity<ApplicationUser>

cribbed from the last comment in https://github.com/aspnet/Identity/issues/1082

Calve answered 2/11, 2019 at 18:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.