wake-up-neo.com

So listen Sie Benutzer mit Rollennamen in ASP.NET MVC 5 auf

Ich habe eine Standardprojektvorlage für die ASP.NET MVC 5-Website, und ich versuche, alle Benutzer mit Rollennamen (nicht IDs) aufzulisten.

Die Abfrage lautet:

db.Users.Include(u => u.Roles).ToList()

Dann möchte ich die Rollennamen folgendermaßen drucken:

@string.Join(", ", user.Roles.Select(r => r.RoleId))

Das Problem ist, dass ich nur RoleId erreichen kann, nicht die Rollenklasse, in der Name und andere Eigenschaften gespeichert sind.

Ich könnte eine weitere Auswahl ausführen, um alle Rollen zu erhalten, und diese dann als Nachschlagewerk verwenden. Oder schreibe einen Join direkt in die Abfrage? Ich bin nicht sicher, wie, weil ich keinen Zugriff auf die Tabelle mit IdentityUserRole-Entitäten habe, die Benutzer und Rollen miteinander verbinden.

Die Wurzel des Problems scheint die Tatsache zu sein, dass es sich bei Roles um eine Auflistung von IdentityUserRole (nicht Role) handelt, die nur RoleId und UserId enthält.

public class IdentityUserRole<TKey> {
    public virtual TKey RoleId { get; set; }
    public virtual TKey UserId { get; set; }
}

Ich dachte, wenn man eine N-zu-N-Beziehung in EF machen will, sollte man die Sammlung von Roles direkt setzen und dann OnModelCreating überschreiben und die Beziehungen angeben. Dieser Ansatz scheint das Durchsuchen der Objekte von einem zum anderen zu komplizieren.

Warum haben sie beschlossen, IdentityUserRole als zusätzliche Entität aufzunehmen? Um zusätzliche Daten zu den Beziehungen hinzufügen zu können? Zu Kosten, weil Sie nicht in der Lage sind, von Benutzern zu Rollen zu navigieren?

11
NightElfik

Ich mache das so:

using (var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationContext()))
{
    var rolesForUser = await userManager.GetRolesAsync(userId);

   // rolesForUser now has a list role classes.
}

Das Identitätsteam hat zwei Manager gebildet: RoleManager für das Sortieren von Rollen (nicht jedoch für Benutzerrollen) und UserManager für alles was die Authentifizierung angeht. Es gibt auch eine SignInManager, die aber nicht benötigt wird.

So findet UserManager Benutzer, erstellt Benutzer, löscht Benutzer, sendet E-Mails ... die Liste wird fortgesetzt.

So könnte meine Action so aussehen:

    public async Task<ActionResult> GetRolesForUser(string userId)
    {
        using (
            var userManager =
                new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
        {
            var rolesForUser = await userManager.GetRolesAsync(userId);

            return this.View(rolesForUser);
        }
    }

Um Raw SQL auszuführen, können Sie Folgendes tun:

Erstellen Sie die Klasse, der Entity Framework basierend auf der Ausgabe Ihrer Abfrage zugeordnet werden kann:

public class UserWithRole
{
    public string UserName {get;set;} // You can alias the SQL output to give these better names
    public string Name {get;set;}
}

using (var context = new DbContext())
{
    var sql = @"
                SELECT AspNetUsers.UserName, AspNetRoles.Name 
                FROM AspNetUsers 
                LEFT JOIN AspNetUserRoles ON  AspNetUserRoles.UserId = AspNetUsers.Id 
                LEFT JOIN AspNetRoles ON AspNetRoles.Id = AspNetUserRoles.RoleId
                WHERE AspNetUsers.Id = @Id";
    var idParam = new SqlParameter("Id", theUserId);

    var result = context.Database.ExecuteQuery<UserWithRole>(sql, idParam);
}

Ziemlich einfach!

Wenn Sie die SQL-Spalten als Aliasnamen angeben:

SELECT AspNetUSers.UserName, AspNetRoles.Name As RoleName

Dann kann Ihre DTO-Klasse so aussehen:

public class UserWithRole
{
    public string UserName {get;set;}
    public string RoleName {get;set;}
}

Das ist natürlich viel sauberer.

14

So mache ich es mit MVC 5, Identity 2.0 und einem benutzerdefinierten Benutzer und einer Rolle, die von John Atten beschrieben wird.

In Controller

public virtual ActionResult ListUser()
    {            
        var users = UserManager.Users;
        var roles = new List<string>();
        foreach (var user in users)
        {
            string str = "";
            foreach (var role in UserManager.GetRoles(user.Id))
            {
                str = (str == "") ? role.ToString() : str + " - " + role.ToString();
            }
            roles.Add(str);
        }
        var model = new ListUserViewModel() {
            users = users.ToList(),
            roles = roles.ToList()
        };
        return View(model);
    }

In ViewModel 

public class ListUserViewModel
{
    public IList<YourAppNamespace.Models.ApplicationUser> users { get; set; }
    public IList<string> roles { get; set; }
}

Und aus meiner Sicht

@{
    int i = 0;
}
@foreach (var item in Model.users)
{   
    @Html.DisplayFor(modelItem =>  item.Name)
    [... Use all the properties and formating you want ... and ] 
    @Model.roles[i]
    i++;
}
3
remi

Ich denke, es ist eine schlechte Technik, dynamisches SQL von Ihrer C # -Anwendung auszuführen. Unten ist meine Methode:

Modell:

  public class ApplicationRole : IdentityRole
  {
    public ApplicationRole() : base() { }
    public ApplicationRole(string name) : base(name) { }
    public string Description { get; set; }

  }

Regler:

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.AspNet.Identity.EntityFramework;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Collections.Generic;

//Example for Details.
if (id == null)
  {
    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
  }
  var role = await RoleManager.FindByIdAsync(id);
  // Get the list of Users in this Role
  var users = new List<ApplicationUser>();

  // Get the list of Users in this Role
  foreach (var user in UserManager.Users.ToList())
  {
    if (await UserManager.IsInRoleAsync(user.Id, role.Name))
    {
      users.Add(user);
    }
  }

  ViewBag.Users = users;
  ViewBag.UserCount = users.Count();
  return View(role);

Ansicht (mit ApplicationRole)

    <div>
        <h4>Roles.</h4>
        <hr />
        <dl class="dl-horizontal">
            <dt>
                @Html.DisplayNameFor(model => model.Name)
            </dt>
            <dd>
                @Html.DisplayFor(model => model.Name)
            </dd>
        </dl>
        <dl class="dl-horizontal">
            <dt>
                @Html.DisplayNameFor(model => model.Description)
            </dt>
            <dd>
                @Html.DisplayFor(model => model.Description)
            </dd>
        </dl>
    </div>
    <h4>List of users in this role</h4>
    @if (ViewBag.UserCount == 0)
{
        <hr />
        <p>No users found in this role.</p>
}
    <table class="table">
        @foreach (var item in ViewBag.Users)
    {
            <tr>
                <td>
                    @item.UserName
                </td>
            </tr>
    }
    </table>
0
Danny Rancher

Vielen Dank an @Callum Linington für seine Antwort. Versuchen Sie einfach, es für Anfänger wie mich etwas klar zu machen ... Hier sind die Schritte, um eine Liste der Benutzer mit ihren Rollen zu erhalten.

1- Erstellen Sie ein Ansichtsmodell mit dem Namen "UsersWithRoles" mit einigen folgenden Eigenschaften:

 enter image description here

2- Erstellen Sie einen Controller mit dem Namen "RolesController" und fügen Sie anschließend den folgenden Code hinzu.

        public ActionResult Index()
    {
        using (var context = new ApplicationDbContext())
        {
            var sql = @"
            SELECT AspNetUsers.UserName, AspNetRoles.Name As Role
            FROM AspNetUsers 
            LEFT JOIN AspNetUserRoles ON  AspNetUserRoles.UserId = AspNetUsers.Id 
            LEFT JOIN AspNetRoles ON AspNetRoles.Id = AspNetUserRoles.RoleId";
            //WHERE AspNetUsers.Id = @Id";
            //var idParam = new SqlParameter("Id", theUserId);

            var result = context.Database.SqlQuery<UserWithRoles>(sql).ToList();
            return View(result);
        }

    }

und so sollte der RolesController aussehen:

 enter image description here

3- Fügen Sie dem Rollenordner die Indexseite hinzu und fügen Sie den folgenden Code hinzu.

@model IEnumerable<MVC_Auth.ViewModels.UserWithRoles>
<div class="row">
    <h4>Users</h4>
    <table class="table table-hover table-responsive table-striped table-bordered">
        <th>User Name</th>
        <th>Role</th>
        @foreach (var user in Model)
        {
            <tr>
                <td>@user.UserName</td>
                <td>@user.Role</td>
            </tr>
        }
    </table>
</div>

Hier ist das Ergebnis 

 enter image description here

Vielen Dank.

0
user2662006
using System.Linq;
using System.Data;
using System.Data.Entity;

            var db = new ApplicationDbContext();
            var Users = db.Users.Include(u => u.Roles);

            foreach (var item in Users)
            {
                string UserName = item.UserName;
                string Roles = string.Join(",", item.Roles.Select(r=>r.RoleId).ToList());
            }
0