首页 > 解决方案 > 如何显示具有角色的用户列表 - ASP.NET (Core)

问题描述

我正在尝试将每个用户的角色包含在列表中,如下图所示。在 Index 方法中,我想将用户加入角色并将其发送到视图。但是由于某种原因user.Roles没有被识别。因此,似乎缺少导航属性。我在下面添加了一个屏幕截图,以更清楚地说明我的问题。我一直在关注一些指南,它们似乎都可以user.Roles毫无问题地使用。

代码对我来说似乎是正确的,我在这里缺少什么吗?

在此处输入图像描述

帐户控制器

private AppIdentityDbContext context;

public AccountController(AppIdentityDbContext _context)
{
    context = _context;
}

public IActionResult Index()
{
    var usersWithRoles = (from user in context.Users
        select new
        {
            Username = user.UserName,
            Email = user.Email,
            RoleNames = (from userRole in user.Roles
                join role in context.Roles on userRole.RoleId
                    equals role.Id
                select role.Name).ToList()
        }).ToList().Select(p => new UsersViewModel()

    {
        Username = p.Username,
        Email = p.Email,
        Role = string.Join(",", p.RoleNames)
    });

    return View(usersWithRoles);
}

用户视图模型

public class UsersViewModel
{
    public string Username { get; set; }
    public string Email { get; set; }
    public string Role { get; set; }
}

应用用户

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

AppIdentityDbContext

public class AppIdentityDbContext : IdentityDbContext<ApplicationUser>
{
    public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options)
        : base(options) { }
}

AppDbContext

public class AppDbContext : DbContext
{

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(
            "Server=(localdb)\\MSSQLLocalDB;Database=Local;MultipleActiveResultSets=true");
    }

我得到错误:

在此处输入图像描述

标签: c#entity-frameworkasp.net-coreasp.net-identity

解决方案


根据您的代码,您似乎正在使用带有自定义自定义用户数据和角色的Asp.net Core Identity 。

首先,请检查 Startup.ConfigureServices 方法,确保您已将角色添加到 ApplicationUser。像这样:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));

        services.AddIdentity<ApplicationUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = true)
                 .AddDefaultUI()
                 .AddEntityFrameworkStores<ApplicationDbContext>()
                 .AddDefaultTokenProviders();

        //or using the following code.
        //services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
        //    .AddRoles<IdentityRole>()
        //    .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddControllersWithViews();
        services.AddRazorPages();

    }

您可以参考这篇文章来了解如何使用 asp.net Core 身份添加角色。

然后,在控制器中,您可以使用UserManager.GetRolesAsync方法获取指定用户所属的角色名称列表。像这样的代码:

public class ApplicationUserController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;

    private readonly ApplicationDbContext _context;
    public ApplicationUserController(UserManager<ApplicationUser> usermanager, ApplicationDbContext context)
    {
        _userManager = usermanager;
        _context = context;
    }
    public IActionResult Index()
    {
        var users = _userManager.Users.Select(c => new UsersViewModel()
        {
            Username = c.UserName,
            Email = c.Email,
            Role = string.Join(",", _userManager.GetRolesAsync(c).Result.ToArray())
        }).ToList();

        return View(users);
    }
}

结果是这样的:

在此处输入图像描述

此外,在使用 Asp.net Identity 时,数据库将使用 AspNetUserRoles 表来存储 AspNetUsers 表和 AspNetRoles 表之间的关系(您可以使用SQL Server Management Studio检查数据库表)。如果您不想使用 UserManager 来获取用户的角色,您可以加入 AspNetUsers、AspNetUserRoles 和 AspNetRoles 表并查询数据库并获取所需的属性。代码如下:

public class ApplicationUserController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;

    private readonly ApplicationDbContext _context;
    public ApplicationUserController(UserManager<ApplicationUser> usermanager, ApplicationDbContext context)
    {
        _userManager = usermanager;
        _context = context;
    }
    public IActionResult Index()
    { 
        var result = _context.Users
            .Join(_context.UserRoles, u => u.Id, ur => ur.UserId, (u, ur) => new { u, ur })
            .Join(_context.Roles, ur => ur.ur.RoleId, r => r.Id, (ur, r) => new { ur, r }) 
            .Select(c => new UsersViewModel()
            {
                Username = c.ur.u.UserName,
                Email = c.ur.u.Email,
                Role = c.r.Name
            }).ToList().GroupBy(uv=> new { uv.Username, uv.Email }).Select(r=> new UsersViewModel()
            {
                Username = r.Key.Username,
                Email = r.Key.Email,
                Role = string.Join(",", r.Select(c=>c.Role).ToArray())
            }).ToList();

        // you could also use the following code:
        var result2 = _context.Users
        .Join(_context.UserRoles, u => u.Id, ur => ur.UserId, (u, ur) => new { u, ur })
        .Join(_context.Roles, ur => ur.ur.RoleId, r => r.Id, (ur, r) => new { ur, r })
        .ToList()
        .GroupBy(uv => new { uv.ur.u.UserName, uv.ur.u.Email }).Select(r => new UsersViewModel()
        {
            Username = r.Key.UserName,
            Email = r.Key.Email,
            Role = string.Join(",", r.Select(c => c.r.Name).ToArray())
        }).ToList();

        return View(result);
    }
}

通过使用上面的 linq 命令,我们也可以得到相同的结果。

在此处输入图像描述

附加资源:

数据库上下文:

public class ApplicationDbContext : IdentityDbContext
{
    public DbSet<ApplicationUser> ApplicationUsers { get; set; }
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
    }
}

public class ApplicationUser: IdentityUser
{
    public int Age { get; set; }
    public string CustomTag { get; set; }
}

推荐阅读