I am creating a system that where a user can have roles optionally assigned against an object.
So, User1 can be a user for most of the system therefore has the "User" Role however i'd like to be able to allow User1 to have an "Admin" role for some entities on the system (these are basically represented by another EF entity called Account).
To do this we have customised the UserRole class by creating our own Class derived from IdentityUserRole and we use this in the IdentityDbContext generic template parameters. This works fine and the additional ObjectId member is present in the EF Core Migrations.
<div> public class ConsoleUserRole : IdentityUserRole<Int64></div> <div> {</div> <div> public String ObjectType { get; set; }</div> <div></div>
<div> public String ObjectID { get; set; }</div> <div> }</div>
The problem is that the composite primary key on the UserId and RoleId is incorrect as now this should include the ObjectId. I tried adding HasKey() using the FluentApi and this changed the Primary key however left a table.UniqueConstraint("AK_AspNetUserRoles_UserId_RoleId",
x => new { x.UserId, x.RoleId }); in the Migrations file which i assume must be the previous Primary key demoted to a constraint.
What happens when i try and create the second entry on the DbSet.
System.InvalidOperationException: 'The instance of entity type 'ConsoleUserRole' cannot be tracked because another instance with the same key value for {'UserId', 'RoleId'} is already being tracked. When attaching existing entities, ensure that only one
entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.'
This must be the UniqueConstraint in the migration.
Yes, I managed to fix this problem by creating my own User Store and Role Store derived from their base class customising the generic parameters where required. In this case the important one was AppUserRole.
public class AppUserStore : UserStore<AppUser, AppRole, ApplicationDbContext, Int64, IdentityUserClaim<Int64>,
AppUserRole, IdentityUserLogin<Int64>, IdentityUserToken<Int64>, IdentityRoleClaim<long>>
{
public ConsoleUserStore(ApplicationDbContext dbContext) : base(dbContext)
{
}
}
public class AppRoleStore : RoleStore<AppRole, ApplicationDbContext, Int64,
AppUserRole, IdentityRoleClaim<Int64>>
{
public AppRoleStore(ApplicationDbContext context) : base(context)
{
}
}
None
0 Points
4 Posts
Customisation of ASP.Net Identity UserRoles
May 10, 2019 03:08 PM|kjporbis|LINK
Hi,
I am creating a system that where a user can have roles optionally assigned against an object.
So, User1 can be a user for most of the system therefore has the "User" Role however i'd like to be able to allow User1 to have an "Admin" role for some entities on the system (these are basically represented by another EF entity called Account).
To do this we have customised the UserRole class by creating our own Class derived from IdentityUserRole and we use this in the IdentityDbContext generic template parameters. This works fine and the additional ObjectId member is present in the EF Core Migrations.
<div> public class ConsoleUserRole : IdentityUserRole<Int64></div> <div> { </div> <div> public String ObjectType { get; set; }</div> <div> </div> <div> public String ObjectID { get; set; }</div> <div> }</div>The problem is that the composite primary key on the UserId and RoleId is incorrect as now this should include the ObjectId. I tried adding HasKey() using the FluentApi and this changed the Primary key however left a table.UniqueConstraint("AK_AspNetUserRoles_UserId_RoleId", x => new { x.UserId, x.RoleId }); in the Migrations file which i assume must be the previous Primary key demoted to a constraint.
What happens when i try and create the second entry on the DbSet.
userRoles.Add(new ConsoleUserRole() { UserId = consoleUser.Id, RoleId = customerAdminRole.Id, ObjectID = "1", ObjectType = "Account" });
userRoles.Add(new ConsoleUserRole() { UserId = consoleUser.Id, RoleId = customerAdminRole.Id, ObjectID = "2", ObjectType = "Account" });
System.InvalidOperationException: 'The instance of entity type 'ConsoleUserRole' cannot be tracked because another instance with the same key value for {'UserId', 'RoleId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.'
This must be the UniqueConstraint in the migration.
The Migrations Builder includes the following...
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<long>(nullable: false),
RoleId = table.Column<long>(nullable: false),
ObjectID = table.Column<string>(nullable: false),
ObjectType = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId, x.ObjectID });
table.UniqueConstraint("AK_AspNetUserRoles_UserId_RoleId", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
If anyone can please point me in the right direction it would be appreciated!
Many Thanks,
Kevin
All-Star
18815 Points
3831 Posts
Re: Customisation of ASP.Net Identity UserRoles
May 13, 2019 02:47 AM|Nan Yu|LINK
Hi kjporbis ,
Why not directly assign that part of users the "Admin" role , you could just adjust to retire roles of current user and write your own logic .
Best Regards,
Nan Yu
None
0 Points
1 Post
Re: Customisation of ASP.Net Identity UserRoles
May 23, 2019 02:04 PM|pdabhi@argusoft.com|LINK
Hi, @kjporbis I have the same problem. Did you manage to find a solution and get past the Entity error?
Thank you for the help.
None
0 Points
4 Posts
Re: Customisation of ASP.Net Identity UserRoles
May 23, 2019 02:34 PM|kjporbis|LINK
Hi,
Yes, I managed to fix this problem by creating my own User Store and Role Store derived from their base class customising the generic parameters where required. In this case the important one was AppUserRole.
public class AppUserStore : UserStore<AppUser, AppRole, ApplicationDbContext, Int64, IdentityUserClaim<Int64>, AppUserRole, IdentityUserLogin<Int64>, IdentityUserToken<Int64>, IdentityRoleClaim<long>>
{
public ConsoleUserStore(ApplicationDbContext dbContext) : base(dbContext)
{
}
}
public class AppRoleStore : RoleStore<AppRole, ApplicationDbContext, Int64, AppUserRole, IdentityRoleClaim<Int64>>
{
public AppRoleStore(ApplicationDbContext context) : base(context)
{
}
}
You then inject these in the Startup.cs
services.AddTransient<IUserStore<ConsoleUser>, ConsoleUserStore>();
services.AddTransient<IRoleStore<ConsoleRole>, ConsoleRoleStore>();
None
0 Points
4 Posts
Re: Customisation of ASP.Net Identity UserRoles
May 24, 2019 07:36 AM|kjporbis|LINK
Sorry, the injecting would be..
services.AddTransient<IUserStore<ConsoleUser>, AppUserStore>();
services.AddTransient<IRoleStore<ConsoleRole>, AppRoleStore>();