jQuery Grid With ASP.Net MVC



Introduction

This article shows how to easily implement paging, sorting, filtering and CRUD operations with the jQuery Grid Plugin in ASP.NET MVC with bootstrap.

Background
 
In the sample project that you can download from this article I'm using jQuery Grid 0.4.3 by gijgo.com, jQuery 2.1.3, Bootstrap 3.3.4 and AspNet.Mvc 5.2.3. A few words about jQuery Grid by gijgo.com. Since the other libraries, that are in use are pretty popular compared to the grid plugin, I'm going to provide you some info about this plugin.
  • Stylish and Featured Tabular data presentation control.
  • JavaScript control for representing and manipulating tabular data on the web.
  • Ajax Enabled.
  • Can be integrated with any of the server-side technologies like ASP, JavaServelets, JSP, PHP and so on.
  • Very simple to integrate with ASP.NET.
  • Supports pagination, JavaScript and server-side data sources.
  • Supports jQuery UI and Bootstrap.
  • Free open-source tool distributed under the MIT License.
You can find the documentation about the version of the plugin that is in use in this article at http://gijgo.com/version_0_4/Documentation. Integrating jQuery Grid with ASP.NET MVC step-by-step.
  • Create a new ASP.NET MVC project in Visual Studio.
  • I assume that jQuery and bootstrap has been added to your ASP.NET MVC project by default. If they are not added you can find and add them to your project via Nuget.
  • Add the jQuery Grid by gijgo.com via Nuget. You can find more info at https://www.nuget.org/packages/jQuery.Grid/
  • Ensure that you have a reference to the jquery.js, bootstrap.css, grid.css and grid.js files in the pages where you are planning to use the jQuery grid.



In order to use the grid plugin you will need a HTML table tag for a base element of the grid. I recommend to use the "data-source" attribute of the table as identification for the location of source URL on the server side.

  1. <table id="grid" data-source="@Url.Action("GetPlayers")"></table> 

Then, we need to initialize the table as a jQuery grid with the fields that we are planning to display in the Grid.

  1. grid = $("#grid").grid({  
  2.    dataKey: "ID",  
  3.    uiLibrary: "bootstrap",  
  4.    columns: [  
  5.    { field: "ID", width: 50, sortable: true },  
  6.    { field: "Name", sortable: true },  
  7.    { field: "PlaceOfBirth", title: "Place Of Birth", sortable: true },  
  8.    { field: "DateOfBirth", title: "Date Of Birth", sortable: true },  
  9.    { field: "Edit", title: "", width: 34, type: "icon", icon: "glyphicon-pencil", tooltip: "Edit", events: { "click": Edit } },  
  10.    { field: "Delete", title: "", width: 34, type: "icon", icon: "glyphicon-        
          remove", tooltip: "Delete", events: { "click": Remove } } 
  11.    ],  
  12.    pager: { enable: true, limit: 5, sizes: [2, 5, 10, 20] }  
  13. }); 

If you want to be able to sort by a specific column you need to set the sortable option of the colum to true. When you do that, the grid plugin will send information to the server about the field name that needs to be sorted. In order to configure paging you need to use the pager option from where you can control the paging.

In the sample project I use the following code to implement simple CRUD operations over the data inside the grid.

  1. function Add() {  
  2.     $("#playerId").val("");  
  3.     $("#name").val("");  
  4.     $("#placeOfBirth").val("");  
  5.     $("#dateOfBirth").val("");  
  6.     $("#playerModal").modal("show");  
  7.   }  
  8.   function Edit(e) {  
  9.     $("#playerId").val(e.data.id);  
  10.     $("#name").val(e.data.record.Name);  
  11.     $("#placeOfBirth").val(e.data.record.PlaceOfBirth);  
  12.     $("#dateOfBirth").val(e.data.record.DateOfBirth);  
  13.     $("#playerModal").modal("show");  
  14.   }  
  15.   function Save() {  
  16.     var player = {  
  17.       ID: $("#playerId").val(),  
  18.       Name: $("#name").val(),  
  19.       PlaceOfBirth: $("#placeOfBirth").val(),  
  20.       DateOfBirth: $("#dateOfBirth").val()  
  21.     };  
  22.     $.ajax({ url: "Home/Save", type: "POST", data: { player: player } })  
  23.       .done(function () {  
  24.         grid.reload();  
  25.         $("#playerModal").modal("hide");  
  26.       })  
  27.       .fail(function () {  
  28.         alert("Unable to save.");  
  29.         $("#playerModal").modal("hide");  
  30.       });  
  31.   }  
  32.   function Remove(e) {  
  33.     $.ajax({ url: "Home/Remove", type: "POST", data: { id: e.data.id } })  
  34.       .done(function () {  
  35.         grid.reload();  
  36.       })  
  37.       .fail(function () {  
  38.         alert("Unable to remove.");  
  39.       });  
  40.   }  
  41.   function Search() {  
  42.     grid.reload({ searchString: $("#search").val() });  
  43.   } 

Server Side

In the Controller we need only the 4 methods Index, GetPlayers, Save and Remove.

  1. [NoCache]  
  2.   public class HomeController : Controller  
  3.   {  
  4.     public ActionResult Index()  
  5.     {  
  6.       return View();  
  7.     }  
  8.   
  9.     [HttpGet]  
  10.     public JsonResult GetPlayers(int? page, int? limit, string sortBy, string direction, string searchString = null)  
  11.     {  
  12.       int total;  
  13.       var records = new GridModel().GetPlayers(page, limit, sortBy, direction, searchString, out total);  
  14.       return Json(new { records, total }, JsonRequestBehavior.AllowGet);  
  15.     }  
  16.   
  17.     [HttpPost]  
  18.     public JsonResult Save(Player player)  
  19.     {  
  20.       new GridModel().Save(player);  
  21.       return Json(true);  
  22.     }  
  23.   
  24.     [HttpPost]  
  25.     public JsonResult Remove(int id)  
  26.     {  
  27.       new GridModel().Remove(id);  
  28.       return Json(true);  
  29.     }  
  30.   } 

Please note that I'm using the custom "[NoCache]" attribute for the controller that will resolve some issues with the caching. I recommend the usage of that attribute or a similar mechanism for the prevention of bugs related to caching.

  1. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]  
  2.   public sealed class NoCacheAttribute : ActionFilterAttribute  
  3.   {  
  4.     public override void OnResultExecuting(ResultExecutingContext filterContext)  
  5.     {  
  6.       filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));  
  7.       filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);  
  8.       filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);  
  9.       filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);  
  10.       filterContext.HttpContext.Response.Cache.SetNoStore();  
  11.       base.OnResultExecuting(filterContext);  
  12.     }  
  13.   } 

In the data model of this example I use XML as a data store to simplify the logic in the model. You can customize the date model as you want and replace my implementation with code using relational databases like Microsoft SQL Server, My SQL or other services that are specific for your project.

I hope that this article will be useful for your project. Happy codding!