13
votes

I want to have list of all the users registered on my site with their roles.

Id | Name | Role


1 | ABC | Admin


2 | DEF | User

Something like this, I have made Roles controller in which all the roles is listed.

 public ActionResult Index()
    {
        var roles = context.Roles.ToList();
        return View(roles);
    }

In View

@model IEnumerable<Microsoft.AspNet.Identity.EntityFramework.IdentityRole>
@{
    ViewBag.Title = "Index";
}    
<div>
    @foreach (var role in Model)
    {
        <p>
            <strong>@role.Name | </strong>
        </p>
    }
</div>

This will list all the roles but i want user's list with their roles.

Please give any solution, Thanks

4
context.Users should have Roles property for each user: var usersWithRoles = context.Users.Select(x => new UserWithRolesViewModel {User = x, UserRoles = x.Roles}).ToList(); - Dmitry Pavliv
Which namespace should i add in the View of this actionResult Method? - Rras
and what is 'UserWithRolesViewModel' after new keyword ? I am sorry for asking such silly things but i am new in MVC development - Rras

4 Answers

12
votes

Create a new class called UserViewModel. This will act as a view model for your page.

public class GroupedUserViewModel
{
    public List<UserViewModel> Users {get; set;}
    public List<UserViewModel> Admins {get; set;}
}

public class UserViewModel
{
    public string Username {get; set;}
    public string Roles {get; set;}
}

In the controller's action method, get the list of users along with their roles and map that to the UserViewModel.

public ActionResult Index()
{
    var allusers = context.Users.ToList();
    var users = allusers.Where(x=>x.Roles.Select(role => role.Name).Contains("User")).ToList();
    var userVM = users.Select(user=>new UserViewModel{Username = user.FullName, Roles = string.Join(",", user.Roles.Select(role=>role.Name))}).ToList();

    var admins = allusers.Where(x=>x.Roles.Select(role => role.Name).Contains("Admin")).ToList();
    var adminsVM = admins.Select(user=>new UserViewModel{Username = user.FullName, Roles = string.Join(",", user.Roles.Select(role=>role.Name))}).ToList(); 
    var model = new GroupedUserViewModel{Users = userVM, Admins = adminsVM};

    return View(model);
}

Then use the new model in the view. Make sure to use correct namespace here where you defined your view model.

@model Models.GroupedUserViewModel
@{
    ViewBag.Title = "Index";
}    
<div>
    @foreach (var user in Model.Admins)
    {
        <p>
            <strong>@user.Username | @user.Roles </strong>
        </p>
    }

    @foreach (var user in Model.Users)
    {
        <p>
            <strong>@user.Username | @user.Roles </strong>
        </p>
    }
</div>
8
votes

Although it is very late to answer this question, but here it is for the future visits:

Create view model class:

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

Then populate this view model class in controller:

var usersWithRoles = (from user in context.Users
                      from userRole in user.Roles
                      join role in context.Roles on userRole.RoleId equals 
                      role.Id
                      select new UserViewModel()
                      {
                          Username = user.UserName,
                          Email = user.Email,
                          Role = role.Name
                      }).ToList();

Here, context.Users represents the AspNetUsers table which has a navigation property Roles which represents the AspNetUserInRoles table. Then we perform join of context.Roles which represents the AspNetRoles table to get the role name.

Now return this list to your Index view:

return View(userWithRoles);

In the view show the list of users with roles:

@model IEnumerable<MyProject.Models.UserViewModel>
<div class="row">
        <h4>Users</h4>

        @foreach (var user in Model)
        {
            <p>
                <strong>
                    @user.Username | @user.Email | @user.Role
                </strong>
            </p>
        }            
</div>

Edit: To get multiple roles of user(if assigned any)

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

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

I have a solution as above.
This is a solution in MVC 6.

In AccountViewModel.cs add models

public class GroupedUserViewModel
{
    public List<UserViewModel> Users { get; set; }
    public List<UserViewModel> Admins { get; set; }
}
public class UserViewModel
{
    public string Username { get; set; }
    public string Email { get; set; }
    public string RoleName { get; set; }
}

the controller is as follows:

    public ActionResult Index()
    {            
        var role = (from r in context.Roles where r.Name.Contains("Adviser") select r).FirstOrDefault();            
        var users = context.Users.Where(x => x.Roles.Select(y => y.RoleId).Contains(role.Id)).ToList();

        var userVM = users.Select(user => new UserViewModel
        {
            Username = user.UserName,
            Email = user.Email,
            RoleName = "Adviser"
       }).ToList();


        var role2 = (from r in context.Roles where r.Name.Contains("Admin") select r).FirstOrDefault();
        var admins = context.Users.Where(x => x.Roles.Select(y => y.RoleId).Contains(role2.Id)).ToList();

        var adminVM = admins.Select(user => new UserViewModel
        {
            Username = user.UserName,
            Email = user.Email,
            RoleName = "Admin"
        }).ToList();


        var model = new GroupedUserViewModel { Users = userVM, Admins = adminVM };
        return View(model); 

    }

finally the view:

@model ToroCRM.Models.GroupedUserViewModel
<div class="row">
        <h4>Users</h4>
        @foreach (var user in Model.Users)
        {
            <p>
                <strong>
                    @user.Username <br />
                    @user.Email<br />
                    @user.RoleName
                </strong>
            </p>
        }
        <h4>Advisers</h4>
        @foreach (var usera in Model.Admins)
        {
            <p>
                <strong>
                    @usera.Username <br />
                    @usera.Email<br />
                    @usera.RoleName
                </strong>
            </p>
        }
</div>
0
votes

I also have a solution as above. This is a solution in MVC 6. the reason for this is i try the above code and faced problems. so..

lets start off Create a new class called UserViewModel. This will act as a view model for your page

public class UserViewModel
{
    public string Username { get; set; }
    public string Email { get; set; }
    public string RoleName { get; set; }
}

The controller is as follows:

public ActionResult Index()
    { 
       List<UserViewModel> modelLst = new List<UserViewModel>();
            var role = _db.Roles.Include(x => x.Users).ToList();

            foreach (var r in role)
            {
                foreach (var u in r.Users)
                {
                    var usr = _db.Users.Find(u.UserId);
                    var obj = new UserViewModel
                    {
                        Username = usr.FullName,
                        Email = usr.Email,
                        RoleName = r.Name
                    };
                    modelLst.Add(obj);
                }

            }
     return View(modelLst); 

    }

finally the view:

@model IEnumerable<ToroCRM.Models.UserViewModel>

<div class="row">
 @foreach (var r in Model.DistinctBy(x=>x.RoleName).ToList())
    {

        <h4>@r.RoleName</h4><hr />
        <table class="table">
        foreach (var user in Model.Where(x=>x.RoleName == r.RoleName))
         {
              <tr><th>@user.Username</th><td>@user.Email</td></tr> 
         }
        </table>

    }
</div>