50 votes

.NET Core 2.1 Identity obtient tous les utilisateurs avec leurs rôles associés

Je suis en train de sortir tout mon Identité des utilisateurs et de leurs rôles associés pour une gestion de l'utilisateur admin de la page. 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 fonctionné jusqu'à présent.

Voici ce que j'ai à ce jour:

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

Démarrage le code d'identification de

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

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

J'obtiens l'erreur suivante lors de l'appel d' userManager.Users.Include(u => u.Roles).ToList();:

MySql.Les données.MySqlClient.MySqlException: "Unknown column 'u.Les rôles.ApplicationUserId "dans" liste des champs"

93voto

Andy Furniss Points 2127

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

Comme CodeNotFound souligné dans les commentaires, IdentityUser l'habitude d'avoir un Roles de la propriété. Ce n'est plus le cas .NET de Base. Ce commentaire/question sur GitHub semble être la solution actuelle pour .Net De Base. J'ai tenté de mise en œuvre 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();
        });
    }
}

Démarrage

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

Enfin, assurez-vous que lorsque vous l'utilisez, que vous avec impatience la charge de l'Utilisateur UserRoles, puis le UserRole du Rôle de la sorte:

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

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

Microsoft doc sur multi-niveau désireux de chargement: https://docs.microsoft.com/en-us/ef/core/querying/related-data#including-multiple-levels

ASP Core 2.2 mise à jour

Inhérente à partir de IdentityUserRole<Guid> pas de chaîne Vous pouvez aussi avoir besoin de supprimer le code dans la ModelBuilder pour obtenir des migrations de travail.

8voto

parcourt la liste d'utilisateurs et obtient les rôles d'utilisateur en appelant la fonction _userManager.GetRolesAsync (user) et parcourt les rôles d'utilisateur et les rôles fractionnés avec "," dans une variable de 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

3voto

Bunni Points 3

Depuis c'est le top résultat de recherche de google; de nos jours, vous pouvez juste joindre au large de la UserRoles dbset (si votre db contexte hérite de IdentityDbContext).

E. g externe de rejoindre le tableau des rôles à tous les rôles d'utilisateur, puis de la création de notre manageUserModel (réduction de l'info de applicationUser classe pour notre api):

var employees = (from bb in _appContext.Users
            join roleIds in _appContext.UserRoles on bb.Id equals roleIds.UserId
            join role in _appContext.Roles on roleIds.RoleId equals role.Id into roles
            orderby bb.LastName, bb.FirstName
            where roles !=null && roles.Any(e => e.Name == Permissions.RoleNames.Administrator || e.Name == Permissions.RoleNames.Employee)
            select ManageUserModel.FromInfo(bb, roles)).ToList();

public static ManageUserModel FromInfo(ApplicationUser info, IEnumerable<UserRole> roles)
    {
        var ret= FromInfo(info);
        ret.Roles = roles.Select(e => new SimpleEntityString() {Id=e.Id, Text=e.Name}).ToList();
        return ret;
    }

Cela a également des démos une clause where à l'aide de tout le rôle de l'info (le ci-dessus ne sélectionne que les utilisateurs de notre Admin et les rôles des Employés).

Remarque: cette jointures internes de la IdentityUserRole, de sorte que seuls les utilisateurs avec un rôle sera de retour, si vous souhaitez que tous les utilisateurs il suffit d'ajouter un "en identRoles" à la fin de la jointure roleIds... ligne et de modifier le reste des conditions.

0voto

Matt Hearn Points 1

Fonctionne parfaitement. J'utilise des clés entières, j'ai donc remplacé la "chaîne" par "int"

 ApplicationRole : IdentityRole<int>
ApplicationUserRole : IdentityUserRole<int>
ApplicationUser : IdentityUser<int>

ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int, 
IdentityUserClaim<int>,
ApplicationUserRole, IdentityUserLogin<int>, IdentityRoleClaim<int>, 
IdentityUserToken<int>>
 

Linq: RoleId = (à partir d'un dans m.UserRoles sélectionnez un.Role.Id) .FirstOrDefault (),

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X