6

How do I handle a many to many object mapping in the view and controller in the context of users and roles?

I used entity framework to map to pure POCOs like this:

public class Role
{
    public int RoleId { get; set; }
    public string RoleName { get; set; }
    public List<User> Users { get; set; }
}

public class User
{
    public int UserId { get; set; }
    public List<Role> Roles { get; set; }
}

In my view, I'd like to add a User to a role using checkboxes. I list all the roles then check one to add the user to that role. How do I handle this?

1 Answer 1

15

I would start by designing a view model for this scenario:

public class UserRolesViewModel
{
    public int UserId { get; set; }
    public IEnumerable<RoleViewModel> Roles { get; set; }
}

public class RoleViewModel
{
    public int RoleId { get; set; }
    public bool InRole { get; set; }
    public string RoleName { get; set; }
}

Then a roles controller:

public class RolesController : Controller
{
    public ActionResult Edit(int userId)
    {
        // TODO: Use a repository to fetch the roles associated to the given
        // user id and then AutoMapper to map your model POCOs 
        // to a UserRolesViewModel
        var model = new UserRolesViewModel
        {
            UserId = userId,
            Roles = new[]
            {
                new RoleViewModel { RoleId = 1, InRole = false, RoleName = "Role 1" },
                new RoleViewModel { RoleId = 2, InRole = true, RoleName = "Role 2" },
                new RoleViewModel { RoleId = 3, InRole = true, RoleName = "Role 3" }
            }
        };
        return View(model);
    }

    [HttpPut]
    public ActionResult Update(UserRolesViewModel model)
    {
        // Here you will get the view model back containing the
        // user id and the selected roles
        // TODO: use AutoMapper to map back to a POCO and 
        // invoke the repository to update the database
        return RedirectToAction("Edit");
    }
}

then the Edit view (~/Views/Roles/Edit.cshtml):

@model YourAppName.Models.UserRolesViewModel
@{
    ViewBag.Title = "Edit user roles";
}
<h2>Roles for user @Model.UserId</h2>
@using (Html.BeginForm("Update", "Roles"))
{
    @Html.HttpMethodOverride(HttpVerbs.Put)
    @Html.HiddenFor(x => x.UserId)
    @Html.EditorFor(x => x.Roles)
    <input type="submit" value="update roles" />
}

and finally the corresponding editor template (~/Views/Roles/EditorTemplates/RoleViewModel.cshtml):

@model YourAppName.Models.RoleViewModel
<div>
    @Model.RoleName
    @Html.HiddenFor(x => x.RoleId)
    @Html.CheckBoxFor(x => x.InRole)
</div>
Sign up to request clarification or add additional context in comments.

2 Comments

Could you give alittle more information on this statement: then AutoMapper to map your model POCOs to a UserRolesViewModel
I made a new question about automapper: stackoverflow.com/questions/4653163/automapper-usage

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.