web-dev-qa-db-ja.com

asp.net identity 2.0で割り当てられたロールを持つユーザーのリストを取得します

役割をリストするドロップダウンリストボックスがあります。その役割を持つユーザーのリストを取得したい。 「管理者」ロールまたは「CanEdit」ロールのユーザーのリストを意味します。ここに私のコードがあります:

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

助けてください。

更新されたコード(まだエラー)

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

エラー:SelectTypeは、ItemTypeが「Microsoft.AspNet.Identity.EntityFramework.IdentityUser」に設定されている場合、「IQueryable」、「IEnumerable」、または「Microsoft.AspNet.Identity.EntityFramework.IdentityUser」のいずれかを返す必要があります。

さまざまなキャストを試しましたが、どれも役に立たなかった。

PDATE(ワーキングソリューション)

Chris544のおかげで、彼のアイデアはこれを修正するのに役立ちました。ここに作業方法があります:-

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

専門家ではありませんが...

Identityにはこの機能が組み込まれていないようで、組み込みのRolesからも機能させることができませんでした(クレームベースのIdentityでは機能しないようです)。

だから私はこのようなことをしました:

_var users = context.Users        
    .Where(x => x.Roles.Select(y => y.Id).Contains(roleId))
    .ToList();
_
  • x.Roles.Select(y => y.Id)は_user x_のすべてのロールIDのリストを取得します
  • .Contains(roleId)は、このIDリストに必要なroleIdが含まれているかどうかを確認します
37
chris544

ロール名入力でロールを見つけます。その後、ロールのIDでリストユーザーを見つけます。

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

コンテキストを直接使用したくない場合は、次のスニペットでRoleManagerを使用できます

roleManager.FindByName("Administrator").Users

または

roleManager.FindByName("CanEdit").Users

このトピックに関する短い議論については、 this thread をご覧ください。

7
Horizon_Net

RoleManagerを使用すると、次のソリューションが得られます。

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

これが他のソリューションよりも良いか悪いかを聞いてみたいです。

4
Rob Church

3つの方法があります。

現在ログインしているユーザーの役割をコントローラーで確認するには、次のようにします。

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

Controllerの外部では、次のようにして特定のユーザーがロールに属しているかどうかを確認できます。

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

名前空間を追加することを忘れないでください、

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

統合テストなどのいくつかの理由で、次のようにEFを直接使用してユーザーの役割を見つけることができます。

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
        }

それが役に立てば幸い。

ありがとう/ dj @debug_mode

3
Debug_mode

.Emailを削除し、UserNameまたは名前のASPNetUsersに追加されたものを追加します。

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

このようなビットはパフォーマンスに影響を与える傾向があるため、ここに投稿された他の回答を試し、生成されたSQLを調べました。これは、現在すべてのユーザーの電子メールアドレスを取得する最もパフォーマンスの高い方法のようです。

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

    ...
}

実行されるSQLを以下に示します。

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

私のために働いているコードは次のとおりでした:

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