ASP.NET MVC 5: Datatables Plugin Server Side Integration

In this article, I shall be focusing on how the Datatables plugin can be integrated with ASP.NET MVC 5 server side data. I have also attached the code.

Ever since Microsoft introduced the MVC paradigm for web development many classic ASP.NET webform users miss built-in web UI controls to boost-up their development. One such control that has been missed a lot is DataGridView. In MVC paradigm, there is no concept of web UI controls, rather than simple plain HTML. So, yeah, it sometimes get annoying for classic ASP.NET webform users to switch to MVC paradigm with ease, especially, when UI designing is concerned.

table

HTML tables are quite common, especially when lists are to be shown on the web pages. There are many beautiful free for commercial use or open source based plugins out there that solve a lot of designing issues in web development to boost up not just development productivity, but also provide lucid user interactivity for websites. One such really cool free for commercial use plugin for lists is Datatables. There are alot of flavors of Datatables plugins and it comes to support many major web programming technologies.

The following are some prerequisites before you proceed any further in this article:

Prerequisites:

The prerequisites include knowledge about the following technologies: 
  1. ASP.NET MVC 5
  2. HTML
  3. JavaScript.
  4. AJAX
  5. CSS
  6. Bootstrap.
  7. C# Programming
  8. C# LINQ
  9. jQuery

You can download the complete source code for this tutorial and cal also  follow the step by step discussion below. The sample code is developed in Microsoft Visual Studio 2013 Ultimate. I am using SalesOrderDetail table extract from Adventure Works Sample Database.

Let’s begin now

  1. Create new MVC 5 web application project and name it "PluginIntegration-1".

  2. Create new controller and name it "Plugin".

  3. In "RouteConfig.cs" file change your default controller to "Plugin".

  4. Create a new page called "Index.cshtml" under "Views, Plugin" folder and place the following code in it:
    1. @{   
    2. ViewBag.Title = "Plugin Integration - Datatable";   
    3. }   
    4. <div class="row">  
    5. <div class="panel-heading">  
    6. <div class="col-md-8">  
    7. <h3>  
    8. <i class="fa fa-table"></i>  
    9. <span>Datatables Plugin Integration with ASP.NET MVC5 C#</span>  
    10. </h3>  
    11. </div>  
    12. </div>  
    13. </div>  
    14. <div class="row">  
    15. <section class="col-md-12 col-md-push-0">  
    16. @Html.Partial("_ViewListPartial")   
    17. </section>  
    18. </div>  
    Here, I am simply creating a page heading and section for my partial view in which I will be displaying my DataTables plugin base server side data.

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

  6. Now, create a new partial page under "Views->Plugin" folder, name it "_ViewListPartial.cshtml" and place the following code in it:
    1. <section>  
    2.     <div class="well bs-component">  
    3.         <br />  
    4.         <div class="row">  
    5.             <div>  
    6.                 <table class="table table-striped table-bordered table-hover" id="TableId" cellspacing="0" align="center" width="100%">  
    7.                     <thead>  
    8.                         <tr>  
    9.                             <th>Sr</th>  
    10.                             <th>Order Track Number</th>  
    11.                             <th>Quantity</th>  
    12.                             <th>Product Name</th>  
    13.                             <th>Special Offer</th>  
    14.                             <th>Unit Price</th>  
    15.                             <th>Unit Price Discount</th>  
    16.                         </tr>  
    17.                     </thead>  
    18.                 </table>  
    19.             </div>  
    20.         </div>  
    21.     </div>  
    22. </section>  
    Here, I have created a table holder that will be integrated with Datatables plugin with data from server side. I have only provided table header information here, since, the data will be integrated from server side.

  7. Now create new model under "Model", name it "SalesOrderDetail.cs" and add the following properties in it:
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Text;  
    5. using System.Threading.Tasks;  
    6. namespace PluginIntegration_1.Models  
    7. {  
    8.     public class SalesOrderDetail  
    9.     {  
    10.         public int Sr  
    11.         {  
    12.             get;  
    13.             set;  
    14.         }  
    15.         public string OrderTrackNumber  
    16.         {  
    17.             get;  
    18.             set;  
    19.         }  
    20.         public int Quantity  
    21.         {  
    22.             get;  
    23.             set;  
    24.         }  
    25.         public string ProductName  
    26.         {  
    27.             get;  
    28.             set;  
    29.         }  
    30.         public string SpecialOffer  
    31.         {  
    32.             get;  
    33.             set;  
    34.         }  
    35.         public double UnitPrice   
    36.         {  
    37.             get;  
    38.             set;  
    39.         }  
    40.         public double UnitPriceDiscount   
    41.         {  
    42.             get;  
    43.             set;  
    44.         }  
    45.     }  
    46. }  
  8. Now, in "PluginController.cs" file add the following function to load data from "SalesOrderDetail.txt" text file:
    1. #region Load Data  
    2. /// <summary>  
    3. /// Load data method.   
    4. /// </summary>  
    5. /// <returns>Returns - Data</returns>  
    6. private List < SalesOrderDetail > LoadData()  
    7. {  
    8.     // Initialization.   
    9.     List < SalesOrderDetail > lst = new List < SalesOrderDetail > ();  
    10.     try {  
    11.         // Initialization.   
    12.         string line = string.Empty;  
    13.         string srcFilePath = "content/files/SalesOrderDetail.txt";  
    14.         var rootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);  
    15.         var fullPath = Path.Combine(rootPath, srcFilePath);  
    16.         string filePath = new Uri(fullPath).LocalPath;  
    17.         StreamReader sr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read));  
    18.         // Read file.   
    19.         while ((line = sr.ReadLine()) != null)   
    20.         {  
    21.             // Initialization.   
    22.             SalesOrderDetail infoObj = new SalesOrderDetail();  
    23.             string[] info = line.Split(',');  
    24.             // Setting.   
    25.             infoObj.Sr = Convert.ToInt32(info[0].ToString());  
    26.             infoObj.OrderTrackNumber = info[1].ToString();  
    27.             infoObj.Quantity = Convert.ToInt32(info[2].ToString());  
    28.             infoObj.ProductName = info[3].ToString();  
    29.             infoObj.SpecialOffer = info[4].ToString();  
    30.             infoObj.UnitPrice = Convert.ToDouble(info[5].ToString());  
    31.             infoObj.UnitPriceDiscount = Convert.ToDouble(info[6].ToString());  
    32.             // Adding.   
    33.             lst.Add(infoObj);  
    34.         }  
    35.         // Closing.   
    36.         sr.Dispose();  
    37.         sr.Close();  
    38.     } catch (Exception ex)  
    39.     {  
    40.         // info.   
    41.         Console.Write(ex);  
    42.     }  
    43.     // info.   
    44.     return lst;  
    45. }  
    The above piece of code simply loads data from text file into list.

  9. Now, create new script file under "Scripts" folder, name it "custom-datatable.js" and place the following code in it:
    1. $(document).ready(function()  
    2. {  
    3.     $('#TableId').DataTable  
    4.     ({  
    5.         "columnDefs": [  
    6.           {  
    7.             "width""5%",  
    8.             "targets": [0]  
    9.         },  
    10.           {  
    11.             "className""text-center custom-middle-align",  
    12.             "targets": [0, 1, 2, 3, 4, 5, 6]  
    13.         }, ],  
    14.         "language":  
    15.         {  
    16.             "processing""<div class='overlay custom-loader-background'><i class='fa fa-cog fa-spin custom-loader-color'></i></div>"  
    17.         },  
    18.         "processing"true,  
    19.         "serverSide"true,  
    20.         "ajax":  
    21.       {  
    22.             "url""/Plugin/GetData",  
    23.             "type""POST",  
    24.             "dataType""JSON"  
    25.         },  
    26.         "columns": [  
    27.           {  
    28.             "data""Sr"  
    29.         },  
    30.           {  
    31.             "data""OrderTrackNumber"  
    32.         },  
    33.           {  
    34.             "data""Quantity"  
    35.         },  
    36.           {  
    37.             "data""ProductName"  
    38.         },  
    39.           {  
    40.             "data""SpecialOffer"  
    41.         },  
    42.           {  
    43.             "data""UnitPrice"  
    44.         },  
    45.           {  
    46.             "data""UnitPriceDiscount"  
    47.         }]  
    48.     });  
    49. });  
    Now, this is the fun part which will display the server side data in the table that we have created earlier into our partial view "_ViewListPartial.cshtml." This is how Datatables plugin integrates server side data with underlying web programming language. Let’s see each piece of information here chunk by chunk:
    1. "columnDefs": [   
    2. "width""5%""targets": [0] },   
    3. "className""text-center custom-middle-align""targets": [0, 1, 2, 3, 4, 5, 6] },   
    4. ],   
    This chunk of code provides styling, enables/disables information for sorting, searching etc, for the number of columns which are being used in the table, which is why this chunk of code defines columns definition for our table.
    1. "language":   
    2. {   
    3. "processing""<div class='overlay custom-loader-background'><i class='fa fa-cog fa-spin custom-loader-color'></i></div>"   
    4. },   
    This chunk of code allows us to customize the processing message that will appear when data is being loaded. I have used the following custom styling here:
    1. .custom - loader - color  
    2. {  
    3.         color: #fff!important;  
    4.         font - size: 50 px!important;  
    5.     }  
    6.     .custom - loader - background  
    7.     {  
    8.         background - color: crimson!important;  
    9.     }  
    10.     .custom - middle - align   
    11.     {  
    12.         vertical - align: middle!important;  
    13.     }  

    integration
    Below is the snippet of what the processing loader will look like:

    Below piece of code will enable the data loading from server side:
    1. "processing"true,  
    2. "serverSide"true,  
    3. "ajax":  
    4. {  
    5.     "url""/Plugin/GetData",  
    6.     "type""POST",  
    7.     "dataType""JSON"  
    8. },  
    9. "columns":   
    10. [{  
    11.     "data""Sr"  
    12. }, {  
    13.     "data""OrderTrackNumber"  
    14. }, {  
    15.     "data""Quantity"  
    16. }, {  
    17.     "data""ProductName"  
    18. }, {  
    19.     "data""SpecialOffer"  
    20. }, {  
    21.     "data""UnitPrice"  
    22. }, {  
    23.     "data""UnitPriceDiscount"  
    24. }]  
    The columns here are the exact name of the properties that we have created in "SalesOrderDetail.cs" file and the path "/Plugin/GetData" is the function that will be returning data from server side.

  10. Now, in "PluginController.cs" file let’s create "GetData" method as follows:

    #region Get data method

    1. /// <summary>  
    2. /// GET: /Plugin/GetData   
    3. /// </summary>  
    4. /// <returns>Return data</returns>  
    5. public ActionResult GetData()   
    6. {  
    7.     // Initialization.   
    8.     JsonResult result = new JsonResult();  
    9.     try {  
    10.         // Initialization.   
    11.         string search = Request.Form.GetValues("search[value]")[0];  
    12.         string draw = Request.Form.GetValues("draw")[0];  
    13.         string order = Request.Form.GetValues("order[0][column]")[0];  
    14.         string orderDir = Request.Form.GetValues("order[0][dir]")[0];  
    15.         int startRec = Convert.ToInt32(Request.Form.GetValues("start")[0]);  
    16.         int pageSize = Convert.ToInt32(Request.Form.GetValues("length")[0]);  
    17.         // Loading.   
    18.         List < SalesOrderDetail > data = this.LoadData();  
    19.         // Total record count.   
    20.         int totalRecords = data.Count;  
    21.         // Verification.   
    22.         if (!string.IsNullOrEmpty(search) &&  
    23.             !string.IsNullOrWhiteSpace(search))  
    24.         {  
    25.             // Apply search   
    26.             data = data.Where(p => p.Sr.ToString().ToLower().Contains(search.ToLower()) ||  
    27.                 p.OrderTrackNumber.ToLower().Contains(search.ToLower()) ||  
    28.                 p.Quantity.ToString().ToLower().Contains(search.ToLower()) ||  
    29.                 p.ProductName.ToLower().Contains(search.ToLower()) ||  
    30.                 p.SpecialOffer.ToLower().Contains(search.ToLower()) ||  
    31.                 p.UnitPrice.ToString().ToLower().Contains(search.ToLower()) ||  
    32.                 p.UnitPriceDiscount.ToString().ToLower().Contains(search.ToLower())).ToList();  
    33.         }  
    34.         // Sorting.   
    35.         data = this.SortByColumnWithOrder(order, orderDir, data);  
    36.         // Filter record count.   
    37.         int recFilter = data.Count;  
    38.         // Apply pagination.   
    39.         data = data.Skip(startRec).Take(pageSize).ToList();  
    40.         // Loading drop down lists.   
    41.         result = this.Json(new {  
    42.             draw = Convert.ToInt32(draw), recordsTotal = totalRecords, recordsFiltered = recFilter, data = data  
    43.         }, JsonRequestBehavior.AllowGet);  
    44.     } catch (Exception ex) {  
    45.         // Info   
    46.         Console.Write(ex);  
    47.     }  
    48.     // Return info.   
    49.     return result;  
    50. }#  
    51. endregion  

In this piece of code, which is based on searching, sorting and pagination information sent from Datatables plugin, the  following has been done i.e.

  1. Data is being loaded first.

  2. Data is being churned out based on searching criteria.

  3. Data is sorted by provided column in provided order.

  4. Data is then paginated.

  5. Data is returned.

    "GetData" function will be executed each time the table is being searched, sort or new page is accessed. Here are the following two lines which are important:
    1. // Total record count.   
    2. int totalRecords = data.Count;   
    3.   
    4. // Filter record count.   
    5. int recFilter = data.Count;   
    First line determines the actual amount of records that exist in the list and second line determines the amount of records that are left after applying filtering. Below is the piece of code that will do the sorting:

    #region Sort by column with order method
    1. /// <summary>  
    2. /// Sort by column with order method.   
    3. /// </summary>  
    4. /// <param name="order">Order parameter</param>  
    5. /// <param name="orderDir">Order direction parameter</param>  
    6. /// <param name="data">Data parameter</param>  
    7. /// <returns>Returns - Data</returns>  
    8. private List < SalesOrderDetail > SortByColumnWithOrder(string order, string orderDir, List < SalesOrderDetail > data)  
    9. {  
    10.     // Initialization.   
    11.     List < SalesOrderDetail > lst = new List < SalesOrderDetail > ();  
    12.     try {  
    13.         // Sorting   
    14.         switch (order)  
    15.         {  
    16.             case "0":  
    17.                 // Setting.   
    18.                 lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.Sr).ToList() : data.OrderBy(p => p.Sr).ToList();  
    19.                 break;  
    20.             case "1":  
    21.                 // Setting.   
    22.                 lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.OrderTrackNumber).ToList() : data.OrderBy(p => p.OrderTrackNumber).ToList();  
    23.                 break;  
    24.             case "2":  
    25.                 // Setting.   
    26.                 lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.Quantity).ToList() : data.OrderBy(p => p.Quantity).ToList();  
    27.                 break;  
    28.             case "3":  
    29.                 // Setting.   
    30.                 lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.ProductName).ToList() : data.OrderBy(p => p.ProductName).ToList();  
    31.                 break;  
    32.             case "4":  
    33.                 // Setting.   
    34.                 lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.SpecialOffer).ToList() : data.OrderBy(p => p.SpecialOffer).ToList();  
    35.                 break;  
    36.             case "5":  
    37.                 // Setting.   
    38.                 lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.UnitPrice).ToList() : data.OrderBy(p => p.UnitPrice).ToList();  
    39.                 break;  
    40.             case "6":  
    41.                 // Setting.   
    42.                 lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.UnitPriceDiscount).ToList() : data.OrderBy(p => p.UnitPriceDiscount).ToList();  
    43.                 break;  
    44.             default:  
    45.                 // Setting.   
    46.                 lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.Sr).ToList() : data.OrderBy(p => p.Sr).ToList();  
    47.                 break;  
    48.         }  
    49.     } catch (Exception ex)   
    50.     {  
    51.         // info.   
    52.         Console.Write(ex);  
    53.     }  
    54.     // info.   
    55.     return lst;  
    56. }#endregion  

    tables

    Here is how the results will look  after applying the filtering.

Conclusion

This article was about Datatable plugins server side integration with ASP.NET MVC 5. In this article you learned how to integrate server side data, searching, sorting, and pagination information with Datatable plugin.

Read more articles on ASP.NET: