1

WHAT I AM TRYING TO ACHIEVE

If a user is a member of 3 roles, i want to generate 3 DropDownLists of all roles and each user role to be selected. I dont want to use ViewBag.

PROBLEM

Currently, i can generate 3 DropDownLists which contain all roles, but the 3 roles that the user is a member of are not selected. If the user is a member of Admin, PowerUser, and Manager roles, only the last role, Manager, is selected in all 3 DropDownLists.

QUESTION

How do i generate the required DropDownLists with the correctly selected roles?

VIEWMODEL

public class UserViewModel
{
    public IEnumerable<SelectListItem> RolesList { get; set; }
    public string RolesListId { get; set; }
}

CONTROLLER

// Get list of roles that user is a member of
var userRoles = UserManager.GetRoles(user.Id);

var model = new UserViewModel()
{
    RolesList = RoleManager.Roles.ToList().Select(r => new SelectListItem
    {
        Selected = userRoles.Contains(r.Name),
        Text = r.Name,
        Value = r.Name
    }).OrderBy(r => r.Text),
};

VIEW

@for (int i = 0; i < Model.RolesList.Where(x => x.Selected == true).Count(); i++)
{
    @Html.DropDownListFor(model => model.RolesListId, Model.RolesList, "Select Role ...")
}
drewmagoo
  • 15
  • 2
  • 5
  • RoleListId contains single id? – Ehsan Sajjad Sep 12 '15 at 19:00
  • RoleListId contains single id - Yes – drewmagoo Sep 12 '15 at 19:32
  • The selected option will be the value of `RolesListId` (because your binding to `RolesListId`). And setting the `Selected` property of `SelectListItem` is ignored when binding to a property. But `RolesListId` is a value type (`string`)` so you cannot bind multiple dropdownlists to it anyway so unclear what your trying to achieve. –  Sep 12 '15 at 22:43
  • I suspect what you want is for property `RolesListId` to be `List` and you want a single `@Html.ListBoxFor(m => m.RolesListId, Model.RolesList)` which will display all roles and if `RolesListId` contains 3 values, then those 3 options will be selected. –  Sep 12 '15 at 22:45
  • The solution you have accepted means you can only ever have 3 roles. You cannot add new roles. You cannot delete roles. You cannot have client or server side validation. You can select the same role multiple times. You need a single ` –  Sep 13 '15 at 21:44
  • thanks stephen I dont have a good enough grasp of MVC, all I can do try your suggestions. I am still going throught the process of trying and failing. My last classic asp web site used this technique and am hoping it will work similarly in MVC. – drewmagoo Sep 14 '15 at 14:57
  • I suspect you really want something like [this solution](http://stackoverflow.com/questions/29542107/pass-list-of-checkboxes-into-view-and-pull-out-ienumerable/29554416#29554416) –  Sep 18 '15 at 00:04

1 Answers1

2

Here is the code you need, but When user can have more than one role, instead of using DropDownList, its better to use list of CheckBoxes.

  • There is a (n to n) relation between users and roles and dropdownliast can never represent such relation.
  • If you use more than dropdownlist, user may select role1 from list1 and again role1 from list2 and again role 1 from list 3.
  • If you use dropdownlist, how end user can add a role to user?

Anyway, here is the code you need with DropDownList:

@foreach (var item in Model.RolesList.Where(x => x.Selected))
{
    @Html.DropDownList("SelectedRole", new SelectList(Model.RolesList, "Value", "Text", item.Value), "Select a Role")
}

And here is the code that should be if you decide to use CheckBoxes:

@foreach (var item in (SelectList)ViewBag.RoleId)
{
    <input type="checkbox" name="SelectedRoles" value="@item.Value" class="checkbox-inline" />
    @Html.Label(item.Value, new { @class = "control-label" })
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • I really need to use dropdownlists, the original code was for checkboxes, so i already have working checkboxes. There could be 50 roles, so checkboxes is too much. If a user is only a member of 1 role, thats only one dropdownlist, not 50 checkboxes. – drewmagoo Sep 12 '15 at 21:24
  • @DrewWelsh Maybe I can fix your code to render dropdowns but it is an incorrect design. There is a (n to n) relation between users and roles and dropdownliast can never represent such relation. If you use more than dropdownlist, user may select role1 from list1 and again role1 from list2 and again role 1 from list 3. – Reza Aghaei Sep 12 '15 at 21:32
  • I have tested your solution and it works great, thanks. Without being ungrateful, how would I do it using the DropDownListFor? – drewmagoo Sep 13 '15 at 07:24
  • @DrewWelsh You are welcome, if you want to use `DropDownListFor(model=>model.SelectedRole, ...)` then you should have a `SelectedRole` property of type `List` in your `UserViewModel`. – Reza Aghaei Sep 13 '15 at 08:09
  • @DrewWelsh by the way, in StackOverflow, when you find an answer helpful, you can kindly accept it as answer and/or vote it up to be more useful for other users:) – Reza Aghaei Sep 13 '15 at 08:12
  • i have added public List SelectedRole { get; set; } to the VIEWMODEL and this to the VIEW @Html.DropDownListFor(model => model.SelectedRole, new SelectList(Model.RolesList2, "Value", "Text", Model.SelectedRole), "Select a Role"). But no roles are selected. – drewmagoo Sep 13 '15 at 08:42
  • @DrewWelsh When you add `List SelectedRole { get; set; }` to your model, and using `@Html.DropDownListFor(m => m.SelectedRole, new SelectList(Model.RolesList, "Value", "Text", item.Value), "Select a Role")` in view, you will see selected role in combobox, remember you should not set value of this property in controller, if you set a value for it, then dropdownlists will show without selected item – Reza Aghaei Sep 13 '15 at 15:14
  • Thank-you for your time, that is it all working just the way i want it. – drewmagoo Sep 13 '15 at 17:00