web-dev-qa-db-ja.com

.NET Core 2.1 Identityは、関連するロールを持つすべてのユーザーを取得します

ユーザー管理管理ページのすべてのIDユーザーとそれらに関連付けられたロールを引き出しようとしています。これはかなり簡単だが、明らかにそうではないと思った。私は次の解決策を試してみました: https://stackoverflow.com/a/43562544/5392786 しかし、それは今のところうまくいきませんでした。

ここに私がこれまで持っているものがあります:

ApplicationUser:

_public class ApplicationUser : IdentityUser
{
    public List<IdentityUserRole<string>> Roles { get; set; }
}
_

DBContext

_public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}
_

スタートアップIDコード

_services.AddIdentity<ApplicationUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
_

リストを表示したいRazorページ:

_public class IndexModel : PageModel
{
    private readonly UserManager<ApplicationUser> userManager;

    public IndexModel(UserManager<ApplicationUser> userManager)
    {
        this.userManager = userManager;
    }

    public IEnumerable<ApplicationUser> Users { get; set; }

    public void OnGetAsync()
    {
        this.Users = userManager.Users.Include(u => u.Roles).ToList();
    }
}
_

userManager.Users.Include(u => u.Roles).ToList();を呼び出すと、次のエラーが表示されます。

MySql.Data.MySqlClient.MySqlException: 'フィールドリストの'不明な列 'u.Roles.ApplicationUserId'

9
Andy Furniss

現在、次のソリューションを実装しています。

CodeNotFoundがコメントで指摘したように、IdentityUserはRolesプロパティを使用していました。これは、.NET Coreには当てはまりません。 GitHubのこの comment/issue は、.Net Coreの現在のソリューションのようです。私は次のコードでそれを実装しようとしました:

ApplicationUser

_public class ApplicationUser : IdentityUser
{
    public ICollection<ApplicationUserRole> UserRoles { get; set; }
}
_

ApplicationUserRole

_public class ApplicationUserRole : IdentityUserRole<string>
{
    public virtual ApplicationUser User { get; set; }
    public virtual ApplicationRole Role { get; set; }
}
_

ApplicationRole

_public class ApplicationRole : IdentityRole
{
    public ICollection<ApplicationUserRole> UserRoles { get; set; }
}
_

DBContext

_public class ApplicationDbContext
    : IdentityDbContext<ApplicationUser, ApplicationRole, string, IdentityUserClaim<string>,
    ApplicationUserRole, IdentityUserLogin<string>,
    IdentityRoleClaim<string>, IdentityUserToken<string>>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<ApplicationUserRole>(userRole =>
        {
            userRole.HasKey(ur => new { ur.UserId, ur.RoleId });

            userRole.HasOne(ur => ur.Role)
                .WithMany(r => r.UserRoles)
                .HasForeignKey(ur => ur.RoleId)
                .IsRequired();

            userRole.HasOne(ur => ur.User)
                .WithMany(r => r.UserRoles)
                .HasForeignKey(ur => ur.UserId)
                .IsRequired();
        });
    }
}
_

スタートアップ

_services.AddIdentity<ApplicationUser, ApplicationRole>(options => options.Stores.MaxLengthForKeys = 128)
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
_

最後に、それを使用しているときは、ユーザーのUserRolesを熱心にロードしてから、UserRoleのロールを次のようにロードしてください。

_this.Users = userManager.Users.Include(u => u.UserRoles).ThenInclude(ur => ur.Role).ToList();
_

RoleUserRoleプロパティがnullであるという問題があり、これは.ThenInclude(ur => ur.Role)部分を追加することで解決しました。

マルチレベルの積極的な読み込みに関するMicrosoftドキュメント: https://docs.Microsoft.com/en-us/ef/core/querying/related-data#include-multiple-levels

30
Andy Furniss

ユーザーリストをループし、_userManager.GetRolesAsync(user)関数を呼び出してユーザーロールを取得し、ユーザーのロールをループし、1つの文字列変数で「、」を使用してロールを分割します

[HttpPost]
    public async Task<IActionResult> OnPostGetPagination()
    {


        var users = await _userManager.Users.ToListAsync();
        InputModel inputModel = new InputModel();
        foreach (var v in users)
        {
            inputModel = new InputModel();
            var roles = await _userManager.GetRolesAsync(v);
            inputModel.Email = v.UserName;
            inputModel.role = "";
            foreach (var r in roles)
            {
                if (!inputModel.role.Contains(","))
                {
                    inputModel.role = r;
                }
                else
                {
                    inputModel.role = "," + r;
                }
            }
            Input2.Add(inputModel);
        }


    }

がんばろう

1

参照 コメント

最初はデータを取得するコードです

 public async Task<IEnumerable<AccountViewModel>> GetUserList()
        {
            var userList = await (from user in _context.Users
                                  select new
                                  {
                                      UserId = user.Id,
                                      Username = user.UserName,
                                      user.Email,
                                      user.EmailConfirmed,
                                      RoleNames = (from userRole in user.Roles //[AspNetUserRoles]
                                                   join role in _context.Roles //[AspNetRoles]//
                                                   on userRole.RoleId
                                                   equals role.Id
                                                   select role.Name).ToList()
                                  }).ToListAsync();

            var userListVm = userList.Select(p => new AccountViewModel
            {
                UserId = p.UserId,
                UserName = p.Username,
                Email = p.Email,
                Roles = string.Join(",", p.RoleNames),
                EmailConfirmed = p.EmailConfirmed.ToString()
            });

            return userListVm;
        }

ASP.Netコア2.1では、ユーザーのロールを取得するために、このようにApplicationRoleをセットアップしました。ユーザーが使用するために明示的に公開するデータを定義する必要があります

public class ApplicationRole : IdentityRole
    {
        public virtual ICollection<IdentityUserRole<string>> Users { get; set; }

        public virtual ICollection<IdentityRoleClaim<string>> Claims { get; set; }
    }

最後に

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
            {
                relationship.DeleteBehavior = DeleteBehavior.Restrict;
            }

            modelBuilder.Entity<User>().HasMany(u => u.Claims).WithOne().HasForeignKey(c => c.UserId).IsRequired().OnDelete(DeleteBehavior.Cascade);
            modelBuilder.Entity<User>().HasMany(u => u.Roles).WithOne().HasForeignKey(r => r.UserId).IsRequired().OnDelete(DeleteBehavior.Cascade);

            modelBuilder.Entity<ApplicationRole>().HasMany(r => r.Claims).WithOne().HasForeignKey(c => c.RoleId).IsRequired().OnDelete(DeleteBehavior.Cascade);
            modelBuilder.Entity<ApplicationRole>().HasMany(r => r.Users).WithOne().HasForeignKey(r => r.RoleId).IsRequired().OnDelete(DeleteBehavior.Cascade);

            modelBuilder.EnableAutoHistory(null);
        }

結果は、ユーザー名とユーザーロールになります。ユーザーが複数のロールを持っている場合、データはこの管理者、編集者などのように表示されます...

完全なコードはここにあります herehere および here このヘルプを願っています。

0