0

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>
Surukuku
  • 11
  • 3
  • You ajax call just posts to `Index()` method - it does not update the DOM (the only thing you do in the `success` function is `console.log("Sucess!")`). Not clear exactly want you want to do but I suspect you need to call a method that returns a partial view with the new checkboxes and update the DOM, or better just return JSON containing the permissions you want set and update the DOM with jquery. –  Jan 17 '15 at 00:41
  • i see, i was hoping i could reuse the Index function in my controller to return the permissions of new Role the user chooses. And the the .ajax request was the way to post the selected value, and then i would redirect to Index action so it can get the records needed. Returning to the view again ...how can i achieve this without partial views, can you help me ? – Surukuku Jan 17 '15 at 19:42
  • Ajax calls stay on the same page (don't redirect). Using `location.hef = URL` kind of defeats the purpose of using ajax (you might as well do a standard submit and redirect in the controller). If you use ajax, typically you would returns a partial view or Json and then update just part of the DOM in the success function based on what you returned to avoid making a redirect. –  Jan 17 '15 at 23:02
  • Thx Stephen, i will try the "return JSon" approach, since I dont want to use partial views here. – Surukuku Jan 19 '15 at 09:48
  • Stephen, could tou check Update 2 in my Post ? i ended up using the partial view as you pointed out.Can tou confirm if the async usage is done in a proper way ? every works as expected, thx for helping me along the way :) – Surukuku Jan 19 '15 at 15:37
  • I can really comment on the use of async. Only you can determine if it provides any benefits over a normal method. –  Jan 20 '15 at 04:50
  • ok, thx for helping! i think for my this solution suits me. :) – Surukuku Jan 20 '15 at 11:25

0 Answers0