如何在ASP.NET MVC 5中列出具有角色名称的用户
我有ASP.NET MVC 5网站的默认项目模板,我试图列出具有角色名称(而不是ID)的所有用户。
查询是:
db.Users.Include(u => u.Roles).ToList()
然后我想用以下内容打印角色名称:
@string.Join(", ", user.Roles.Select(r => r.RoleId))
问题是我只能访问RoleId
,而不能访问存储Name
和其他属性的Role类。
我可以运行另一个select来获取所有角色,然后将其用作查找。 或直接在查询中写一个连接? 我不确定如何,因为我无法访问具有绑定用户和角色的IdentityUserRole
实体的表。
问题的根源似乎是IdentityUserRole
(不是Role
)的Roles集合, RoleId
包含RoleId
和UserId
。
public class IdentityUserRole { public virtual TKey RoleId { get; set; } public virtual TKey UserId { get; set; } }
我认为如果想在EF中建立N对N关系,他们应该直接收集Roles
,然后重写OnModelCreating
并指定关系。 这种方法似乎使从一个对象浏览对象变得复杂。
为什么他们决定将IdentityUserRole
作为额外实体包含在内? 能够在关系中添加额外数据吗? 代价是无法从用户导航到角色?
我这样做的方式是:
using (var userManager = new UserManager(new UserStore (new ApplicationContext())) { var rolesForUser = await userManager.GetRolesAsync(userId); // rolesForUser now has a list role classes. }
身份团队制作了两个管理员: RoleManager
用于排序角色(尽管不是用户角色)和UserManager
基本上用于所有身份validation。 还有一个SignInManager
,但不需要。
因此, UserManager
找到用户,创建用户,删除用户,发送电子邮件….列表继续。
所以我的Action
看起来像这样:
public async Task GetRolesForUser(string userId) { using ( var userManager = new UserManager(new UserStore (new ApplicationDbContext()))) { var rolesForUser = await userManager.GetRolesAsync(userId); return this.View(rolesForUser); } }
要执行原始SQL,您可以执行以下操作:
根据查询的输出创建Entity Framework可以映射到的类:
public class UserWithRole { public string UserName {get;set;} // You can alias the SQL output to give these better names public string Name {get;set;} } using (var context = new DbContext()) { var sql = @" SELECT AspNetUsers.UserName, AspNetRoles.Name FROM AspNetUsers LEFT JOIN AspNetUserRoles ON AspNetUserRoles.UserId = AspNetUsers.Id LEFT JOIN AspNetRoles ON AspNetRoles.Id = AspNetUserRoles.RoleId WHERE AspNetUsers.Id = @Id"; var idParam = new SqlParameter("Id", theUserId); var result = context.Database.ExecuteQuery(sql, idParam); }
很简单!
如果为SQL返回列添加别名:
SELECT AspNetUSers.UserName, AspNetRoles.Name As RoleName
然后你的DTO类看起来像这样:
public class UserWithRole { public string UserName {get;set;} public string RoleName {get;set;} }
这显然更清洁了。
这就是我使用MVC 5,Identity 2.0以及John Atten描述的自定义用户和角色的方法
在控制器中
public virtual ActionResult ListUser() { var users = UserManager.Users; var roles = new List(); foreach (var user in users) { string str = ""; foreach (var role in UserManager.GetRoles(user.Id)) { str = (str == "") ? role.ToString() : str + " - " + role.ToString(); } roles.Add(str); } var model = new ListUserViewModel() { users = users.ToList(), roles = roles.ToList() }; return View(model); }
在ViewModel中
public class ListUserViewModel { public IList users { get; set; } public IList roles { get; set; } }
在我看来
@{ int i = 0; } @foreach (var item in Model.users) { @Html.DisplayFor(modelItem => item.Name) [... Use all the properties and formating you want ... and ] @Model.roles[i] i++; }
我认为从C#应用程序执行动态SQL是一种糟糕的技术。 以下是我的方法:
模型:
public class ApplicationRole : IdentityRole { public ApplicationRole() : base() { } public ApplicationRole(string name) : base(name) { } public string Description { get; set; } }
控制器:
using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; using Microsoft.AspNet.Identity.EntityFramework; using System.Linq; using System.Net; using System.Threading.Tasks; using System.Web; using System.Web.Mvc; using System.Collections.Generic; //Example for Details. if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var role = await RoleManager.FindByIdAsync(id); // Get the list of Users in this Role var users = new List(); // Get the list of Users in this Role foreach (var user in UserManager.Users.ToList()) { if (await UserManager.IsInRoleAsync(user.Id, role.Name)) { users.Add(user); } } ViewBag.Users = users; ViewBag.UserCount = users.Count(); return View(role);
查看(使用ApplicationRole)
Roles.
- @Html.DisplayNameFor(model => model.Name)
- @Html.DisplayFor(model => model.Name)
- @Html.DisplayNameFor(model => model.Description)
- @Html.DisplayFor(model => model.Description)
List of users in this role
@if (ViewBag.UserCount == 0) {
No users found in this role.
} @foreach (var item in ViewBag.Users) { @item.UserName }
using System.Linq; using System.Data; using System.Data.Entity; var db = new ApplicationDbContext(); var Users = db.Users.Include(u => u.Roles); foreach (var item in Users) { string UserName = item.UserName; string Roles = string.Join(",", item.Roles.Select(r=>r.RoleId).ToList()); }
感谢@Callum Linington的回答。 试着让像我这样的初学者有点清楚。 以下是获取具有角色的用户列表的步骤。
1-创建一个名为“UsersWithRoles”的视图模型,其中包含一些属性,如下所示:
2-创建一个名为“RolesController”的控制器,然后在其中添加以下代码。
public ActionResult Index() { using (var context = new ApplicationDbContext()) { var sql = @" SELECT AspNetUsers.UserName, AspNetRoles.Name As Role FROM AspNetUsers LEFT JOIN AspNetUserRoles ON AspNetUserRoles.UserId = AspNetUsers.Id LEFT JOIN AspNetRoles ON AspNetRoles.Id = AspNetUserRoles.RoleId"; //WHERE AspNetUsers.Id = @Id"; //var idParam = new SqlParameter("Id", theUserId); var result = context.Database.SqlQuery(sql).ToList(); return View(result); } }
这是RolesController的样子:
3-将Index页面添加到Roles文件夹,并在其中添加以下代码。
@model IEnumerable Users
User Name Role @foreach (var user in Model) { @user.UserName @user.Role }