【问题标题】:Trying to display all roles in a DropDownList?试图在 DropDownList 中显示所有角色?
【发布时间】:2016-01-25 15:50:56
【问题描述】:

我试图在DropDownList 中显示我的RoleManager 中的所有可用角色,然后选择用户所属的特定角色。对此的要求是用户只能处于一个角色(“用户、管理员或 NoAccess”)。

当我获得角色列表并将它们分配给我的 ViewModel 时,当我尝试显示它们时出现错误:

无法从“System.Collections.Generic.IEnumberable”转换为“Systems.Collections.IEnumerable

我是否需要创建一个 ViewModel 只是为了获取 RoleName 和 RoleId,然后遍历我从 RoleManger 获得的角色列表并填充该 ViewModel 的列表以传递给我的视图?当我已经有一个继承自 IdentityRole 的类 (AppRole) 应该具有 Role.Name 和 Role.Id 时,这似乎是额外的代码。

这是我用于编辑/显示用户的 ViewModel:

public class UserEditVM : BaseViewModel
{
    public string Id { get; set; }
    public string UserName { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string UserRole { get; set; }
    public string RoleID { get; set; }
    public IEnumerable<AppRole> AllRoles { get; set; }
    public IEnumerable<SelectListItem> RolesList { get; set; }
    public bool IsActive { get; set; }
}

这是来自我正在创建 VM 对象的控制器。我已经尝试将列表作为 AppRole 和 SelectListItem。两者都给了我与上述相同的错误。

private async Task<UserEditVM> createUserVM(AppUser user)
{
    var userRoles = await UserManager.GetRolesAsync(user.Id);

    var allRoles = RoleManager.Roles.ToList();

    string roleName = userRoles.Count() == 0 ? "User" : userRoles[0];

    UserEditVM editUser = new UserEditVM();
    editUser.Id = user.Id;
    editUser.UserName = user.UserName;
    editUser.FirstName = user.FirstName;
    editUser.LastName = user.LastName;
    editUser.Email = user.Email;
    editUser.UserRole = roleName;
    editUser.AllRoles = RoleManager.Roles.ToList();
    editUser.RolesList = new SelectList(RoleManager.Roles.ToList(), "Id", "Name"); ;
    editUser.IsActive = user.IsActive;

    return editUser;
}

这是 AppRole。从 IdentityRole 继承,它应该已经有 Role .Name 和 .Id 可用。

public class AppRole : IdentityRole
{
    public AppRole() : base() { }

    public AppRole(string name) : base(name) { }
}

这是我试图在 DDL 中显示它们的视图。

<div class="form-group">
    <label>Role:</label> @Html.DisplayNameFor(model => model.UserRole)

    @Html.DropDownListFor(model => model.Id, Model.AllRoles)
</div>

更新

这是我更新的虚拟机

public class UserEditVM : BaseViewModel
    {
        public string Id { get; set; }
        public string UserName { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string UserRole { get; set; }
        public string RoleID { get; set; }
        public IEnumerable<AppRole> AllRoles { get; set; }
        public IEnumerable<SelectListItem> RolesList { get; set; }
        public string SelectedRoleId { get; set; }
        public bool IsActive { get; set; }

    }

这是我的控制器。我的 AppRole 类继承自具有 .Id 和 .Name 属性的 IdentityRole。

private async Task<UserEditVM> createUserVM(AppUser user)
        {
            var userRoles = await UserManager.GetRolesAsync(user.Id);

            var allRoles = RoleManager.Roles.ToList();

            string roleName = userRoles.Count() == 0 ? "User" : userRoles[0];

            UserEditVM editUser = new UserEditVM();
            editUser.Id = user.Id;
            editUser.UserName = user.UserName;
            editUser.FirstName = user.FirstName;
            editUser.LastName = user.LastName;
            editUser.Email = user.Email;
            editUser.UserRole = roleName;
            editUser.AllRoles = RoleManager.Roles.Select(r => new AppRole { Id = r.Id, Name = r.Name }).ToList();
            //editUser.RolesList = new SelectList(RoleManager.Roles.ToList(), "Id", "Name"); ;
            editUser.IsActive = user.IsActive;

            return editUser;
        }

这是我在我的视图中尝试过的

<div class="form-group">
        <label>Role:</label> @Html.DisplayNameFor(model => model.UserRole)

        @Html.DropDownListFor(model => model.SelectedRoleId, Model.AllRoles, "Select")
    </div>

在视图中我仍然收到错误“cannot convert from ‘System.Collections.Generic.IEnumberable&lt;SiteName.Models.AppRole&gt;’ to ‘System.Collections.Generic.IEnumberable&lt;System.Web.Mvc.SelectListItem&gt;’

固定更新

这是最后的修复。最后,问题出在我的 ViewModel 中的 Using 语句上。当我第一次添加 IEnumberable 时,我使用了 VisualStudio 2015 中的 QuickFix 功能来解析引用。问题在于它建议“使用 System.Web.WebPages.Html”,而我真正需要的是“使用 System.Web.Mvc”。这可以在我得到的最后一个错误中看到。一旦我切换了 using 语句,它就起作用了。

这就是我的结局

using System.Collections.Generic;
//using System.Web.WebPages.Html;
using System.Web.Mvc;

namespace SampleMvcSite.Models
{
    public class UserEditVM : BaseViewModel
    {
        public string Id { get; set; }
        public string UserName { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string UserRole { get; set; }
        public string RoleID { get; set; }
        public IEnumerable<AppRole> AllRoles { get; set; }
        public IEnumerable<SelectListItem> RolesList { get; set; }
        public string SelectedRoleId { get; set; }
        public bool IsActive { get; set; }

    }
}

控制器

private async Task<UserEditVM> createUserVM(AppUser user)
        {    
            var userRoles = await UserManager.GetRolesAsync(user.Id);
            string roleName = userRoles.Count() == 0 ? "User" : userRoles[0];

            var allRoles = RoleManager.Roles.ToList();

            UserEditVM editUser = new UserEditVM();
            editUser.Id = user.Id;
            editUser.UserName = user.UserName;
            editUser.FirstName = user.FirstName;
            editUser.LastName = user.LastName;
            editUser.Email = user.Email;
            editUser.UserRole = roleName;
            editUser.RolesList = allRoles.Select(s => new SelectListItem
                                {
                                    Value = s.Id.ToString(),
                                    Text = s.Name,
                                    Selected = s.Name == roleName ? true : false
                                });
            editUser.IsActive = user.IsActive;

            return editUser;
        }

查看

<div class="form-group">
        <label>Current Role:</label> 
        @Html.DropDownListFor(model => model.SelectedRoleId, Model.RolesList, "Select Role")
    </div>

【问题讨论】:

    标签: c# asp.net-mvc asp.net-identity-2


    【解决方案1】:

    对于您的编译错误。

    看起来RoleManager.Roles 会返回一个与您在视图模型中声明的类型不同的集合 (IEnumberable&lt;AppRole&gt;)。在这种情况下,您需要将其转换为 AppRole 的集合。

    editUser.AllRoles = RoleManager.Roles
             .Select(s=>new AppRole { Id = s.Id, Name = s.Name).toList();
    

    假设 AppRole 类具有您要用于显示下拉列表的 Id 和 Name 属性。如果您的属性名称不同,请更改上述代码的 Projection 部分。

    但显然,您没有在视图中使用AllRoles 集合。

    修复 Razor 错误

    向您的视图模型添加一个属性以存储从下拉列表中选择的角色

    public class UserEditVM : BaseViewModel
    {
      public int SelectedRoleId {set;get;}
      public IEnumerable<SelectListItem> RolesList { get; set; }
       //Other properties as needed.
    
    }
    

    在您的 GET 操作方法中,您将获取所有角色(可以是 Role 类或某些自定义类的集合),将其转换为 SelectListItem 的集合并将其分配给 RolesList 的属性UserEditVM 对象。

    public ActionResult Create()
    {
      var vm=new UserEditVM();
      var allRoles= RoleManager.Roles.ToList();
      vm.RolesList = allRoles.Select(s => new SelectListItem
                {
                    Value = s.Id.ToString(),
                    Text = s.Name
                });
    
      return View(vm);     
    }
    

    在剃刀视图中,使用RolesList 属性,它是SelectListItem 的集合

      @model YourNameSpace.UserEditVM
    
      @Html.DropDownListFor(x=> x.SelectedRoleId, Model.RolesList,"Select")
    

    现在当用户提交表单时,选择的角色 id 将在发布模型的SelectedRoleId 属性中。

    [HttpPost]
    public ActionResult Edit(UserEditVM model)
    {
      //check model.SelectedRoleId
     //to do : Save and Redirect
    }
    

    【讨论】:

    • 首先,感谢大家的帮助。但是,在尝试了不同的建议后,我仍然遇到错误。请参阅上面的更新代码。此外,我正在尝试传递角色的不同场景,这就是我同时拥有 AllRoles 和 RolesList 的原因。我无法弄清楚如何使用任一选项传递它们。
    • 你现在有什么问题?
    • 在我的原始帖子中查看我的更新。进行建议的更改后,我仍然收到错误消息。 “无法从‘System.Collections.Generic.IEnumberable’转换为‘System.Collections.Generic.IEnumberable
    • @Caverman 查看更新后的答案。这应该没有任何问题。保持你的视图模型瘦。只添加视图真正需要的属性。
    • Shyju...感谢您的帮助。有了你的建议和更多的故障排除,我终于把它修好了。我用最终修复更新了我的原始帖子。
    【解决方案2】:

    您已经拥有正确的数据,但在模型的不同属性中。您需要使用RolesList,而不是AllRoles。例如:

    @Html.DropDownListFor(model => model.Id, Model.RolesList)
    

    【讨论】:

    • 当我尝试 RolesList 时,我收到错误“无法从 'System.Collections.Generic.IEnumerable' 转换为 'System.Collections.Generic.IEnumerable '
    猜你喜欢
    • 2014-10-25
    • 1970-01-01
    • 2021-02-14
    • 2015-08-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-01
    • 2015-04-23
    • 1970-01-01
    相关资源
    最近更新 更多