2014-12-07 2 views
10

У меня есть шаблон проекта по умолчанию веб-сайта ASP.NET MVC 5, и я пытаюсь перечислить всех пользователей с именами ролей (не идентификаторами).Как указать пользователей с именами ролей в ASP.NET MVC 5

Этот запрос:

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

Тогда я хочу, чтобы напечатать имена ролей с чем-то вроде:

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

Проблема заключается в том, что я могу достичь только RoleId, а не роль класса, где Name и сохраняются другие свойства.

Я мог бы запустить другой выбор, чтобы получить все роли, а затем использовать его в качестве поиска. Или просто написать соединение в запросе? Я не уверен, потому что у меня нет доступа к таблице с объектами IdentityUserRole, которые объединяют пользователей и роли.

Корень проблемы, как представляется, тот факт, что является сбор роли IdentityUserRole (не Role), который содержит только RoleId и UserId.

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

Я подумал, что если один хочет сделать отношения N-к-N в EF они должны поместить непосредственно коллекцию Roles, а затем переопределить OnModelCreating и определить отношения. Этот подход, похоже, усложняет просмотр объектов от одного к другому.

Почему они решили включить IdentityUserRole в качестве дополнительного объекта? Уметь добавлять дополнительные данные в отношения? По стоимости не удается перейти от пользователей к ролям?

+0

вы можете легко перемещаться от пользователя к ролям, там есть таблица соединений, потому что существует много-много отношений. Я не думаю, что команда Identity просто создала мусорную систему для удовольствия .... –

+0

@ No1_Melman Не могли бы вы привести пример запроса (может быть, как ответ)? Благодарю. – NightElfik

+0

Да, дайте мне минуту –

ответ

14

Как мне сделать это:

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

    // rolesForUser now has a list role classes. 
} 

Команда идентичности из двух менеджеров: RoleManager для сортировки ролей (не роли пользователей, хотя) и UserManager в основном для всего аутентификации мудр. Существует также SignInManager, но не нужен.

So UserManager находит пользователей, создает пользователей, удаляет пользователей, отправляет электронные письма .... этот список можно продолжить.

Так мой Action может выглядеть следующим образом:

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

Чтобы выполнить необработанный SQL, то вы можете сделать что-то вроде этого:

Создать класс, Entity Framework можно сопоставить с, основанный на выходе ваш запрос:

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

Довольно просто!

Если псевдоним Ваш SQL возвращаемые столбцы:

SELECT AspNetUSers.UserName, AspNetRoles.Name As RoleName 

Тогда ваш класс DTO может выглядеть следующим образом:

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

Что, очевидно, намного чище.

+0

Спасибо за ответ, но откуда вы взяли DbSet 'UserRoles'? В default 'IdentityDbContext' есть только« Роли »и« Пользователи »DbSets, которые делают такое соединение невозможным в моих глазах. – NightElfik

+0

Да, я только что развернул проект, чтобы посмотреть, но нашел, что ничего не было, что причудливо, потому что во всех моих проектах я это делаю, но я думаю, что нашел причину! –

+0

@NightElfik посмотреть прямо сейчас! –

0

Я думаю, что его плохая техника для выполнения динамического SQL из вашего приложения C#. Ниже мой метод:

Модель:

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

    } 

Контроллер:

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

View (с использованием 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> 
3

Это, как я делаю это с MVC 5, Identity 2.0, а пользовательский пользователь и роль описываются John Atten

В контроллере

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

В ViewModel

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

И на мой взгляд

@{ 
    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++; 
} 
0
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

Спасибо @Callum Linington за его ответ. Просто попробуйте сделать это немного понятным для начинающих, таких как я. Вот шаги, чтобы получить список пользователей с их ролями.

1- Создать модель представления под названием «UsersWithRoles» с некоторыми свойствами, как показано ниже:

enter image description here

2- Создать контроллер под названием «RolesController», а затем добавить следующий фрагмент кода в нем.

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

    } 

и вот что RolesController должен выглядеть следующим образом:

enter image description here

3- Добавить страницу в индекс папку Roles и добавьте в него следующий код.

@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>

Вот результат

enter image description here

Спасибо.