How can I extend Identity with custom attributes in ASP.NET MVC?

I seem to have a hate / love relationship for Identity. I like it because it is a complete solution for most applications. But I hate it because renewing is not an easy task. I feel that he is more fit than he should be.

I am trying to add user attributes and foreign keys to my user model, but this seems like a very difficult task.

I need to add a new Identity field called UserId , since Id is the string that will be automatically generated by the database. Then I need to add the foreign key to the Company model and the other to the Location model.

I followed the instructions in the answer from this other question in an attempt to add two new foreign keys and get their value from my controllers.

Here is what I have done so far. My ApplicationUser class after the changes is like this:

 public class ApplicationUser : IdentityUser { [Key] public int MyUserId { get; set; } [ForeignKey("Company")] public int CompanyId { get; set; } [ForeignKey("Location")] public int CurrentLocationId { get; set; } public virtual Company Company { get; set; } public virtual Location Location { get; set; } public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> 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 userIdentity.AddClaim(new Claim("MyUserId", this.MyUserId.ToString() )); userIdentity.AddClaim(new Claim("CompanyId", this.CompanyId.ToString() )); userIdentity.AddClaim(new Claim("CurrentLocationId", this.CurrentLocationId.ToString())); return userIdentity; } } 

I also created an extension class that allows me to get values ​​from such controllers

 public static class IdentityExtensions { public static int GetComapnyId(this IIdentity identity) { var claim = ((ClaimsIdentity)identity).FindFirst("ComapnyId"); // Test for null to avoid issues during local testing return (claim != null) ? Int32.Parse(claim.Value) : 0; } public static int GetCurrentLocationId(this IIdentity identity) { var claim = ((ClaimsIdentity)identity).FindFirst("CurrentLocationId"); // Test for null to avoid issues during local testing return (claim != null) ? Int32.Parse(claim.Value) : 0; } public static int GetMyUserId(this IIdentity identity) { var claim = ((ClaimsIdentity)identity).FindFirst("MyUserId"); // Test for null to avoid issues during local testing return (claim != null) ? Int32.Parse(claim.Value) : 0; } } 

But I ran into the error below when I try to add a new migration

Here is the error

During model generation, one or more validation errors were detected:

ApplicationUser_Claims_Source_ApplicationUser_Claims_Target :: the types of all properties in the dependent role of the reference constraint must be the same as the corresponding property types in the Main role. The property type "MyUserId" for the object "IdentityUserClaim" does not match the property type "MyUserId" on the entity 'ApplicationUser' in the reference constraint 'ApplicationUser_Claims'. ApplicationUser_Logins_Source_ApplicationUser_Logins_Target :: the types of all properties in the dependent role of the reference constraint must be the same as the corresponding property types in the Main role. The property type 'MyUserId' for the 'IdentityUserLogin' object does not match the property type 'MyUserId' on entity 'ApplicationUser' in the reference constraint 'ApplicationUser_Logins'. ApplicationUser_Roles_Source_ApplicationUser_Roles_Target :: The types of all properties of the dependent role of the reference constraint must be the same as the corresponding property types in the Principal Role. The property type "MyUserId" for the object "IdentityUserRole" does not match the property type "MyUserId" for the object "ApplicationUser" in the reference constraint "ApplicationUser_Roles".

This is the command I used to create the InitialCreate migration

 Add-Migration InitialCreate 

How can I add my foreign key and get it correctly from the controllers?

+5
source share
1 answer

Identity has a way to change the primary key (Id field) to int . These are many templates / empty classes, but this works for us. Maybe this will help?

 public class ApplicationUser : IdentityUser<int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim> { [ForeignKey("Company")] public int CompanyId { get; set; } [ForeignKey("Location")] public int CurrentLocationId { get; set; } public virtual Company Company { get; set; } public virtual Location Location { get; set; } public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> 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 userIdentity.AddClaim(new Claim("CompanyId", this.CompanyId.ToString() )); userIdentity.AddClaim(new Claim("CurrentLocationId", this.CurrentLocationId.ToString())); return userIdentity; } } public class ApplicationUserLogin : IdentityUserLogin<int> { } public class ApplicationUserRole : IdentityUserRole<int> { [ForeignKey("RoleId")] public virtual ApplicationRole Role { get; set; } [ForeignKey("UserId")] public virtual ApplicationUser User { get; set; } } public class ApplicationRole : IdentityRole<int, UserRole> { } public class ApplicationUserClaim : IdentityUserClaim<int> { } 

then we also needed a custom ApplicationUserStore as well

 public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim> { public ApplicationUserStore(DbContext context) : base(context) { } } 
0
source

All Articles