web-dev-qa-db-fra.com

Identité .NET Core 2.1: obtenez tous les utilisateurs avec leurs rôles associés

J'essaie d'extraire tous mes utilisateurs Identity et leurs rôles associés pour une page d'administrateur de gestion des utilisateurs. Je pensais que ce serait assez facile mais apparemment pas. J'ai essayé de suivre la solution suivante: https://stackoverflow.com/a/43562544/5392786 mais cela n'a pas encore fonctionné.

Voici ce que j'ai jusqu'à présent:

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

Code d'identité au démarrage

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

Razor Page où je veux afficher la liste:

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

Je reçois le message d'erreur suivant lors de l'appel de userManager.Users.Include(u => u.Roles).ToList();:

MySql.Data.MySqlClient.MySqlException: 'Colonne inconnue' u.Roles.ApplicationUserId 'dans la liste de champs' '

9
Andy Furniss

J'ai maintenant mis en œuvre la solution suivante.

Comme CodeNotFound l'a souligné dans les commentaires, IdentityUser possédait une propriété Roles. Ce n'est plus le cas dans .NET Core. Ce commentaire/issue sur GitHub semble être la solution actuelle pour .Net Core. J'ai essayé de l'implémenter avec le code suivant:

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

Commencez

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

Enfin, lorsque vous l'utilisez, assurez-vous de charger avec impatience les rôles utilisateur de l'utilisateur, puis le rôle du rôle utilisateur, comme suit:

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

J'ai eu un problème où la propriété Role de chaque UserRole était nulle et cela a été résolu en ajoutant la partie .ThenInclude(ur => ur.Role).

Document Microsoft sur le chargement à plusieurs niveaux: https://docs.Microsoft.com/en-us/ef/core/querying/related-data#including-multiple-levels

30
Andy Furniss

parcourt la liste des utilisateurs et obtient des rôles en appelant la fonction _userManager.GetRolesAsync (utilisateur) et parcourt les rôles des utilisateurs et divise les rôles avec "," dans une variable chaîne

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


    }

bonne chance 

1
Mohamed Aboughoufa

Référence commentaire

Le premier est le code pour obtenir des données

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

Dans ASP.Net Core 2.1, nous configurons ApplicationRole comme ceci pour obtenir les rôles des utilisateurs. Vous devez définir les données que vous souhaitez exposer explicitement pour que l'utilisateur puisse les utiliser.

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

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

Finalement 

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

Le résultat sera le nom d'utilisateur et les rôles d'utilisateur. Si l'utilisateur a plus de 1 rôles, les données s'afficheront comme ceci Administrateur, éditeur, etc.

Le code complet peut être trouvé ici iciici et ici J'espère que cela vous aidera.

0
Ngô Hùng Phúc