C# 如何在ASP.NET MVC 5中列出具有角色名的用户

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来获取所有角色,然后将其用作查找。或者直接在查询中写入

我有ASP.NET MVC 5网站的默认项目模板,我正在尝试列出所有具有角色名(而不是ID)的用户

查询是:

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);
        }

    }