Reputation: 145
At first I have a table of users from userManager
where I can search and sort by username. The original table is following microsoft .net tutorial
but now I am trying join the role of each user from roleManager
. Tried to look for other solution in stackoverflow but I couldn't implement them into my code below. How should I revise my code to get the result from user from userManager
and role from roleManager
in one table?
public async Task<IActionResult> ListUsers(string sortOrder, string currentFilter, string searchString, int? pageNumber, string name)
{
ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "userid" : "username";
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";
var users = userManager.Users;
if (searchString != null)
{
pageNumber = 1;
}
else
{
searchString = currentFilter;
}
if (!String.IsNullOrEmpty(searchString))
{
users = userManager.Users.Where(u => u.Name.Contains(searchString));
}
switch (sortOrder)
{
case "userid":
users = users.OrderByDescending(s => s.UserName);
break;
case "username":
users = users.OrderByDescending(s => s.Name);
break;
case "Date":
users = users.OrderBy(s => s.BirthDate);
break;
case "date_desc":
users = users.OrderByDescending(s => s.BirthDate);
break;
default:
users = users.OrderBy(s => s.UserName);
break;
}
int pageSize = 50;
return View(await PaginatedList<ApplicationUser>.CreateAsync(users.AsNoTracking(), pageNumber ?? 1, pageSize));
//return View(await users.AsNoTracking().ToListAsync());
}
Upvotes: 3
Views: 5985
Reputation: 12695
In default ASP.NET Core Identity , the relationship between User and Role is many-to-many. And in EF Core ,you should represent a many-to-many relationship by including an entity class for the join table and mapping two separate one-to-many relationships.
For getting all users with their associated roles , this comment on GitHub issue seems to be the current solution for .Net Core . Here is a working demo :
ApplicationUser
public class ApplicationUser:IdentityUser<string>
{
public string Name { get; set; }
public DateTime BirthDate { get; set; }
public ICollection<ApplicationUserRole> UserRoles { get; set; }
}
ApplicationRole
public class ApplicationRole : IdentityRole
{
public ICollection<ApplicationUserRole> UserRoles { get; set; }
}
ApplicationUserRole
public class ApplicationUserRole : IdentityUserRole<string>
{
public virtual ApplicationUser User { get; set; }
public virtual ApplicationRole Role { get; set; }
}
ApplicationDbContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, IdentityUserClaim<string>,
ApplicationUserRole, IdentityUserLogin<string>,
IdentityRoleClaim<string>, IdentityUserToken<string>>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationUserRole>(userRole =>
{
userRole.HasKey(ur => new { ur.UserId, ur.RoleId });
userRole.HasOne(ur => ur.Role)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.RoleId);
userRole.HasOne(ur => ur.User)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.UserId);
});
}
}
Startup.cs
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();
Controller
var users = _userManager.Users
.Include(u=>u.UserRoles)
.ThenInclude(ur=>ur.Role).AsNoTracking();
Microsoft doc on multi-level eager loading: https://learn.microsoft.com/en-us/ef/core/querying/related-data#including-multiple-levels
View
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.BirthDate)
</td>
<td>
@foreach (var userRole in item.UserRoles)
{
<p>@Html.DisplayFor(model=>userRole.Role.Name) </p>
}
</td>
</tr>
}
Result:
Upvotes: 3