[英]How to list users with role names in 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<TKey> {
public virtual TKey RoleId { get; set; }
public virtual TKey UserId { get; set; }
}
我認為如果想在EF中建立N對N關系,他們應該直接收集Roles
,然后重寫OnModelCreating
並指定關系。 這種方法似乎使從一個對象瀏覽對象變得復雜。
為什么他們決定將IdentityUserRole
作為額外實體包含在內? 能夠在關系中添加額外數據嗎? 代價是無法從用戶導航到角色?
我這樣做的方式是:
using (var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationContext()))
{
var rolesForUser = await userManager.GetRolesAsync(userId);
// rolesForUser now has a list role classes.
}
身份團隊制作了兩個管理員: RoleManager
用於排序角色(盡管不是用戶角色)和UserManager
基本上用於所有身份驗證。 還有一個SignInManager
,但不需要。
因此, UserManager
找到用戶,創建用戶,刪除用戶,發送電子郵件....列表繼續。
所以我的Action
看起來像這樣:
public async Task<ActionResult> GetRolesForUser(string userId)
{
using (
var userManager =
new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(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<UserWithRole>(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<string>();
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<YourAppNamespace.Models.ApplicationUser> users { get; set; }
public IList<string> 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<ApplicationUser>();
// 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)
<div>
<h4>Roles.</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd>
@Html.DisplayFor(model => model.Name)
</dd>
</dl>
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Description)
</dt>
<dd>
@Html.DisplayFor(model => model.Description)
</dd>
</dl>
</div>
<h4>List of users in this role</h4>
@if (ViewBag.UserCount == 0)
{
<hr />
<p>No users found in this role.</p>
}
<table class="table">
@foreach (var item in ViewBag.Users)
{
<tr>
<td>
@item.UserName
</td>
</tr>
}
</table>
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<UserWithRoles>(sql).ToList();
return View(result);
}
}
這是RolesController的樣子:
3-將Index頁面添加到Roles文件夾,並在其中添加以下代碼。
@model IEnumerable<MVC_Auth.ViewModels.UserWithRoles> <div class="row"> <h4>Users</h4> <table class="table table-hover table-responsive table-striped table-bordered"> <th>User Name</th> <th>Role</th> @foreach (var user in Model) { <tr> <td>@user.UserName</td> <td>@user.Role</td> </tr> } </table> </div>
這是結果
謝謝。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.