I've looking all over for something similar, couldn't find nothing.. I'm using ASP.NET MVC 4. I'm building a page so the users in my app can manage the permissions associated with each role. So i have a view with @htmlDropDownList to show all the available roles, and below, one @Html.CheckBox for each Permission of the role wich is selected above.
The first time the view is rendered, the checkboxes are all set to true or false, according to the permission of that role.All is fine, life is good :) . When the value of the drop is changed, i post the SelectedRoleId using $.ajax. Then, i fetch all the permissions of the new selected role. While in debug, in the razor view, i can confirm the new values (true or false) inside the model are correct. The problem is that the checkboxes show the old values, before the role was changed.. This is my first question asked, so i'll have to apologize if the question is not being made the best way. And thx in advance to all of you :)
So here's my Controller:
public ActionResult Index(int ? SelectedRoleId)
{
ManagePermissionsViewModel model = new ManagePermissionsViewModel();
if (SelectedRoleId == null)
{
model.SelectedRoleID = 1; // value 1 is the supervisor Role
}
else
{
model.SelectedRoleID = SelectedRoleId;
}
//values for the dropdownlist of Roles
var items = from x in db.UserRoles
select x;
model.RoleList = new SelectList(items, "Id", "DESCRIPTION");
//gets all the permissions of the selected role
model.EntirePermissionList = (from k in db.Permissions
select new Permission
{
IdPermission = k.Id,
PermissionDescription = k.Description,
IsSet = db.RolePermissions.Any(n => n.RoleId == model.SelectedRoleID && n.PermissionId == k.Id),
PermissionGroupId = (int)k.PermissionGroupId
}).ToList();
//Gets all the groups of Permissions
model.ListPermissionGroups = (from l in db.PermissionGroups
select new PermissionGroup
{
Id = l.Id,
Description = l.Description
}).ToList();
return View(model);
}
[HttpPost]
public ActionResult Index(FormCollection form) {
switch (form["SubmitButton"])
{
case "Save":
SavePermissions();
break;
default:
return RedirectToAction("Index", new RouteValueDictionary(new { controller = "ManagePermissions", action = "Index", SelectedRoleId = Convert.ToInt32(form["SelectedRoleId"]) }));
}
return View();
}
And here is my View:
'@model AML.Web.Models.ManagePermissionsViewModel
@using (Html.BeginForm("Index", "ManagePermissions", FormMethod.Post, new { id = "MyForm" }))
{
@Html.Label("Role :", htmlAttributes: new { @class = "control-label col-md-2" })
@Html.DropDownList("RoleId", Model.RoleList, new { id = "RoleId" })
<div>
@foreach (var item in Model.ListPermissionGroups)
{
<h3> @item.Description</h3>
foreach (var permission in Model.EntirePermissionList.Where(n => n.PermissionGroupId == item.Id))
{
<h5>
@permission.PermissionDescription
@Html.CheckBox("Chk_Permisssion", permission.IsSet)
</h5>
}
}
</div>
<input type="submit" value="Save" name="SubmitButton" class="btn btn-default" />
}
@section Scripts {
<script type="text/JavaScript">
$(document).ready(function () {
$("#RoleId").change(function (e) {
e.preventDefault();
$.ajax({
url: "/ManagePermissions/Index",
cache: false,
type: "POST",
data: { 'SelectedRoleId': $(this).val() },
dataType: "json",
success: function (result) { console.log("Sucess!"); },
error: function (error) { console.log("Error!"); }
})
});
});
</script>
}
And my viewModel:
public class ManagePermissionsViewModel
{
public int? SelectedRoleID { get; set; }
public string SelectedRoleDescription { get; set; }
public SelectList RoleList { get; set; }
public List<Permission> EntirePermissionList { get; set; }
public List<PermissionGroup> ListPermissionGroups { get; set; }
}
public class Permission
{
public int IdPermission { get; set; }
public bool IsSet { get; set; }
public string PermissionDescription { get; set; }
public int PermissionGroupId { get; set; }
}
public class PermissionGroup {
public int Id { get; set; }
public string Description{ get; set; }
}
UPDATE 1 - Well, i think i got it. Let me post my approach
In the View:
@Html.DropDownListFor(n => n.SelectedRoleID, Model.RoleList,null,
new { onchange = "document.location.href = '/ManagePermissions/Index?SelectedRoleId=' + this.options[this.selectedIndex].value;" })
<div>
@foreach (var item in Model.ListPermissionGroups)
{
<h3> @item.Description</h3>
foreach (var permission in Model.EntirePermissionList.Where(n => n.PermissionGroupId == item.Id))
{
<h5>
@permission.PermissionDescription
<input type="checkbox" id="@permission.IdPermission" checked="@permission.IsSet">
</h5>
}
}
</div>
And in the Controller:
public ActionResult Index(int? SelectedRoleId)
{
ManagePermissionsViewModel model = new ManagePermissionsViewModel();
ModelState.Clear();
if (SelectedRoleId == null)
{
model.SelectedRoleID = 1;
}
else
{
model.SelectedRoleID = SelectedRoleId;
}
var items = from x in db.UserRoles
select x;
model.RoleList = new SelectList(items, "Id", "DESCRIPTION");
model.EntirePermissionList = (from k in db.Permissions
select new Permission
{
IdPermission = k.Id,
PermissionDescription = k.Description,
IsSet = db.RolePermissions.Any(n => n.RoleId == model.SelectedRoleID && n.PermissionId == k.Id),
PermissionGroupId = (int)k.PermissionGroupId
}).ToList();
model.ListPermissionGroups = (from l in db.PermissionGroups
select new PermissionGroup
{
Id = l.Id,
Description = l.Description
}).ToList();
ModelState.Clear();
return View(model);
}
Now each time the Drop changes value, the permissions in the checkboxes are updated. I got it to work with the attribute on the drop, "on change = Document.location.hef = URL". Is this a good approach? Or should i use something like ajax request ?
UPDATE 2
The Controller:
public async Task<ActionResult> Index(int? SelectedRoleId)
{
if (SelectedRoleId == null)
{
SelectedRoleId = 1;
}
var model = await GetSelectedPermissions(SelectedRoleId);
return this.View("Index",model);
}
[HttpGet]
public async Task<ActionResult> GetPermissions(string Id)
{
var SelectedRoleId = int.Parse(Id);
var model = await this.GetSelectedPermissions(SelectedRoleId);
return PartialView("_ManagePermissions", model);
}
private async Task<ManagePermissionsViewModel> GetSelectedPermissions(int? SelectedRoleId)
{
ModelState.Clear();
ManagePermissionsViewModel model = new ManagePermissionsViewModel();
model.SelectedRoleID = SelectedRoleId;
var items = from x in db.UserRoles
select x;
model.RoleList = new SelectList(items, "Id", "DESCRIPTION");
model.EntirePermissionList = await (from k in db.Permissions
select new Permission
{
IdPermission = k.Id,
PermissionDescription = k.Description,
IsSet = db.RolePermissions.Any(n => n.RoleId == model.SelectedRoleID && n.PermissionId == k.Id),
PermissionGroupId = (int)k.PermissionGroupId
}).ToListAsync();
model.ListPermissionGroups = await (from l in db.PermissionGroups
select new PermissionGroup
{
Id = l.Id,
Description = l.Description
}).ToListAsync();
return model;
}
The View
<h2>Permissions - Ajax with Partial View</h2>
@using (Html.BeginForm("SaveData", "ManagePermissions", FormMethod.Post, new { id = "MyForm" }))
{
@Html.Label("Role :", htmlAttributes: new { @class = "control-label col-md-2" })
@Html.DropDownListFor(n => n.SelectedRoleID, Model.RoleList, null, null)
<div id="target">
@Html.Partial("~/Views/Shared/_ManagePermissions.cshtml", Model)
</div>
<input type="submit" value="Save" name="SubmitButton" class="btn btn-default" />
}
@section Scripts {
<script type="text/javascript">
$(document).ready(function () {
$("#SelectedRoleID").change(function () {
var SelectedRoleID = $("#SelectedRoleID").val();
$("#target").load('@(Url.Action("GetPermissions","ManagePermissions",null, Request.Url.Scheme))?Id=' + SelectedRoleID);
});
});
</script>
}
And the Partial View:
<div>
@foreach (var item in Model.ListPermissionGroups)
{
<h3> @item.Description</h3>
foreach (var permission in Model.EntirePermissionList.Where(n => n.PermissionGroupId == item.Id))
{
<h5>
@permission.PermissionDescription
<input type="checkbox" id="@permission.IdPermission" checked="@permission.IsSet">
</h5>
}
}
</div>