To be able to use it with ASP.NET MVC and JSON I created a generic model class to easier reuse it when passing it around in MVC actions in the controller.
To load jqGrid with data (JSON) I call an MVC action like this:
1: $('#StoreGrid').jqGrid({
2: url: '<%=Url.Action("StoreList", "StoreController") %>',
3: datatype: 'json',
4: mtype: 'POST',
5: colNames: ['Store Name', 'Store Address'],
6: colModel: [7: { name: 'Name', index: 'Name' },
8: { name: 'Address', index: 'Address'},
9: ] 10: ... 1: public JsonResult StoreList(string sidx, string sord, int page, int rows)
2: { 3: ...4: // Load data from repository
5: IQueryable<Store> stores = _repository.GetAllStores();6: int totalRecords = stores.Count();
7: int totalPages = (int)Math.Ceiling(totalRecords/(double)rows);
8: 9: // Convert business model to view model
10: List<StoreListItem> storeListItems = 11: stores 12: .Select(s => new StoreListItem(s.Id, s.Name, s.Address)
13: .ToList(); 14: 15: // Create JSON data that jqGrid understands :-)
16: var jsonData = new JqGridJsonModelView<StoreListItem>
17: { 18: total = totalPages, 19: page = page, 20: records = totalRecords, 21: rows = storeListItems 22: };23: return Json(jsonData, JsonRequestBehavior.AllowGet);
1: /// <summary>
2: /// See http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_data3: /// </summary>
4: public class JqGridJsonModelView<T> where T : IHaveJqGridCells
5: {6: /// <summary>
7: /// Total number of pages
8: /// </summary>
9: public int total { get; set; }
10: 11: /// <summary>
12: /// Current page
13: /// </summary>
14: public int page { get; set; }
15: 16: /// <summary>
17: /// Total number of records
18: /// </summary>
19: public int records { get; set; }
20: 21: public IList<T> rows { get; set; }
22: } 1: public interface IHaveJqGridCells
2: {3: string id { get; set; }
4: 5: string[] cell { get; }
6: } 1: public class StoreListItem : IHaveJqGridCells
2: {3: // Implement interface
4: public string id { get; set; }
5: 6: // Private properties to "disable" serialization (no need to be public anyway)
7: readonly string Name;
8: readonly string Address;
9: 10: public StoreListItem(int id, string name, string address)
11: {12: this.id = id.ToString();
13: 14: Name = name; 15: Address = address; 16: } 17: 18: // Implement interface
19: public string[] cell
20: { 21: get 22: {23: return new[] { Name, Address }
24: } 25: } 26: 1: {
2: "total" : "xxx",
3: "page" : "yyy",
4: "records" : "zzz",
5: "rows" : [
6: {"id" : "1", "cell" : ["Store 1", "Address 1"]},
7: {"id" : "2", "cell" : ["Store 2", "Address 2"]},
8: ... 9: ] 10: }Hope you like it!
Update (requested by danlimerick):
If you want to do sorting/paging. I usually use Dynamic Linq Query Library and make sure the naming in the jqGrid colModel corrolates to the naming in the repository:
1: IQueryable<Store> stores = _repository.GetStores(sidx, sord, (page - 1), rows);
2: 3: ... 4: 5: public IQueryable<Store> GetStores(string sortIndex, string sortOrder, int page, int rowsPerPage)
6: {7: return _context.Store
8: .OrderBy(sortIndex + " " + sortOrder)
9: .Skip(page * rowsPerPage) 10: .Take(rowsPerPage); 11: }
Totally agree that jqGrid is nice. I get why you ignore the sorting, paging etc. but that is the hard part of using jqGrid. Any chance of a follow up post focusing on how to do sorting and paging together and how to implement that in an elegant way in the repository?
ReplyDeleteAgree!
ReplyDeleteThe only thing is I don't know any *elegant* way of doing it. The same problem as with Linq2Sql when it comes to paging and sorting.
I usually use DynamicQuery and pass jqGrid colModel names and make sure the naming correlates to the naming in the repository.