试图在DropDownList中显示所有角色?

时间:2015-10-26 13:57:15

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

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

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

  

无法从'System.Collections.Generic.IEnumberable< SiteName.Models.AppRole>'转换为'Systems.Collections.IEnumerable< System.Web.Mvc.SelectListItem>。

我是否需要创建一个ViewModel来获取RoleName和RoleId,然后遍历我从RoleManger获得的角色列表并填充该ViewModel的List以传递给我的视图?当我已经有一个继承自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>

更新

这是我更新的VM

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类继承自IdentityRole,它具有.Id和.Name属性。

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<SiteName.Models.AppRole>’ to ‘System.Collections.Generic.IEnumberable<System.Web.Mvc.SelectListItem>’

修正了更新

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

这就是我最终的结果

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>

2 个答案:

答案 0 :(得分:4)

编译错误。

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

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

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

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

修复剃刀错误

向您的viewmodel添加一个属性,以便从下拉列表

存储所选角色
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
}

答案 1 :(得分:1)

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

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