asp.net-coreasp.net-identityrazor-pages

List users with roles in a razor page using asp.net 6.0 Identity


I would like to create a Razor Page which lists all users with their associated roles. While I could find some tutorials doing this for previous versions of ASP.NET MVC but I am not able to do this using ASP.NET Core 6.0 Identity Razor pages. Currently, I have the following code but I get an error message when navigating to the page

//UserRolesViewModel.cs file
namespace MyApp.Models
{
    public class UserRolesViewModel
    {
        public string UserName { get; set; }
        public string Email { get; set; }
        public IEnumerable<string> Roles { get; set; }
    }
}

//Index.cshtml.cs file
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using MyApp.Models;

namespace MyApp.Pages.Users
{
    public class IndexModel : PageModel
    {
        private readonly UserManager<IdentityUser> _userManager;
        private readonly RoleManager<IdentityRole> _roleManager;

        public IndexModel
            (
            UserManager<IdentityUser> userManager,
            RoleManager<IdentityRole> roleManager
            )
        {
            _userManager = userManager;
            _roleManager = roleManager;
        }
        public IList<UserRolesViewModel> UserRolesViewModel { get; set; }

        public async Task<IActionResult> OnGetAsync()
        {
            var users = await _userManager.Users.ToListAsync();
            var userRolesViewModel = new List<UserRolesViewModel>();
            foreach (IdentityUser user in users)
            {
                var thisViewModel = new UserRolesViewModel();
                thisViewModel.Email = user.Email;
                thisViewModel.Roles = await GetUserRoles(user);
                userRolesViewModel.Add(thisViewModel);
            }
            return Page();
        }
        private async Task<List<string>> GetUserRoles(IdentityUser user)
        {
            return new List<string>(await _userManager.GetRolesAsync(user));
        }
    }
}

//Index.cshtml file
@page
@model MyApp.Pages.Users.IndexModel

@{
    ViewData["Title"] = "Index";
    Layout = "~/Pages/Shared/_Layout.cshtml";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                User
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model.UserRolesViewModel) {
        <tr>
            @Html.DisplayFor(modelItem => item.Email)
        </tr>
        <td>@string.Join(" , ", item.Roles.ToList())</td>
}
    </tbody>
</table>


//Error message
NullReferenceException: Object reference not set to an instance of an object.
MyApp.Pages.Users.Pages_Users_Index.ExecuteAsync() in Index.cshtml
  @foreach (var item in Model.UserRolesViewModel)

Solution

  • I write a simple demo here, you can refer to it

            [BindProperty]
            public IList<UserRolesViewModel> model { get; set; } = new List<UserRolesViewModel>();
    
            public class UserRolesViewModel
            {
                public string UserName { get; set; }
                public string Email { get; set; }
                public IEnumerable<string> Roles { get; set; }
            }
    
            public async Task<IActionResult> OnGetAsync()
            {
                var users = await _userManager.Users.ToListAsync();
                
                foreach (IdentityUser user in users)
                {
                    UserRolesViewModel urv = new UserRolesViewModel()
                    {
                        UserName = user.UserName,
                        Email = user.Email,
                        Roles = await _userManager.GetRolesAsync(user)
                    };
    
                    model.Add(urv);
                }
                return Page();
            }
    

    page

    @page
    @model IndexModel
    
    @foreach (var item in Model.model) 
    {
           <div>User: @item.UserName</div>
           <div>Email: @item.Email</div>
            @foreach (var role in item.Roles)
           {
               <div>Role: @role</div>
           }
           <br />
    }
    

    result

    enter image description here