Hi,
I am trying to create a permissions view for my MVC 4 application.
What I want to achieve is that the selection made on the users table, populates the payrolls this person can access in a second table, then by selecting a payroll from the second table I would like it to display the permissions that user has within the selected payroll. So exactly like this http://demos.telerik.com/aspnet-ajax/grid/examples/clientmasterdetails/defaultcs.aspx but three tables instead of 2.
I can get a grid to populate with the users but where I am strugling is getting the selected user to query the payrolls and populate the payrolls table. I am quite new to all this so I am not quite sure how the selection gets the data and renders the grid? Does this call an ajax action in the view controller? And how is the second grid element then rendered? Does it re-render the first grid with the list of users again or will this persits?
My controller so far is like this NB the ReadPay and ReadPay Functions and all the ViewData in the Index action are my attempts to get this to work so please ignore them if they are wrong and point me in the right direction if possible please:
This is my view so far, again the second grid code and the selectable: true in the first grid are my attempts to get this to work:
Your help will be greatly appreciated!
Andy
I am trying to create a permissions view for my MVC 4 application.
What I want to achieve is that the selection made on the users table, populates the payrolls this person can access in a second table, then by selecting a payroll from the second table I would like it to display the permissions that user has within the selected payroll. So exactly like this http://demos.telerik.com/aspnet-ajax/grid/examples/clientmasterdetails/defaultcs.aspx but three tables instead of 2.
I can get a grid to populate with the users but where I am strugling is getting the selected user to query the payrolls and populate the payrolls table. I am quite new to all this so I am not quite sure how the selection gets the data and renders the grid? Does this call an ajax action in the view controller? And how is the second grid element then rendered? Does it re-render the first grid with the list of users again or will this persits?
My controller so far is like this NB the ReadPay and ReadPay Functions and all the ViewData in the Index action are my attempts to get this to work so please ignore them if they are wrong and point me in the right direction if possible please:
using System;using System.Collections.Generic;using System.Data;using System.Data.Entity;using System.Linq;using System.Web;using System.Web.Mvc;using PayPlate.Models;using PayPlate.DAL;using PagedList;namespace PayPlate.Controllers { public class UserController : Controller { UnitOfWork unitOfWork = new UnitOfWork(); public ActionResult Index(Int32 ? uid, Int32 ? pid) { ViewData["Users"] = Read(); if (uid == null) { uid = unitOfWork.UserRepository.Get().FirstOrDefault().UserID; } ViewData["uid"] = uid; ViewData["Payrolls"] = ReadPay(uid.Value); if (pid == null) { pid = unitOfWork.UserRepository.Get(i => i.UserID == uid).Single().Permissions.Select(p => p.PayrollID).Distinct().FirstOrDefault(); } ViewData["pid"] = pid; ViewData["Permissions"] = ReadPerm(uid.Value, pid.Value); return View(); } public IEnumerable<Payroll> ReadPay(Int32 uid) { var pays = unitOfWork.UserRepository.Get(i => i.UserID == uid).Single().Permissions.Select(p => p.Payroll).Distinct(); // Use a view model to avoid serializing internal Entity Framework properties as JSON pays = pays.Select(p => new Payroll { PayrollID = p.PayrollID, Title = p.Title, C21Name = p.C21Name, Server = p.Server, Port = p.Port, Connection = p.Connection }) .ToList(); return pays; } public IEnumerable<Permission> ReadPerm(Int32 uid, Int32 pid) { var viewModel = new PayrollIndexData(); var selectedPay = viewModel.Payrolls.Where(x => x.PayrollID == pid).Single(); var usersPay = selectedPay.Permissions.Where(u => u.UserID == uid); viewModel.Permissions = usersPay; var perms = viewModel.Permissions; return perms; }
/// <summary> /// Creates new products by inserting the data posted by the Kendo Grid in the database. /// </summary> /// <param name="products">The products created by the user.</param> /// <returns>The inserted products so the Kendo Grid is aware of the database generated ProductID</returns> [HttpPost] public ActionResult Create(IEnumerable<User> _users) { var result = new List<User>(); //Iterate all created products which are posted by the Kendo Grid foreach (var user in _users) { // Create a new Product entity and set its properties from productViewModel var _user = new User { NetLogin = user.NetLogin, EmpNumber = user.EmpNumber, Forename = user.Forename, Surname = user.Surname, Active = user.Active }; // store the product in the result result.Add(_user); // Add the entity unitOfWork.UserRepository.Insert(_user); } // Insert all created products to the database unitOfWork.Save(); // Return the inserted products - the Kendo Grid needs their ProductID which is generated by SQL server during insertion return Json(result.Select(p => new User { UserID = p.UserID, NetLogin = p.NetLogin, EmpNumber = p.EmpNumber, Forename = p.Forename, Surname = p.Surname, Active = p.Active }) .ToList()); } /// <summary> /// Reads the available products to provide data for the Kendo Grid /// </summary> /// <returns>All available products as JSON</returns> [HttpPost] public ActionResult Read() { var _users = unitOfWork.UserRepository.Get() // Use a view model to avoid serializing internal Entity Framework properties as JSON .Select(p => new User { UserID = p.UserID, NetLogin = p.NetLogin, EmpNumber = p.EmpNumber, Forename = p.Forename, Surname = p.Surname, Active = p.Active }) .ToList(); return Json(_users); } /// <summary> /// Updates existing products by updating the database with the data posted by the Kendo Grid. /// </summary> /// <param name="products">The products updated by the user</param> [HttpPost] public ActionResult Update(IEnumerable<User> _users) { //Iterate all created products which are posted by the Kendo Grid foreach (var user in _users) { // Attach the entity unitOfWork.UserRepository.Update(user); } // Save all updated products to the database unitOfWork.Save(); //Return emtpy result return Json(null); } /// <summary> /// Destroys existing products by deleting them from the database. /// </summary> /// <param name="products">The products deleted by the user</param> [HttpPost] public ActionResult Destroy(IEnumerable<User> _users) { //Iterate all destroyed products which are posted by the Kendo Grid foreach (var user in _users) { // Delete the entity unitOfWork.UserRepository.Delete(user); } // Delete the products from the database unitOfWork.Save(); //Return emtpy result return Json(null); } // // GET: /User/Details/5 public ViewResult Details(Int32? id, Int32? payrollID, IEnumerable<User> _users) { var viewModel = new PayrollIndexData(); foreach (var _user in _users) { viewModel.Users = unitOfWork.UserRepository.Get(i => i.UserID == _user.UserID); } if (id != null) { ViewBag.UserID = id.Value; viewModel.Payrolls = unitOfWork.UserRepository.Get(i => i.UserID == id.Value).Single().Permissions.Select(p => p.Payroll).Distinct(); } if (payrollID != null) { ViewBag.PayrollID = payrollID.Value; var selectedPayroll = viewModel.Payrolls.Where(x => x.PayrollID == payrollID).Single(); var usersPayroll = selectedPayroll.Permissions.Where(u => u.UserID == id.Value); viewModel.Permissions = usersPayroll; } return View(viewModel); } protected override void Dispose(bool disposing) { unitOfWork.Dispose(); base.Dispose(disposing); } }}This is my view so far, again the second grid code and the selectable: true in the first grid are my attempts to get this to work:
@section CustomHeader { @* kendo.common.min.css contains common CSS rules used by all Kendo themes *@ <link href="http://cdn.kendostatic.com/2012.2.710/styles/kendo.common.min.css" rel="stylesheet" /> @* kendo.silver.min.css contains the "Blue Opal" Kendo theme *@ <link href="http://cdn.kendostatic.com/2012.2.710/styles/kendo.silver.min.css" rel="stylesheet" /> <script src="http://cdn.kendostatic.com/2012.2.710/js/kendo.all.min.js"></script>}<h2>Users</h2>@* The DIV where the Kendo grid will be initialized *@<div id="grid"></div><script>$(function () { $("#grid").kendoGrid({ height: 425, selectable: "true", columns: [ { field: "NetLogin", width: "60px" }, { field: "EmpNumber", width: "60px" }, { field: "Forename", width: "90px" }, { field: "Surname", width: "90px" }, { field: "Active", width: "45px" }, { command: "destroy", title: "Command", width: "120px", groupable: false, filterable: false } ], change: function() { var row = this.select(); var id = row.data("id"); $("#log").html("selected row with id= " + id); var secondGrid = $("#grid2").data("kendoGrid"); var row = secondGrid.table.find('tr[data-id="' + id + '"]'); secondGrid.select(row); }, editable: true, // enable editing sortable: true, pageable: true, filterable: true, groupable: true, resizable: true, reorderable: true, toolbar: ["create", "save", "cancel"], // specify toolbar commands dataSource: { pageSize: 20, schema: { model: { // define the model of the data source. Required for validation and property types. id: "UserID", fields: { UserID: { editable: false, nullable: true }, NetLogin: { validation: { required: true } }, EmpNumber: { validation: { required: true } }, Forename: { validation: { required: true } }, Surname: { validation: { required: true } }, Active: { validation: { required: false } } } } }, batch: true, // enable batch editing - changes will be saved when the user clicks the "Save changes" button transport: { create: { url: "@Url.Action("Create", "User")", //specify the URL which should create new records. This is the Create method of the HomeController. type: "POST" //use HTTP POST request as the default GET is not allowed for ASMX }, read: { url: "@Url.Action("Read", "User")", //specify the URL which should return the records. This is the Read method of the HomeController. type: "POST" //use HTTP POST request as by default GET is not allowed by ASP.NET MVC }, update: { url:"@Url.Action("Update", "User")", //specify the URL which should update the records. This is the Update method of the HomeController. type: "POST" //use HTTP POST request as by default GET is not allowed by ASP.NET MVC }, destroy: { url: "@Url.Action("Destroy", "User")", //specify the URL which should destroy the records. This is the Destroy method of the HomeController. type: "POST" //use HTTP POST request as by default GET is not allowed by ASP.NET MVC }, parameterMap: function(data, operation) { if (operation != "read") { // post the products so the ASP.NET DefaultModelBinder will understand them: // _users[0].Value="value" // _users[0].UserID =1 // _users[1].Value="value" // _users[1].UserID =1 var result = {}; for (var i = 0; i < data.models.length; i++) { var _user = data.models[i]; for (var member in _user) { result["_users[" + i + "]." + member] = _user[member]; } } return result; } } } } });});</script><h2>Payrolls</h2>@* The DIV where the Kendo grid will be initialized *@<div id="grid2"></div><script> $(function () { $("#grid2").kendoGrid({ height: 425, columns: [ { field: "PayrollID", width: "45px" }, { field: "Title", width: "100px" }, { field: "C21Name", width: "70px" }, { field: "Server", width: "70px" }, { field: "Port", width: "30px" }, { field: "Connection", width: "130px" } ], sortable: true, pageable: true, filterable: true, groupable: true, resizable: true, reorderable: true, dataSource: { pageSize: 20, schema: { model: { // define the model of the data source. Required for validation and property types. id: "PayrollID", fields: { PayrollID: { editable: false, nullable: true }, Title: { validation: { required: true} }, C21Name: { validation: { required: true} }, Server: { validation: { required: true} }, Port: { validation: { required: true} }, Connection: { validation: { required: true} } } } }, parameterMap: function (data, operation) { if (operation != "read") { // post the products so the ASP.NET DefaultModelBinder will understand them: // agrps[0].Value="value" // agrps[0].PayrollID =1 // agrps[1].Value="value" // agrps[1].PayrollID =1 var result = {}; for (var i = 0; i < data.models.length; i++) { var pay = data.models[i]; for (var member in pay) { result["pays[" + i + "]." + member] = pay[member]; } } return result; } } } }); });</script>Your help will be greatly appreciated!
Andy