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.
12
votes
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
@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
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
7 Answers
12
votes
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)
)
11
votes
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;
}
4
votes
3
votes
0
votes
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;
}
0
votes
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);
}
}