C# 如何在ASP.NET MVC 5中列出具有角色名的用户
我有ASP.NET MVC 5网站的默认项目模板,我正在尝试列出所有具有角色名(而不是ID)的用户 查询是:C# 如何在ASP.NET MVC 5中列出具有角色名的用户,c#,asp.net-mvc-5,entity-framework-6,asp.net-identity-2,C#,Asp.net Mvc 5,Entity Framework 6,Asp.net Identity 2,我有ASP.NET MVC 5网站的默认项目模板,我正在尝试列出所有具有角色名(而不是ID)的用户 查询是: db.Users.Include(u => u.Roles).ToList() 然后我想打印角色名称,如下所示: @string.Join(", ", user.Roles.Select(r => r.RoleId)) 问题是我只能访问RoleId,而不能访问存储Name和其他属性的角色类 我可以运行另一个select来获取所有角色,然后将其用作查找。或者直接在查询中写入
db.Users.Include(u => u.Roles).ToList()
然后我想打印角色名称,如下所示:
@string.Join(", ", user.Roles.Select(r => r.RoleId))
问题是我只能访问RoleId
,而不能访问存储Name
和其他属性的角色类
我可以运行另一个select来获取所有角色,然后将其用作查找。或者直接在查询中写入联接?我不知道如何操作,因为我无法访问具有将用户和角色绑定在一起的IdentityUserRole
实体的表
问题的根源似乎是IdentityUserRole
(不是Role
)的角色集合,它只包含RoleId
和UserId
public class IdentityUserRole<TKey> {
public virtual TKey RoleId { get; set; }
public virtual TKey UserId { get; set; }
}
public class IdentityUserRole{
公共虚拟TKey RoleId{get;set;}
公共虚拟TKey用户标识{get;set;}
}
我认为如果想要在EF中建立N对N关系,他们应该直接放置角色的集合
,然后覆盖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.
}
要执行原始SQL,可以执行以下操作:
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);
}
}
public class UserWithRole
{
public string UserName {get;set;}
public string RoleName {get;set;}
}
根据查询的输出,创建实体框架可以映射到的类:
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);
}
然后,您的DTO类可以如下所示:
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);
}
}
public class UserWithRole
{
public string UserName {get;set;}
public string RoleName {get;set;}
}
这显然要干净得多。我认为从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);
使用Microsoft.AspNet.Identity;
使用Microsoft.AspNet.Identity.Owin;
使用Microsoft.AspNet.Identity.EntityFramework;
使用System.Linq;
Net系统;
使用System.Threading.Tasks;
使用System.Web;
使用System.Web.Mvc;
使用System.Collections.Generic;
//请举例说明细节。
if(id==null)
{
返回新的HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var role=await rolemager.FindByIdAsync(id);
//获取此角色的用户列表
var users=新列表();
//获取此角色的用户列表
foreach(UserManager.Users.ToList()中的var user)
{
if(等待UserManager.IsInRoleAsync(user.Id,role.Name))
{
用户。添加(用户);
}
}
ViewBag.Users=用户;
ViewBag.UserCount=users.Count();
返回视图(角色);
视图(使用ApplicationRole)
角色。
@DisplayNameFor(model=>model.Name)
@DisplayFor(model=>model.Name)
@DisplayNameFor(model=>model.Description)
@DisplayFor(model=>model.Description)
此角色的用户列表
@如果(ViewBag.UserCount==0)
{
在此角色中找不到用户
}
@foreach(ViewBag.Users中的var项)
{
@item.UserName
}
这就是我如何使用MVC 5、Identity 2.0以及由
在控制器中
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);
}
感谢@Callum Linington的回答。对像我这样的初学者来说,试着说清楚一点。 下面是获取用户及其角色列表的步骤 1-创建一个名为“UsersWithRoles”的视图模型,其某些属性如下所示: 2-创建一个名为“角色控制器”的控制器,然后在其中添加以下代码
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);
}
}
public ActionResult Index()
{
使用(var context=new ApplicationDbContext())
{
var sql=@”
选择AspNetUsers.UserName,AspNetRoles.Name作为角色
来自AspNetUsers
在AspNetUserRoles.UserId=AspNetUsers.Id上左键加入AspNetUserRoles
在AspNetRoles.Id=AspNetUserRoles.RoleId”上左键加入AspNetRoles;
//其中AspNetUsers.Id=@Id”;
//var idParam=新的SqlParameter(“Id”,theUserId);
var result=context.Database.SqlQuery(sql.ToList();
返回视图(结果);
}
}
以下是角色控制器的外观:
3-将索引页添加到角色文件夹,并在其中添加以下代码
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);
}
}
@model IEnumerable
使用者
用户名
角色
@foreach(模型中的var用户)
{
@user.UserName
@用户角色
}
您可以轻松地从用户导航到角色,因为存在多对多关系,所以存在联接表。我不认为身份验证团队只是为了好玩而创建一个垃圾系统。@No1\u Melman能否请您提供一个查询示例(可能作为答案)?谢谢。是的,请给我一分钟的时间回答,但是你从哪里得到的用户角色
DbSet?在默认的IdentityDbContext
中,只有角色
和用户
DbSet,这使得这种连接在我看来是不可能的。是的,我刚刚启动了一个项目来看看,但发现没有什么,这是商业啊,因为在我所有的项目中我都这样做,但我想我已经找到了原因!我明白了,所以没有“好”的方法来进行单个查询。我必须列出用户,然后分别查询每个用户的角色,对吗?我不确定为什么它如此“复杂”“.是的,你会分开做。但是,从速度的角度来看,转到数据库并检索所有用户及其关联角色不是一个好兆头。在网页中,您可能希望
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());
}
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);
}
}