tables - Obtenga una lista de usuarios con roles asignados en asp.net identity 2.0
asp.net identity tutorial español (8)
Dado que los bits como este tienden a afectar el rendimiento, probé las otras respuestas publicadas aquí y miré el SQL que generaron. Esta parece ser la forma más eficaz de obtener todas las direcciones de correo electrónico del usuario actualmente.
public void SendEmailToUsersInRole(string roleName)
{
MailMessage message = new MailMessage();
...
using (var usersDB = new ApplicationDbContext())
{
var roleId =
usersDB.Roles.First(x => x.Name == roleName).Id;
IQueryable<string> emailQuery =
usersDB.Users.Where(x => x.Roles.Any(y => y.RoleId == roleId))
.Select(x => x.Email);
foreach (string email in emailQuery)
{
message.Bcc.Add(new MailAddress(email));
}
}
...
}
El SQL que ejecuta se muestra a continuación:
SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[AspNetRoles] AS [Extent1]
WHERE N''Reviewer'' = [Extent1].[Name]
SELECT
[Extent1].[Email] AS [Email]
FROM [dbo].[AspNetUsers] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM [dbo].[AspNetUserRoles] AS [Extent2]
WHERE ([Extent1].[Id] = [Extent2].[UserId]) AND ([Extent2].[RoleId] = @p__linq__0)
)
-- p__linq__0: ''3'' (Type = String, Size = 4000)
Tengo un cuadro de lista desplegable que enumera los roles. Quiero obtener la lista de usuarios que tienen ese rol. Me refiero a la lista de usuarios que están en la función de "Administrador" o "CanEdit". Aquí está mi código:
public IQueryable<Microsoft.AspNet.Identity.EntityFramework.IdentityUser>
GetRolesToUsers([Control] string ddlRole)
{
//ddlRole returns role Id, based on this Id I want to list users
var _db = new ApplicationDbContext();
IQueryable<Microsoft.AspNet.Identity.EntityFramework.IdentityUser> query = _db.Users;
if (ddlRole != null)
{
//query = query.Where(e => e.Claims == ddlRole.Value); ???????
}
return query;
}
Por favor ayuda.
Código actualizado (error aún)
public List<IdentityUserRole> GetRolesToUsers([Control]string ddlRole)
{
var roleManager =
new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
var users = roleManager.FindByName("Administrator").Users.ToList();
return users;
}
Error: El método de selección debe devolver uno de "IQueryable" o "IEnumerable" o "Microsoft.AspNet.Identity.EntityFramework.IdentityUser" cuando ItemType se establece en "Microsoft.AspNet.Identity.EntityFramework.IdentityUser".
Intenté varios lanzamientos pero ninguno ayudó.
ACTUALIZACIÓN (solución de trabajo)
Gracias a chris544, su idea me ayudó a solucionar esto. Aquí está el método de trabajo: -
public List<ApplicationUser> GetRolesToUsers([Control]string ddlRole)
{
var context = new ApplicationDbContext();
var users =
context.Users.Where(x => x.Roles.Select(y => y.RoleId).Contains(ddlRole)).ToList();
return users;
}
El uso de RoleManager le brinda esta solución:
if(roleManager.RoleExists("CanEdit"))
{
var idsWithPermission = roleManager.FindByName("CanEdit").Users.Select(iur => iur.Id);
var users = db.Users.Where(u => idsWithPermission.Contains(u.Id));
}
Me interesaría saber si esto fue mejor o peor que las otras soluciones aquí.
Elimine .Email
y agregue .Email
o lo que se haya agregado a ASPNetUsers
para el nombre.
private void AddAddminToMail(MailMessage message)
{
var roles = db.Roles.Include(m => m.Users).Where(m => m.Name == "Admin").First();
foreach (var user in roles.Users)
{
var id = user.UserId;
var userEmail = db.Users.Find(id).Email;
message.To.Add(userEmail);
}
}
Encuentro el rol por la entrada del nombre del rol. Después, encuentro usuarios de la lista por id del rol.
public List<ApplicationUser> GetUsersInRole(string roleName)
{
var roleManager =
new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
var role = roleManager.FindByName(roleName).Users.First();
var usersInRole =
Users.Where(u => u.Roles.Select(r => r.RoleId).Contains(role.RoleId)).ToList();
return usersInRole;
}
Hay tres formas en que puedes hacerlo.
En el controlador, la función del usuario registrado actualmente se puede verificar de la siguiente manera:
if(User.IsInRole("SysAdmin"))
{
Controlador externo puede verificar si un usuario en particular pertenece a un Rol de la siguiente manera:
ApplicationUserManager UserManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
var roles = UserManager.GetRoles(userid);
if (roles.Contains("SysAdmin"))
{
}
No te olvides de agregar espacio de nombre,
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
Por alguna razón, como las pruebas de integración, etc., puede querer usar EF de manera directa para encontrar la función del usuario de la siguiente manera:
string userId = User.Identity.GetUserId();
ApplicationDbContext db = new ApplicationDbContext();
var role = (from r in db.Roles where r.Name.Contains("Admin") select r).FirstOrDefault();
var users = db.Users.Where(x => x.Roles.Select(y => y.RoleId).Contains(role.Id)).ToList();
if (users.Find(x => x.Id == userId) != null)
{
// User is in the Admin Role
}
Espero eso ayude.
Gracias / dj @debug_mode
No es un experto, pero ...
No parecía haber ninguna funcionalidad incorporada para esto en Identity y no pude hacer que funcionara también desde Roles incorporados (parece que no funciona con Identidad basada en reclamos).
Así que terminé haciendo algo como esto:
var users = context.Users
.Where(x => x.Roles.Select(y => y.Id).Contains(roleId))
.ToList();
-
x.Roles.Select(y => y.Id)
obtiene una lista de todos losx.Roles.Select(y => y.Id)
de rol para eluser x
-
.Contains(roleId)
comprueba si esta lista de identificadores contieneroleId
necesario
Si desea evitar el uso directo del contexto, puede usar RoleManager con el siguiente fragmento
roleManager.FindByName("Administrator").Users
o
roleManager.FindByName("CanEdit").Users
Para una breve discusión sobre este tema, eche un vistazo a este hilo
el código que funcionaba para mí fue el siguiente:
var users = roleManager.FindByName(roleName).Users.Select(x => x.UserId);
var usersInRole = Users.Where(u => users.Contains(u.Id));