web-dev-qa-db-fra.com

Obtenir la liste des utilisateurs ayant des rôles attribués dans asp.net identity 2.0

J'ai une liste déroulante qui répertorie les rôles. Je souhaite obtenir la liste des utilisateurs ayant ce rôle. Je veux dire la liste des utilisateurs qui ont un rôle "Administrateur" ou "CanEdit". Voici mon code:

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;
}

S'il vous plaît aider.

Code mis à jour (erreur encore)

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;
}

Erreur: la méthode Select doit renvoyer l'un des éléments "IQueryable" ou "IEnumerable" ou "Microsoft.AspNet.Identity.EntityFramework.IdentityUser" lorsque ItemType est défini sur "Microsoft.AspNet.Identity.EntityFramework.IdentityUser".

J'ai essayé divers castings mais aucun d'entre eux n'a aidé.

UPDATE (solution de travail)

Merci à chris544, son idée m'a aidé à résoudre ce problème. Voici la méthode de travail: -

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;
}
26
Abhimanyu

Pas un expert, mais ...

Il ne semblait y avoir aucune fonctionnalité intégrée pour cela dans Identity et je ne pouvais pas le faire fonctionner à partir de Rôles intégrés également (cela ne semble pas fonctionner avec une identité basée sur des revendications).

Alors j'ai fini par faire quelque chose comme ça:

var users = context.Users        
    .Where(x => x.Roles.Select(y => y.Id).Contains(roleId))
    .ToList();
  • x.Roles.Select(y => y.Id) obtient une liste de tous les identifiants de rôle pour user x
  • .Contains(roleId) vérifie si cette liste d'identifiants contient les informations nécessaires roleId
35
chris544

Je trouve le rôle par l'entrée de nom de rôle. Après, je trouve les utilisateurs de la liste par identifiant du rôle.

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;
}
12
Trieu Doan

Si vous voulez éviter d'utiliser directement le contexte, vous pouvez utiliser le RoleManager avec l'extrait suivant.

roleManager.FindByName("Administrator").Users

ou

roleManager.FindByName("CanEdit").Users

Pour une brève discussion sur ce sujet, jetez un coup d’œil à la ce fil

7
Horizon_Net

Utiliser le RoleManager vous donne cette solution:

if(roleManager.RoleExists("CanEdit"))
{
    var idsWithPermission = roleManager.FindByName("CanEdit").Users.Select(iur => iur.Id);
    var users = db.Users.Where(u => idsWithPermission.Contains(u.Id));
}

Je serais intéressé de savoir si cela était mieux ou pire que les autres solutions ici.

4
Rob Church

Il y a trois façons de le faire. 

Dans le contrôleur, le rôle de l'utilisateur actuellement connecté peut être vérifié comme suit: 

  if(User.IsInRole("SysAdmin"))
        {

En dehors du contrôleur, vous pouvez vérifier si un utilisateur particulier appartient à un rôle comme suit:

 ApplicationUserManager UserManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        var roles = UserManager.GetRoles(userid);
        if (roles.Contains("SysAdmin"))
        {
        }

N'oubliez pas d'ajouter un espace de noms,

using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;

Pour des raisons telles que les tests d'intégration, etc., vous pouvez utiliser directement EF pour rechercher le rôle de l'utilisateur, comme suit:

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
        }

J'espère que ça aide. 

Merci/dj@debug_mode

4
Debug_mode

Supprimez le .Email et ajoutez UserName ou tout ce qui a été ajouté à la ASPNetUsers comme nom.

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);
        }      
}
0
David Evans

Comme de tels éléments ont tendance à avoir un impact sur les performances, j'ai essayé les autres réponses publiées ici et examiné le code SQL généré. Cela semble être le moyen le plus performant d’obtenir actuellement toutes les adresses électroniques de l’utilisateur.

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));
        }
    }

    ...
}

Le code SQL qu'il exécute est présenté ci-dessous:

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)
0
Paul Smith

le code qui fonctionnait pour moi était le suivant:

  var users = roleManager.FindByName(roleName).Users.Select(x => x.UserId);
  var usersInRole = Users.Where(u => users.Contains(u.Id));
0
Bartek Wójcik