13

How to obtain a list of all users in a role? Before it was possible with Roles.GetUsersInRole, but with new Identity I can't find anything like this.

graycrow
  • 3,675
  • 6
  • 26
  • 28
  • 1
    It may be phenomenally expensive to discover the members of a role, including repeated remote queries to whatever data stores are actually supporting the identities that you're accepting - even if those stores *support* such a query. Try turning things on their head - why do you need to know all of the members of the role? (and bear in mind that as soon as your system has this information, it may be out of date) – Damien_The_Unbeliever Oct 21 '13 at 09:19
  • 1
    @Damien_The_Unbeliever: I need to migrate an application from old Membership to new Identity. For example, I need to have a list of users in the admin role to send an email to all of them. Now I trying to imagine a database query for that and looks like it's simple query with one inner join. Maybe I'm missing a lot, but I don't understand why this is phenomenally expensive. So, I always can do this through db context, but just wonder why framework do not offer this functionality. – graycrow Oct 21 '13 at 09:49
  • I said it *may* be expensive - not all scenarios for the use of the identity system have the roles stored in an SQL database. – Damien_The_Unbeliever Oct 21 '13 at 10:01

7 Answers7

12

I didn't see a built in way, but it is fairly easy to implement. I have this method in my application specific UserManager:

public IQueryable<User> GetUsersInRole(string roleName)
{
    return from user in Users
           where user.Roles.Any(r => r.Role.Name == roleName)
           select user;
}

The SQL it output seemed reasonable:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Email] AS [Email], 
[Extent1].[EmailConfirmed] AS [EmailConfirmed], 
[Extent1].[PasswordHash] AS [PasswordHash], 
[Extent1].[SecurityStamp] AS [SecurityStamp], 
[Extent1].[PhoneNumber] AS [PhoneNumber], 
[Extent1].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed], 
[Extent1].[TwoFactorEnabled] AS [TwoFactorEnabled], 
[Extent1].[LockoutEndDateUtc] AS [LockoutEndDateUtc], 
[Extent1].[LockoutEnabled] AS [LockoutEnabled], 
[Extent1].[AccessFailedCount] AS [AccessFailedCount], 
[Extent1].[UserName] AS [UserName]
FROM [dbo].[AspNetUsers] AS [Extent1]
WHERE  EXISTS (SELECT 
    1 AS [C1]
    FROM  [dbo].[AspNetUserRoles] AS [Extent2]
    INNER JOIN [dbo].[AspNetRoles] AS [Extent3] ON [Extent2].[RoleId] = [Extent3].[Id]
    WHERE ([Extent1].[Id] = [Extent2].[UserId]) AND ([Extent3].[Name] = @p__linq__0)
)
ChoptimusPrime
  • 433
  • 7
  • 15
11

For some reason, very nice query suggested above by @ChoptimusPrime did not compile for me in ASP.NET Identity 2.2.1. I have written an extended function:

public static IQueryable<User> GetUsersInRole(DbContext db, string roleName)
{
  if (db != null && roleName != null)
  {
    var roles = db.Roles.Where(r => r.Name == roleName);
    if (roles.Any())
    {
      var roleId = roles.First().Id;
      return from user in db.Users
             where user.Roles.Any(r => r.RoleId == roleId)
             select user;
    }
  }
  return null;
}
Boris Zinchenko
  • 2,142
  • 1
  • 24
  • 34
5

for example if you want users list with role "User"

var users = await (from user in _dbContext.Users
                                 join userRole in _dbContext.UserRoles
                                 on user.Id equals userRole.UserId
                                 join role in _dbContext.Roles 
                                 on userRole.RoleId equals role.Id
                                 where role.Name == "User" 
                                 select user)
                                 .ToListAsync();
Omid Soleiman
  • 246
  • 3
  • 8
4

Its not possible via the RoleManager in 1.0 RTM, in 1.1 it will exposed via an IQueryable RoleManager.Roles. For 1.0, you need to drop down to the implementation layer (i.e. db context)

Hao Kung
  • 28,040
  • 6
  • 84
  • 93
0

You could use the Entity Framework but with Asp.Net Identity 1.0 is not yet possible. You have to wait for the release of Identity 2.0.

using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings("DefaultConnection").ConnectionString)) {
    string queryString = "SELECT AspNetUsers.UserName FROM dbo.AspNetUsers INNER JOIN dbo.AspNetUserRoles ON " + "AspNetUsers.Id=AspNetUserRoles.UserId WHERE AspNetUserRoles.RoleID='" + id + "'";
    SqlCommand command = new SqlCommand(queryString, connection);
    command.Connection.Open();

    List<string> @out = null;
    dynamic reader = command.ExecuteReader();
    while (reader.Read()) {
        if (@out == null) @out = new List<string>();
        @out.Add(reader.GetString(0));
    }

    return @out;
}
Vincenzo Costa
  • 930
  • 11
  • 17
0

This is for the new MVC 5 ASP.NET Identity:

var managerRole = TMRoles.GetIdentityRole(TMRoles.Manager);
var managers = managerRole.Users;

public class TMRoles
{
    private static RoleManager<IdentityRole> RoleManager = 
        new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new TMContext()));

    public static string Manager { get { return "Manager"; } }


    public static IdentityRole GetIdentityRole(string roleName)
    {
        return RoleManager.FindByName(roleName);
    }
}
Serj Sagan
  • 28,927
  • 17
  • 154
  • 183
0

The Simplest way to get the users in any Role

int totalUser=db.AspNetUsers.Where(u => u.AspNetRoles.Any(r => r.Name == "USER")).Count()
Dharman
  • 30,962
  • 25
  • 85
  • 135