ASP.NET MVC 5 - Buttons In Datatables jQuery Plugin

Table view is one of the most important and basic forms of presenting data on a web page. However, adding action to each row is equally important simply because action for each row leads to different results. Jquery Datatables plugin is one of the most used plugins, as I have demonstrated its integration in one of my articles,  ASP.NET MVC5 - Datables Plugin Server Side Integration.

In this article I will demonstrate the idea of using any kind of action within jquery based datatables plugin.



Prerequisites

 

Following are some prerequisites before you proceed any further in this tutorial,

  1. Knowledge about ASP.NET MVC5.
  2. Knowledge about HTML.
  3. Knowledge about Javascript.
  4. Knowledge about AJAX.
  5. Knowledge about CSS.
  6. Knowledge about Bootstrap.
  7. Knowledge about C# programming.
  8. Knowledge about C# LINQ.
  9. Knowledge about JQuery.
  10. Knowledge about WebMethod attribute
  11. Knowledge about Datatebles plugin

You can download the complete source code for this tutorial or you can follow the step by step discussion below. The sample code is developed in Microsoft Visual Studio 2015 Enterprise. I am using SalesOrderDetail table extract from Adventure Works Sample Database.

Let's begin now.

Step 1

Create new MVC5 web application project and name it "MVC5DatatablesWithButton".

Step 2

Open "Views\Shared\_Layout.cshtml" page and replace following code in it i.e.

  1. <!DOCTYPE html>    
  2. <html>    
  3. <head>    
  4.     <meta charset="utf-8" />    
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">    
  6.     <title>@ViewBag.Title</title>    
  7.     @Styles.Render("~/Content/css")    
  8.     @Scripts.Render("~/bundles/modernizr")    
  9.     
  10.     <!-- Font Awesome -->    
  11.     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" />    
  12.     
  13.     <!-- Data table -->    
  14.     <link rel="stylesheet" href="https://cdn.datatables.net/1.10.10/css/dataTables.bootstrap.min.css " />    
  15.     
  16.     @* Custom *@    
  17.     @Styles.Render("~/Content/css/custom-style")    
  18. </head>    
  19. <body>    
  20.     <div class="navbar navbar-inverse navbar-fixed-top">    
  21.         <div class="container">    
  22.             <div class="navbar-header">    
  23.                 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">    
  24.                     <span class="icon-bar"></span>    
  25.                     <span class="icon-bar"></span>    
  26.                     <span class="icon-bar"></span>    
  27.                 </button>    
  28.             </div>    
  29.         </div>    
  30.     </div>    
  31.     <div class="container body-content">    
  32.         @RenderBody()    
  33.         <hr />    
  34.         <footer>    
  35.             <center>    
  36.                 <p><strong>Copyright © @DateTime.Now.Year - <a href="http://www.asmak9.com/">Asma's Blog</a>.</strong> All rights reserved.</p>    
  37.             </center>    
  38.         </footer>    
  39.     </div>    
  40.     
  41.     @Scripts.Render("~/bundles/jquery")    
  42.     @Scripts.Render("~/bundles/bootstrap")    
  43.     
  44.     <!-- Data Table -->    
  45.     <script src="https://cdn.datatables.net/1.10.10/js/jquery.dataTables.min.js" type="text/javascript"></script>    
  46.     <script src="https://cdn.datatables.net/1.10.10/js/dataTables.bootstrap.min.js" type="text/javascript"></script>    
  47.     @Scripts.Render("~/bundles/custom-datatable")    
  48.     
  49.     @RenderSection("scripts", required: false)    
  50. </body>    
  51. </html>  

In the above code, I have simply created a basic layout for the web page and included references to the required libraries and JQuery Datatables plugin.

Step 3

Now, create "Models\SalesOrderDetail.cs" file by and replace below code in this file

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5.   
  6. namespace MVC5DatatablesWithButton.Models  
  7. {  
  8.     public class SalesOrderDetail  
  9.     {  
  10.         public int Sr { getset; }  
  11.         public string OrderTrackNumber { getset; }  
  12.         public int Quantity { getset; }  
  13.         public string ProductName { getset; }  
  14.         public string SpecialOffer { getset; }  
  15.         public double UnitPrice { getset; }  
  16.         public double UnitPriceDiscount { getset; }  
  17.         public string Action { getset; }  
  18.     }  

In the above code, we have simply created our model to map data from text file to main memory with the addition a new property i.e. Action of type string. This property will be used to place the content of our action on Datatables UI grid for each row.

Step 4

Now, create "Controllers\HomeController.cs" file and replace following code in it i.e.

  1. using MVC5DatatablesWithButton.Models;  
  2. using System;  
  3. using System.Collections.Generic;  
  4. using System.IO;  
  5. using System.Linq;  
  6. using System.Reflection;  
  7. using System.Web;  
  8. using System.Web.Mvc;  
  9.   
  10. namespace MVC5DatatablesWithButton.Controllers  
  11. {  
  12.     public class HomeController : Controller  
  13.     {  
  14.         #region Index method  
  15.   
  16.         /// <summary>  
  17.         /// GET: Plugin method.  
  18.         /// </summary>  
  19.         /// <returns>Returns - index view page</returns>   
  20.         public ActionResult Index(string Id)  
  21.         {  
  22.             // Verification  
  23.             if (string.IsNullOrEmpty(Id))  
  24.             {  
  25.                 // Info.  
  26.                 return this.View();  
  27.             }  
  28.   
  29.             // Initialization.  
  30.             this.ViewBag.alert = Id;  
  31.   
  32.             // Info.  
  33.             return this.View();  
  34.         }  
  35.  
  36.         #endregion  
  37.  
  38.         #region Get data method.  
  39.   
  40.         /// <summary>  
  41.         /// GET: /Plugin/GetData  
  42.         /// </summary>  
  43.         /// <returns>Return data</returns>  
  44.         public ActionResult GetData()  
  45.         {  
  46.             // Initialization.  
  47.             JsonResult result = new JsonResult();  
  48.   
  49.             try  
  50.             {  
  51.                 // Initialization.  
  52.                 string search = Request.Form.GetValues("search[value]")[0];  
  53.                 string draw = Request.Form.GetValues("draw")[0];  
  54.                 string order = Request.Form.GetValues("order[0][column]")[0];  
  55.                 string orderDir = Request.Form.GetValues("order[0][dir]")[0];  
  56.                 int startRec = Convert.ToInt32(Request.Form.GetValues("start")[0]);  
  57.                 int pageSize = Convert.ToInt32(Request.Form.GetValues("length")[0]);  
  58.   
  59.                 // Loading.  
  60.                 List<SalesOrderDetail> data = this.LoadData();  
  61.   
  62.                 // Total record count.  
  63.                 int totalRecords = data.Count;  
  64.   
  65.                 // Verification.  
  66.                 if (!string.IsNullOrEmpty(search) &&  
  67.                     !string.IsNullOrWhiteSpace(search))  
  68.                 {  
  69.                     // Apply search  
  70.                     data = data.Where(p => p.Sr.ToString().ToLower().Contains(search.ToLower()) ||  
  71.                                            p.OrderTrackNumber.ToLower().Contains(search.ToLower()) ||  
  72.                                            p.Quantity.ToString().ToLower().Contains(search.ToLower()) ||  
  73.                                            p.ProductName.ToLower().Contains(search.ToLower()) ||  
  74.                                            p.SpecialOffer.ToLower().Contains(search.ToLower()) ||  
  75.                                            p.UnitPrice.ToString().ToLower().Contains(search.ToLower()) ||  
  76.                                            p.UnitPriceDiscount.ToString().ToLower().Contains(search.ToLower())).ToList();  
  77.                 }  
  78.   
  79.                 // Sorting.  
  80.                 data = this.SortByColumnWithOrder(order, orderDir, data);  
  81.   
  82.                 // Filter record count.  
  83.                 int recFilter = data.Count;  
  84.   
  85.                 // Apply pagination.  
  86.                 data = data.Skip(startRec).Take(pageSize).ToList();  
  87.   
  88.                 // Loading drop down lists.  
  89.                 result = this.Json(new { draw = Convert.ToInt32(draw), recordsTotal = totalRecords, recordsFiltered = recFilter, data = data }, JsonRequestBehavior.AllowGet);  
  90.             }  
  91.             catch (Exception ex)  
  92.             {  
  93.                 // Info  
  94.                 Console.Write(ex);  
  95.             }  
  96.   
  97.             // Return info.  
  98.             return result;  
  99.         }  
  100.  
  101.         #endregion  
  102.  
  103.         #region Helpers  
  104.  
  105.         #region Load Data  
  106.   
  107.         /// <summary>  
  108.         /// Load data method.  
  109.         /// </summary>  
  110.         /// <returns>Returns - Data</returns>  
  111.         private List<SalesOrderDetail> LoadData()  
  112.         {  
  113.             // Initialization.  
  114.             List<SalesOrderDetail> lst = new List<SalesOrderDetail>();  
  115.   
  116.             try  
  117.             {  
  118.                 // Initialization.  
  119.                 string line = string.Empty;  
  120.                 string srcFilePath = "content/files/SalesOrderDetail.txt";  
  121.                 var rootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);  
  122.                 var fullPath = Path.Combine(rootPath, srcFilePath);  
  123.                 string filePath = new Uri(fullPath).LocalPath;  
  124.                 StreamReader sr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read));  
  125.   
  126.                 // Read file.  
  127.                 while ((line = sr.ReadLine()) != null)  
  128.                 {  
  129.                     // Initialization.  
  130.                     SalesOrderDetail infoObj = new SalesOrderDetail();  
  131.                     string[] info = line.Split(',');  
  132.   
  133.                     // Setting.  
  134.                     infoObj.Sr = Convert.ToInt32(info[0].ToString());  
  135.                     infoObj.OrderTrackNumber = info[1].ToString();  
  136.                     infoObj.Quantity = Convert.ToInt32(info[2].ToString());  
  137.                     infoObj.ProductName = info[3].ToString();  
  138.                     infoObj.SpecialOffer = info[4].ToString();  
  139.                     infoObj.UnitPrice = Convert.ToDouble(info[5].ToString());  
  140.                     infoObj.UnitPriceDiscount = Convert.ToDouble(info[6].ToString());  
  141.   
  142.                     infoObj.Action = "<a class='btn btn-warning' href='" + this.Url.Action("Index""Home"new { Id = infoObj.Sr }) + "'>Click Me</a>";  
  143.   
  144.                     // Adding.  
  145.                     lst.Add(infoObj);  
  146.                 }  
  147.   
  148.                 // Closing.  
  149.                 sr.Dispose();  
  150.                 sr.Close();  
  151.             }  
  152.             catch (Exception ex)  
  153.             {  
  154.                 // info.  
  155.                 Console.Write(ex);  
  156.             }  
  157.   
  158.             // info.  
  159.             return lst;  
  160.         }  
  161.  
  162.         #endregion  
  163.  
  164.         #region Sort by column with order method  
  165.   
  166.         /// <summary>  
  167.         /// Sort by column with order method.  
  168.         /// </summary>  
  169.         /// <param name="order">Order parameter</param>  
  170.         /// <param name="orderDir">Order direction parameter</param>  
  171.         /// <param name="data">Data parameter</param>  
  172.         /// <returns>Returns - Data</returns>  
  173.         private List<SalesOrderDetail> SortByColumnWithOrder(string order, string orderDir, List<SalesOrderDetail> data)  
  174.         {  
  175.             // Initialization.  
  176.             List<SalesOrderDetail> lst = new List<SalesOrderDetail>();  
  177.   
  178.             try  
  179.             {  
  180.                 // Sorting  
  181.                 switch (order)  
  182.                 {  
  183.                     case "0":  
  184.                         // Setting.  
  185.                         lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.Sr).ToList()  
  186.                                                                                                  : data.OrderBy(p => p.Sr).ToList();  
  187.                         break;  
  188.   
  189.                     case "1":  
  190.                         // Setting.  
  191.                         lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.OrderTrackNumber).ToList()  
  192.                                                                                                  : data.OrderBy(p => p.OrderTrackNumber).ToList();  
  193.                         break;  
  194.   
  195.                     case "2":  
  196.                         // Setting.  
  197.                         lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.Quantity).ToList()  
  198.                                                                                                  : data.OrderBy(p => p.Quantity).ToList();  
  199.                         break;  
  200.   
  201.                     case "3":  
  202.                         // Setting.  
  203.                         lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.ProductName).ToList()  
  204.                                                                                                  : data.OrderBy(p => p.ProductName).ToList();  
  205.                         break;  
  206.   
  207.                     case "4":  
  208.                         // Setting.  
  209.                         lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.SpecialOffer).ToList()  
  210.                                                                                                    : data.OrderBy(p => p.SpecialOffer).ToList();  
  211.                         break;  
  212.   
  213.                     case "5":  
  214.                         // Setting.  
  215.                         lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.UnitPrice).ToList()  
  216.                                                                                                  : data.OrderBy(p => p.UnitPrice).ToList();  
  217.                         break;  
  218.   
  219.                     case "6":  
  220.                         // Setting.  
  221.                         lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.UnitPriceDiscount).ToList()  
  222.                                                                                                  : data.OrderBy(p => p.UnitPriceDiscount).ToList();  
  223.                         break;  
  224.   
  225.                     default:  
  226.   
  227.                         // Setting.  
  228.                         lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.Sr).ToList()  
  229.                                                                                                  : data.OrderBy(p => p.Sr).ToList();  
  230.                         break;  
  231.                 }  
  232.             }  
  233.             catch (Exception ex)  
  234.             {  
  235.                 // info.  
  236.                 Console.Write(ex);  
  237.             }  
  238.   
  239.             // info.  
  240.             return lst;  
  241.         }  
  242.  
  243.         #endregion  
  244.  
  245.         #endregion  
  246.     }  

The above piece of code consists of Index(...), LoadData(), GetData() & SortByColumnWithOrder(...) methods in which Index(...) method will return the details for our view page, LoadData() method will simply load data from text file into list and also I have created HTML link as string and mapped that value to our new action property for the user to perform an action on each row. Then, we have created SortByColumnWithOrder(...) method which will perform sorting and ordering of our table grid on the web page and handle it on server side. Finally, I have created an ajax call web method that will process and map information from server side to the datatables jquery plugin.

The important change is in LoadData(...) method i.e. in LoadData(...) method we have created an HTML link as string and mapped that value to our data grid actionable property i.e.

  1. infoObj.Action = "<a class='btn btn-warning' href='" + this.Url.Action("Index""Home"new { Id = infoObj.Sr }) + "'>Click Me</a>"

And in Index(...) action method, we are simply returning clickable row ID as Viewbag property to see button clicks in action i.e.

  1. // Initialization.  
  2. this.ViewBag.alert = Id; 

Step 5

Create "Views\Home\_ViewListPartial.cshtml" & "Views\Home\Index.cshtml" files and replace following code in it i.e.

Views\Home\_ViewListPartial.cshtml
  1. Views\Home\_ViewListPartial.cshtml   
  2. <section>  
  3.     <div class="well bs-component">  
  4.         <br />  
  5.   
  6.         <div class="row">  
  7.             <div>  
  8.                 <table class="table table-striped table-bordered table-hover"  
  9.                        id="TableId"  
  10.                        cellspacing="0"  
  11.                        align="center"  
  12.                        width="100%">  
  13.                     <thead>  
  14.                         <tr>  
  15.                             <th>Sr</th>  
  16.                             <th>Order Track Number</th>  
  17.                             <th>Quantity</th>  
  18.                             <th>Product Name</th>  
  19.                             <th>Special Offer</th>  
  20.                             <th>Unit Price</th>  
  21.                             <th>Unit Price Discount</th>  
  22.   
  23.                             <th></th>  
  24.                         </tr>  
  25.                     </thead>  
  26.                 </table>  
  27.             </div>  
  28.         </div>  
  29.     </div>  
  30. </section> 

View\Home\Index.cshtml

  1. @{  
  2.     ViewBag.Title = "ASP.NET MVC5 - Jquery Datatables with Button";  
  3. }  
  4.   
  5. <div class="row">  
  6.     @Html.Hidden("Idval", (string)ViewBag.alert)  
  7. </div>  
  8.   
  9. <div class="row">  
  10.     <div class="panel-heading">  
  11.         <div class="col-md-8  custom-heading3">  
  12.             <h3>  
  13.                 <i class="fa fa-table"></i>  
  14.                 <span>ASP.NET MVC5 - Jquery Datatables with Button</span>  
  15.             </h3>  
  16.         </div>  
  17.     </div>  
  18. </div>  
  19.   
  20. <div class="row">  
  21.     <section class="col-md-12 col-md-push-0">  
  22.         @Html.Partial("_ViewListPartial")  
  23.     </section>  
  24. </div>  
  25.   
  26. <script type="text/javascript">  
  27.     var idVal = document.getElementById("Idval").value;  
  28.   
  29.     if (idVal != null && idVal != "")  
  30.     {  
  31.         alert(idVal);  
  32.     }      
  33. </script> 

In the above code, I have simply created the view code for the page which will display the grid view by using JQuery DataTables plugin. I have divided the page into two parts for better manageability.

Here, the important change in the "Views\Home\_ViewListPartial.cshtml" file is the new header column which will contain our action button within the datatables jquery plugin i.e.

  1. <th></th> 

Step 6

Now, create "Scripts\custom-datatable.js"file and replace the following code in it:

  1. $(document).ready(function () {  
  2.     $('#TableId').DataTable(  
  3.     {  
  4.         "columnDefs": [  
  5.             { "width""5%""targets": [0] },  
  6.             { "width""10%""searchable"false"orderable"false,  "targets": [7] },  
  7.             { "className""text-center custom-middle-align""targets": [0, 1, 2, 3, 4, 5, 6, 7] },  
  8.         ],  
  9.         "language":  
  10.             {  
  11.                 "processing""<div class='overlay custom-loader-background'><i class='fa fa-cog fa-spin custom-loader-color'></i></div>"  
  12.             },  
  13.         "processing"true,  
  14.         "serverSide"true,  
  15.         "ajax":  
  16.             {  
  17.                 "url""/Home/GetData",  
  18.                 "type""POST",  
  19.                 "dataType""JSON"  
  20.             },  
  21.         "columns": [  
  22.                     { "data""Sr" },  
  23.                     { "data""OrderTrackNumber" },  
  24.                     { "data""Quantity" },  
  25.                     { "data""ProductName" },  
  26.                     { "data""SpecialOffer" },  
  27.                     { "data""UnitPrice" },  
  28.                     { "data""UnitPriceDiscount" },  
  29.                     { "data""Action" }  
  30.         ]  
  31.     });  
  32. }); 

In the above code, we have simply configured basic settings for our jquery datatables plugin and also added the button action as a column and made it non searchable and non-sortable by the jquery datatables plugin.

Step 7

Let's execute the project now and you will be able to see the following:


 

When you click any button in jquery datatables plugin, you will see the below result:



Conclusion

In this article, you learned about adding any sort of button, link or action within jquery datatables which corresponds to a particular row in order to perform operations like CRUD (Create, Read, Update, Delete). You also learned to use Viewbag property in HTML code and on the server side as well.