I had the problem of having a list of check-boxes being displayed in my view.
I’ll be using a scenario many of us are familiar with, Users and Roles. I’ll be using ASP.NET MCV 3 with the Razor view engine syntax.
Here is my ViewModel:
public class UserRoleViewModel
{
public UserRoleViewModel()
{
Roles = new List<RoleViewModel>();
}
public string UserId { get; set; }
public List<RoleViewModel> Roles { get; set; }
}
public class RoleViewModel
{
public bool IsInRole { get; set; }
[HiddenInput(DisplayValue = false)]
public int RoleId { get; set; }
[HiddenInput(DisplayValue = true)]
public string RoleName { get; set; }
}Now we need our Actions:
public ActionResult EditUserRole(string userId)
{
var user = userService.GetUser(userId);
var roles = userService.GetRoles();
UserRoleViewModel viewModel = new UserRoleViewModel();
viewModel.UserId = user.UserId;
//Match the roles the user is in with the list of roles
foreach (var role in roles)
{
viewModel.Roles.Add(new RoleViewModel
{
IsInRole = user.Roles.Any(r => r.RoleId == role.RoleId),
RoleId = role.RoleId,
RoleName = role.RoleName
});
}
return View(viewModel);
}
[HttpPost]
public ActionResult EditUserRole(UserRoleViewModel model)
{
List<Role> roles = model.Roles.Where(r => r.IsInRole).Select(r => new Role {RoleId = r.RoleId, RoleName = r.RoleName}).ToList();
userService.AddRolesToUser(model.UserId, roles);
return View();
}Now we need to setup our view. This is our EditUserRole.cshtml
@model WebUI.ViewModel.UserRoleViewModel
@using (Html.BeginForm("EditUserRole", "Administrator"))
{
@Html.HiddenFor(x => Model.UserId)
@Html.EditorFor(x => Model.Roles)
<input type="submit" />
}This is our editor template, located at: ~/Shared/EditorTemplates/RoleViewModel.cshtml . Make sure the name of the file is the same name as the viewmodel you are sending.
@model WebUI.ViewModel.RoleViewModel
@Html.CheckBoxFor(m => m.IsInRole)
@Html.HiddenFor(m => m.RoleId)
@Html.LabelFor(m => m.IsInRole, Model.RoleName)
<br />And thats it. No explanation needed.




I am looking for a simple example of MVC3 checkboxes. This looks great! Can you post a link to a working example so I can download and dissect in Visual Studio?
How does @Html.EditorFor(x=>Model.Roles) render the partial view for check boxes? It didn’t happen in mine. I explictly wrote @Html.Partial(“CheckBoxViewModel”,Model.Roles).
Is this what we need to do?
You need an editor template at: /Shared/EditorTemplates/RoleViewModel.cshtml. Make sure the name of the file is the same name as the viewmodel you are sending. This is how @Html.EditorFor(x=>Model.Roles) know to use that template.
Shawn, would you happen to know why in the POST the role name and the role id are not persisted (they are null) is the List of of RoleViewModel items… the IsSelected is correct and returned properly in the POST (EditUserRole)
Allan
Sorry… I should note that I’m using MVC4 but that “shouldn’t” make a difference
LOL… Me again. I worked out the problem and thought I’d post it for others… my stupid mistake.
I initially thought both the Id and the Role name were not being persisted when returning to the POST Action but it was just the RoleName that wasn’t – the Id was being persisted.
I only needed to add a ‘@Html.HiddenFor(m => m.RoleName)’ in the EditorTemplate file in order to retain the name of the role : as follows.
@model WebBoard.Web.Models.RoleViewModel
@Html.CheckBoxFor(m => m.IsInRole)
@Html.LabelFor(m => m.IsInRole, Model.rName)
@Html.HiddenFor(m => m.RoleId)
@Html.HiddenFor(m => m.RoleName)
Thanks for the article – it was very helpful
Hi,
Thanks,it was a great article.
How do we validate the roles checkbox list,so that at least one option is selected? Your help would be greatly appreciated.
I kept having issues trying to add users to roles, then I realized you were not removing roles when i unchecked them. So I modified the [httppost] function slightly… more code and someone could make it look more efficient, but this works for me…
List addRoles = new List();
List removeRoles = new List();
//this function retrieves my account view model and has a string[] Roles list
AccountModel user = http://www.Controllers.AccountController.getAccount(UserName);
bool addit;
foreach (RoleModel rm in model.Roles) //loop through new roles
{
addit = rm.IsInRole;
foreach (string roleName in user.Roles) //loop through existing roles
{
if (rm.Name == roleName)
{
if (addit)
addit = false; //user already in this role
else removeRoles.Add(roleName);
break;
}
}
if (addit) addRoles.Add(rm.Name);
}
if (addRoles.Count > 0) System.Web.Security.Roles.AddUserToRoles(UserName, addRoles.ToArray());
if (removeRoles.Count > 0) System.Web.Security.Roles.RemoveUserFromRoles(UserName, removeRoles.ToArray());
I created editor template at /Shared/EditorTemplates/. But it’s not working. How should i do next?
Excellent. Thank you. I learned about 6 things from this post.
You’re welcome. I appreciate comments like these to know I am helping others.