1

I'm working on an ASP.NET Core 2.2 MVC app and am trying to implement Bootstrap Dual Listbox plugin for role selection. I have _UserEditorPartial.cshtml view that can be used to assign roles to a user (the listbox on the right would contain roles assigned):

enter image description here

(The partial has more editable fields, but I think those are irrelevant)

Now, the partial contains data associated with the user I had selected on the parent page. When I select the user, I just pass UserID to ViewUserEditorPartial and query the database to retrieve the whole list of roles available, marking the IsAssigned property to true if the user belongs to the role. So now, I have a list of roles and I know which role belongs to the user.

What I'm struggling with is figuring out how to make sure that the roles belonging to the user end up in in the listbox on the right. If the user belongs to Role2 and Role4, I want my view to be generated like this:

enter image description here

I've found this solution but it's not obvious to me how the two listboxes are correctly populated. I'm thinking after loading the partial I could probably do something with JavaScript, where I separately retrieve the List<RoleUserAssignment> with AJAX and, depending on the value of IsAssigned property for each role, generate the <option> tag in the correct listbox. But I'm wondering is there a better approach?

Also, I'll implement the ability to create users and assign them roles using this solution that I found.

Models:

public class Role
{
    public int RoleID { get; set; }
    public string RoleName { get; set; }
}

public class User 
{
    public int UserID { get; set; }
    public string UserName { get; set; }
}

public class RoleUserAssignment
{
    public RoleUserAssignment()
    {
        Role = new Role();
        User = new User();
    }
    
    public Role Role { get; set; }
    public User User { get; set; }
    public bool IsAssigned { get; set; } //true if user has role
}

public class UserEditing
{
    public UserEditing()
    {
        RoleUserAssignments = new List<RoleUserAssignment>();
    }

    public List<RoleUserAssignment> RoleUserAssignments { get; set; }
}

HTML

@model UserEditing
<script>
    $(document).ready(function () {
        $('#rolesSelection').bootstrapDualListbox({});
    });
</script>
<form id="userEditorForm">
    <div>Roles</div>
    <select id="rolesSelection" class="form-control" class="form-control" asp-for="@Model.RoleUserAssignments" asp-items="@(new SelectList(Model.RoleUserAssignments, "Role.RoleID", "Role.RoleName"))"
            multiple="multiple">
    </select>
</form>

ViewUserEditorPartial action:

[HttpGet]
public IActionResult ViewUserEditorPartial(int UserID)
{
    UserEditing userEditing = new UserEditing();
    userEditing.RoleUserAssignments = _userAdmin.GetRoleUserAssignmentsByUserID(_appSettings.MOPConfigConnectionString, UserID);

    return PartialView("_UserEditorPartial", userEditing);
}

1 Answer 1

1

What I'm struggling with is figuring out how to make sure that the roles belonging to the user end up in in the listbox on the right.

To achieve this function, you can avoid implementing it in js, it will be easier to implement it in the controller.

You can first get the RoleID data lists that the user belongs to the role, then put the lists into the ViewData in the ViewUserEditorPartial action, and then bind the value of ViewData to the asp-for attribute when binding the select.

Here is my demo:

[HttpGet]
public IActionResult ViewUserEditorPartial(int UserID)
{
    UserEditing userEditing = new UserEditing();
    var roleUserAssignData = _userAdmin.GetRoleUserAssignmentsByUserID(_appSettings.MOPConfigConnectionString, UserID);
    userEditing.RoleUserAssignments = roleUserAssignData;
    
   // get the data which IsAssigned field are true and select the RoleID of each data. 
    ViewData["SelectedRoles"] = roleUserAssignData.Where(x => x.IsAssigned).Select(x => x.Role.RoleID).ToList(); 
    return PartialView("_UserEditorPartial", userEditing);
}

_UserEditorPartial view:

 @model UserEditing
    <script>
        $(document).ready(function () {
            $('#rolesSelection').bootstrapDualListbox({});
        });
    </script>
    <form id="userEditorForm">
        <div>Roles</div>
        <select id="rolesSelection" class="form-control" class="form-control" 
                asp-for="@ViewData["SelectedRoles"]" 
                asp-items="@(new SelectList(Model.RoleUserAssignments, "Role.RoleID", "Role.RoleName"))"
                multiple="multiple">
        </select>
    </form>

Update

If allowed, add List<int> type field named SelectedRoles in UserEditing model to store the selected roles is better.

 public class UserEditing
    {
        public UserEditing()
        {
            RoleUserAssignments = new List<RoleUserAssignment>();
        }
        public List<int> SelectedRoles { get; set; }
        public List<RoleUserAssignment> RoleUserAssignments { get; set; }
    }

In ViewUserEditorPartial action, change ViewData sentence to the following:

userEditing.SelectedRoles = roleUserAssignData.Where(x => x.IsAssigned).Select(x => x.Role.RoleID).ToList(); 

_UserEditorPartial view:

<form id="userEditorForm">
    <div>Roles</div>
    <select id="rolesSelection" class="form-control" asp-for="@Model.SelectedRoles" 
            asp-items="@(new SelectList(Model.RoleUserAssignments, "Role.RoleID", "Role.RoleName"))"
            multiple="multiple">
    </select>
</form>
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, this works! In this case, is using ViewData preferable over having SelectedRoles list as a property in UserEditing view model?
@Lukas, If your code allows you to add a SelectedRoles field of type List<int> to UserEditing model, then I think this is a better choice. I have updated this method in my reply, please refer to it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.