Datatables .NET (How It Works For Developer)

ASP.NET developers often seek efficient ways to present tabular data or HTML tables with advanced features such as sorting, searching, and pagination. DataTables.NET is a powerful jQuery, JavaScript library, and highly flexible tool that facilitates the creation of interactive and feature-rich tables in web applications. In this article, we'll explore how to integrate DataTables.NET distribution files, a table-enhancing library for server-side processing into an ASP.NET project to enhance the presentation and user experience of tabular data.

How to use DataTables in ASP.NET Web Application?

  1. Create ASP.NET Web Application
  2. Add DataTables Client Side styling package
  3. Install Entity Framework Core Packages, only the core software
  4. Add Model Class, Controller, and Razor Page
  5. Add JavaScript code in the JS File
  6. Set up Configuration
  7. Build and Run the Program
  8. Export Data into an Excel file using IronXL

What is Datatables.NET?

Datatables.NET is a jQuery JavaScript library that allows you to create CDN and manipulate interactive tables in .NET applications. It is based on the jQuery DataTables plug-in, which provides comprehensive API features like pagination, sorting, filtering, and scrolling for dynamic as well as static HTML tables. It is a table-enhancing library that can work with various data sources, such as SQL databases, AJAX, or in-memory objects.

Server Side Processing

Consider a scenario where you have an API endpoint delivering a vast dataset of products. The standard approach involves jQuery DataTables making an AJAX call to this API, obtaining a list of products in JSON format, and rendering an HTML table. This is known as client-side processing, which is efficient for smaller datasets, typically ranging from 100 to 1000 records. However, what happens when the dataset expands to 10,000 records or more?

When dealing with a substantial number of records, it becomes impractical to send the entire dataset to the browser in one go. Transmitting 10,000 records at once is not only wasteful in terms of bandwidth but also strains browser resources. In such cases, an alternative approach, server-side processing, becomes crucial for optimizing performance.

In server-side processing, rather than sending the entire dataset, the API transmits data in manageable chunks, typically paginated with around 50 records per page. By doing this, the load time is significantly improved, as jQuery DataTables now loads a modest number of records (~50) instead of dealing with the entire dataset at once. This approach reduces CPU and bandwidth usage, creating a more efficient interaction between the API and the DataTable.

In this article, we will explore the implementation of server-side processing in an ASP.NET Razor Page application, demonstrating how to efficiently handle and display extensive datasets while enhancing the overall performance of your web application.

Getting Started with Datatables.NET in ASP.NET 8

To get started we need to add Datatables.NET Client Side Library in our project. This article will use the ASP.NET Core Web App (Razor Pages) project with .NET 8. You may use any Web App Project as per your requirements.

To add a Client-Side Library, right-click on Solution>Add> Client Side Library, and Search for data tables as shown below.

Datatables .NET (How It Works For Developer): Figure 1 - Add Client-Side Library

Now, we need to add Model Class, DB Context, Controller, HTML table, and AJAX Call.

But before that, we need to install EntityFramework Nuget Packages to connect our application with the Database. This article will use the Code First Approach, you may use Database first as per your preference.

Install the following locally hosted packages:

  1. Microsoft.EntityFrameworkCore
  2. Microsoft.EntityFrameworkCore.Design
  3. Microsoft.EntityFrameworkCore.SqlServer
  4. Microsoft.EntityFrameworkCore.Tools

Install the above package by using the install-package command from the NuGet Package Manager Console, or install it from the NuGet Package Manager solution by searching it.

Add Model Class

I am using Product Model Class for this example, you may use it as per your requirement.

public class Product
{
    public int Id { get; set; }
    public string ProductName { get; set; } = string.Empty;
    public string ProductPrice { get; set; } = string.Empty;
    public string ProductWeight { get; set; } = string.Empty;
    public string ProductDescription { get; set; } = string.Empty;
    public DateTime ProductManufacturingDate { get; set; }
    public DateTime ProductExpiryDate { get; set; }
}
public class Product
{
    public int Id { get; set; }
    public string ProductName { get; set; } = string.Empty;
    public string ProductPrice { get; set; } = string.Empty;
    public string ProductWeight { get; set; } = string.Empty;
    public string ProductDescription { get; set; } = string.Empty;
    public DateTime ProductManufacturingDate { get; set; }
    public DateTime ProductExpiryDate { get; set; }
}
Public Class Product
	Public Property Id() As Integer
	Public Property ProductName() As String = String.Empty
	Public Property ProductPrice() As String = String.Empty
	Public Property ProductWeight() As String = String.Empty
	Public Property ProductDescription() As String = String.Empty
	Public Property ProductManufacturingDate() As DateTime
	Public Property ProductExpiryDate() As DateTime
End Class
VB   C#

Add ApplicationDBContext Class

public class ApplicationDBContext : DbContext
{
    public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options) : base(options)
    {
    }
    public DbSet<Product> Products { get; set; }
}
public class ApplicationDBContext : DbContext
{
    public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options) : base(options)
    {
    }
    public DbSet<Product> Products { get; set; }
}
Public Class ApplicationDBContext
	Inherits DbContext

	Public Sub New(ByVal options As DbContextOptions(Of ApplicationDBContext))
		MyBase.New(options)
	End Sub
	Public Property Products() As DbSet(Of Product)
End Class
VB   C#

Add Advanced Interaction Controls

We will add the ProductDatatables.js inside the wwwroot>js folder for adding advanced controls such as pagination, search, etc.

//add advanced interaction controls
$(document).ready(function () {
    $("#productDatatable").DataTable({
        "processing": true,
        "serverSide": true,
        "filter": true,
        "ajax": {
            "url": "/api/Product",
            "type": "POST",
            "datatype": "json"
        },
        "columnDefs": [{
            "targets": [0].data,
            "visible": false,
            "searchable": false
        }],
        "columns": [
            { "data": "id", "name": "Id", "autoWidth": true },
            { "data": "productName", "name": "ProductName", "autoWidth": true },
            { "data": "productPrice", "name": "ProductPrice", "autoWidth": true },
            { "data": "productWeight", "name": "ProductWeight", "autoWidth": true },
            { "data": "productDescription", "name": "ProductDescription", "autoWidth": true },
            { "data": "productManufacturingDate", "name": "ProductManufacturingDate", "autoWidth": true },
            { "data": "productExpiryDate", "name": "ProductExpiryDate", "autoWidth": true },
            {
                "render": function (data, row) { return "<a href='#' class='btn btn-danger' onclick=DeleteProduct('" + row.id + "'); >Delete</a>"; }
            },
        ]
    });
});
//add advanced interaction controls
$(document).ready(function () {
    $("#productDatatable").DataTable({
        "processing": true,
        "serverSide": true,
        "filter": true,
        "ajax": {
            "url": "/api/Product",
            "type": "POST",
            "datatype": "json"
        },
        "columnDefs": [{
            "targets": [0].data,
            "visible": false,
            "searchable": false
        }],
        "columns": [
            { "data": "id", "name": "Id", "autoWidth": true },
            { "data": "productName", "name": "ProductName", "autoWidth": true },
            { "data": "productPrice", "name": "ProductPrice", "autoWidth": true },
            { "data": "productWeight", "name": "ProductWeight", "autoWidth": true },
            { "data": "productDescription", "name": "ProductDescription", "autoWidth": true },
            { "data": "productManufacturingDate", "name": "ProductManufacturingDate", "autoWidth": true },
            { "data": "productExpiryDate", "name": "ProductExpiryDate", "autoWidth": true },
            {
                "render": function (data, row) { return "<a href='#' class='btn btn-danger' onclick=DeleteProduct('" + row.id + "'); >Delete</a>"; }
            },
        ]
    });
});
'add advanced interaction controls
$(document).ready([function] () {
	$("#productDatatable").DataTable({
		"processing":= True, "serverSide":= True, "filter":= True, "ajax":= {
			"url":= "/api/Product",
			"type":= "POST",
			"datatype":= "json"
		},
		"columnDefs":= ({
			"targets":= (0).data,
			"visible":= False,
			"searchable":= False
		}), "columns":= ({
			"data":= "id",
			"name":= "Id",
			"autoWidth":= True
		},
		{
			"data":= "productName",
			"name":= "ProductName",
			"autoWidth":= True
		},
		{
			"data":= "productPrice",
			"name":= "ProductPrice",
			"autoWidth":= True
		},
		{
			"data":= "productWeight",
			"name":= "ProductWeight",
			"autoWidth":= True
		},
		{
			"data":= "productDescription",
			"name":= "ProductDescription",
			"autoWidth":= True
		},
		{
			"data":= "productManufacturingDate",
			"name":= "ProductManufacturingDate",
			"autoWidth":= True
		},
		{
			"data":= "productExpiryDate",
			"name":= "ProductExpiryDate",
			"autoWidth":= True
		},
		{
			"render":= [function] (data, row) { Return "<a href='#' class='btn btn-danger' onclick=DeleteProduct('" & row.id & "'); >Delete</a>"; }
		},
		)
}); })
VB   C#

Now, we need to add an HTML table.

Add HTML table

Write the following code in the index.cshtml file to add a static HTML page.

//static HTML page
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}
<link href="~/lib/datatables/css/dataTables.bootstrap4.min.css" rel="stylesheet" />
<div class="container">
    <br />
    <div style="width:90%; margin:0 auto;">
        <table id="productDatatable" class="table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0">
            <thead>
                <tr>
                    <th>Id</th>
                    <th>Product Name</th>
                    <th>Product Price</th>
                    <th>Product Weight</th>
                    <th>Product Description</th>
                    <th>Product Manufacturing Date</th>
                    <th>Product Expiry Date</th>
                    <th>Actions</th>
                </tr>
            </thead>
        </table>
    </div>
</div>
@section Scripts
{
    <script src="~/lib/datatables/js/jquery.dataTables.min.js"></script>
    <script src="~/lib/datatables/js/dataTables.bootstrap4.min.js"></script>
    <script src="~/js/ProductDatatable.js"></script>
}
//static HTML page
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}
<link href="~/lib/datatables/css/dataTables.bootstrap4.min.css" rel="stylesheet" />
<div class="container">
    <br />
    <div style="width:90%; margin:0 auto;">
        <table id="productDatatable" class="table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0">
            <thead>
                <tr>
                    <th>Id</th>
                    <th>Product Name</th>
                    <th>Product Price</th>
                    <th>Product Weight</th>
                    <th>Product Description</th>
                    <th>Product Manufacturing Date</th>
                    <th>Product Expiry Date</th>
                    <th>Actions</th>
                </tr>
            </thead>
        </table>
    </div>
</div>
@section Scripts
{
    <script src="~/lib/datatables/js/jquery.dataTables.min.js"></script>
    <script src="~/lib/datatables/js/dataTables.bootstrap4.min.js"></script>
    <script src="~/js/ProductDatatable.js"></script>
}
'static HTML page
page model ReadOnly Property () As IndexModel
	ViewData("Title") = "Home page"
End Property
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: <link href="~/lib/datatables/css/dataTables.bootstrap4.min.css" rel="stylesheet" /> <div class="container"> <br /> <div style="width:90%; margin:0 auto;"> <table id="productDatatable" class="table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0"> <thead> <tr> <th> Id</th> <th> Product Name</th> <th> Product Price</th> <th> Product Weight</th> <th> Product Description</th> <th> Product Manufacturing @Date</th> <th> Product Expiry @Date</th> <th> Actions</th> </tr> </thead> </table> </div> </div> @section Scripts
"100%" cellspacing="0"> (Of thead) (Of tr) (Of th) Id</th> (Of th) Product Name</th> (Of th) Product Price</th> (Of th) Product Weight</th> (Of th) Product Description</th> (Of th) Product Manufacturing [Date]</th> (Of th) Product Expiry [Date]</th> (Of th) Actions</th> </tr> </thead> </table> </div> </div> section Scripts
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: Friend <link href="~/lib/datatables/css/dataTables.bootstrap4.min.css" rel="stylesheet" /> <div Class="container"> <br /> <div style="width:90%; margin:0 auto;"> <table id="productDatatable" class="table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing
"table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: Private Friend <link href="~/lib/datatables/css/dataTables.bootstrap4.min.css" rel="stylesheet" /> <div Class="container"> <br /> <div style="width:90%; margin:0 auto;"> <table id="productDatatable" class="table table-striped table-bordered dt-responsive nowrap" width
"productDatatable" class="table table-striped table-bordered dt-responsive nowrap" width
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: Private Private Friend <link href="~/lib/datatables/css/dataTables.bootstrap4.min.css" rel="stylesheet" /> <div Class="container"> <br /> <div style="width:90%; margin:0 auto;"> <table id="productDatatable" class
"width:90%; margin:0 auto;"> <table id="productDatatable" class
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: Private Private Private Friend <link href="~/lib/datatables/css/dataTables.bootstrap4.min.css" rel="stylesheet" /> <div Class="container"> <br /> <div style="width:90%; margin:0 auto;"> <table id
'INSTANT VB WARNING: Instant VB cannot determine whether both operands of this division are integer types - if they are then you should use the VB integer division operator:
"container"> <br /> <div style="width:90%; margin:0 auto;"> <table id
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: Private Private Private Private Friend <link href="~/lib/datatables/css/dataTables.bootstrap4.min.css" rel="stylesheet" /> <div Class="container"> <br /> <div style
'INSTANT VB WARNING: Instant VB cannot determine whether both operands of this division are integer types - if they are then you should use the VB integer division operator:
"stylesheet" /> <div Class="container"> <br /> <div style
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: Private Private Private Private Private Friend <link href="~/lib/datatables/css/dataTables.bootstrap4.min.css" rel="stylesheet" /> <div Class
"~/lib/datatables/css/dataTables.bootstrap4.min.css" rel="stylesheet" /> <div Class
Private Private Private Private Private Private Private Friend <link href="~/lib/datatables/css/dataTables.bootstrap4.min.css" rel
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: <script src="~/lib/datatables/js/jquery.dataTables.min.js"></script> <script src="~/lib/datatables/js/dataTables.bootstrap4.min.js"></script> <script src="~/js/ProductDatatable.js"></script>
	"~/lib/datatables/js/dataTables.bootstrap4.min.js"></script> <script src="~/js/ProductDatatable.js"></script>
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: Private <script src="~/lib/datatables/js/jquery.dataTables.min.js"></script> <script src="~/lib/datatables/js/dataTables.bootstrap4.min.js"></script> <script src
	"~/lib/datatables/js/jquery.dataTables.min.js"></script> <script src="~/lib/datatables/js/dataTables.bootstrap4.min.js"></script> <script src
	Private Private Private <script src="~/lib/datatables/js/jquery.dataTables.min.js"></script> <script src
End Class
VB   C#

We need to add the controller.

Add Product Controller

Add Product Controller for creating endpoint and direct pull requests.

[Route("api/[controller]")]
[ApiController]
public class ProductController : ControllerBase
{
    private readonly ApplicationDBContext context;
    public ProductController(ApplicationDBContext context)
    {
        this.context = context;
    }
    [HttpPost]
    public IActionResult GetProducts()
    {
        try
        {
            var draw = Request.Form["draw"].FirstOrDefault();
            var start = Request.Form["start"].FirstOrDefault();
            var length = Request.Form["length"].FirstOrDefault();
            var searchValue = Request.Form["search[value]"].FirstOrDefault();
            int pageSize = length != null ? Convert.ToInt32(length) : 0;
            int skip = start != null ? Convert.ToInt32(start) : 0;
            int recordsTotal = 0;
            var productData = context.Products.ToList();
            if (!string.IsNullOrEmpty(searchValue))
            {
                productData = productData.Where(m => m.ProductName.Contains(searchValue)
                                            || m.ProductDescription.Contains(searchValue)
                                            || m.Id.ToString().Contains(searchValue)).ToList();
            }
            recordsTotal = productData.Count();
            var data = productData.Skip(skip).Take(pageSize).ToList();
            var jsonData = new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data };
            return Ok(jsonData);
        }
        catch (Exception ex)
        {
            throw;
        }
    }
}
[Route("api/[controller]")]
[ApiController]
public class ProductController : ControllerBase
{
    private readonly ApplicationDBContext context;
    public ProductController(ApplicationDBContext context)
    {
        this.context = context;
    }
    [HttpPost]
    public IActionResult GetProducts()
    {
        try
        {
            var draw = Request.Form["draw"].FirstOrDefault();
            var start = Request.Form["start"].FirstOrDefault();
            var length = Request.Form["length"].FirstOrDefault();
            var searchValue = Request.Form["search[value]"].FirstOrDefault();
            int pageSize = length != null ? Convert.ToInt32(length) : 0;
            int skip = start != null ? Convert.ToInt32(start) : 0;
            int recordsTotal = 0;
            var productData = context.Products.ToList();
            if (!string.IsNullOrEmpty(searchValue))
            {
                productData = productData.Where(m => m.ProductName.Contains(searchValue)
                                            || m.ProductDescription.Contains(searchValue)
                                            || m.Id.ToString().Contains(searchValue)).ToList();
            }
            recordsTotal = productData.Count();
            var data = productData.Skip(skip).Take(pageSize).ToList();
            var jsonData = new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data };
            return Ok(jsonData);
        }
        catch (Exception ex)
        {
            throw;
        }
    }
}
<Route("api/[controller]")>
<ApiController>
Public Class ProductController
	Inherits ControllerBase

	Private ReadOnly context As ApplicationDBContext
	Public Sub New(ByVal context As ApplicationDBContext)
		Me.context = context
	End Sub
	<HttpPost>
	Public Function GetProducts() As IActionResult
		Try
			Dim draw = Request.Form("draw").FirstOrDefault()
			Dim start = Request.Form("start").FirstOrDefault()
			Dim length = Request.Form("length").FirstOrDefault()
			Dim searchValue = Request.Form("search[value]").FirstOrDefault()
			Dim pageSize As Integer = If(length IsNot Nothing, Convert.ToInt32(length), 0)
			Dim skip As Integer = If(start IsNot Nothing, Convert.ToInt32(start), 0)
			Dim recordsTotal As Integer = 0
			Dim productData = context.Products.ToList()
			If Not String.IsNullOrEmpty(searchValue) Then
				productData = productData.Where(Function(m) m.ProductName.Contains(searchValue) OrElse m.ProductDescription.Contains(searchValue) OrElse m.Id.ToString().Contains(searchValue)).ToList()
			End If
			recordsTotal = productData.Count()
			Dim data = productData.Skip(skip).Take(pageSize).ToList()
			Dim jsonData = New With {
				Key .draw = draw,
				Key .recordsFiltered = recordsTotal,
				Key .recordsTotal = recordsTotal,
				Key .data = data
			}
			Return Ok(jsonData)
		Catch ex As Exception
			Throw
		End Try
	End Function
End Class
VB   C#

Here, we have implemented pagination & searching on the server side.

Now, we need to set up our database and add configuration to the Program.cs class. If you are using .NET 5 or lower version, you may need to do it in Startup.cs class.

First of all, add the following Connection String in the appsettings.json file.

"ConnectionStrings": {
   "ProductDB": "Server=localserver\\SQLEXPRESS;Database=ProductDB;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True;"
 },

Now add the following code to the Program.cs class.

public static void Main(string[] args)
 {
     var builder = WebApplication.CreateBuilder(args);
     builder.Services.AddDbContext<ApplicationDBContext>(options =>
     {
         options.UseSqlServer(builder.Configuration.GetConnectionString("ProductDB"));
     });
     builder.Services.AddControllers();
     // Add services to the container.
     builder.Services.AddRazorPages();
     var app = builder.Build();
     // Configure the HTTP request pipeline.
     if (!app.Environment.IsDevelopment())
     {
         app.UseExceptionHandler("/Error");
         // The default HSTS value is 30 days. You may want to change this for production scenarios, see .NET documentation https://aka.ms/aspnetcore-hsts.
         app.UseHsts();
     }
     app.UseHttpsRedirection();
     app.UseStaticFiles();
     app.UseRouting();
     app.UseAuthorization();
     app.MapControllers();
     app.MapRazorPages();
     app.Run();
 }
public static void Main(string[] args)
 {
     var builder = WebApplication.CreateBuilder(args);
     builder.Services.AddDbContext<ApplicationDBContext>(options =>
     {
         options.UseSqlServer(builder.Configuration.GetConnectionString("ProductDB"));
     });
     builder.Services.AddControllers();
     // Add services to the container.
     builder.Services.AddRazorPages();
     var app = builder.Build();
     // Configure the HTTP request pipeline.
     if (!app.Environment.IsDevelopment())
     {
         app.UseExceptionHandler("/Error");
         // The default HSTS value is 30 days. You may want to change this for production scenarios, see .NET documentation https://aka.ms/aspnetcore-hsts.
         app.UseHsts();
     }
     app.UseHttpsRedirection();
     app.UseStaticFiles();
     app.UseRouting();
     app.UseAuthorization();
     app.MapControllers();
     app.MapRazorPages();
     app.Run();
 }
Public Shared Sub Main(ByVal args() As String)
	 Dim builder = WebApplication.CreateBuilder(args)
	 builder.Services.AddDbContext(Of ApplicationDBContext)(Sub(options)
		 options.UseSqlServer(builder.Configuration.GetConnectionString("ProductDB"))
	 End Sub)
	 builder.Services.AddControllers()
	 ' Add services to the container.
	 builder.Services.AddRazorPages()
	 Dim app = builder.Build()
	 ' Configure the HTTP request pipeline.
	 If Not app.Environment.IsDevelopment() Then
		 app.UseExceptionHandler("/Error")
		 ' The default HSTS value is 30 days. You may want to change this for production scenarios, see .NET documentation https://aka.ms/aspnetcore-hsts.
		 app.UseHsts()
	 End If
	 app.UseHttpsRedirection()
	 app.UseStaticFiles()
	 app.UseRouting()
	 app.UseAuthorization()
	 app.MapControllers()
	 app.MapRazorPages()
	 app.Run()
End Sub
VB   C#

We need to run the migration, as we are using a code-first approach.

Run the following command in the Package Manager Console.

Add-Migration init

The above command will create a migration. Now we need to apply these migrations to our database. Run the following command in the Package Manager Console.

Update-Database

The above command will create tables in our database. Add dummy data in the Product Table, you may generate random data from Mockaroo.

Now, build and run this application.

Output

We can see, that we have a very interactive UI with advanced interaction controls.

Datatables .NET (How It Works For Developer): Figure 2 - Output

Now, pagination is implemented on the server side as shown below.

Datatables .NET (How It Works For Developer): Figure 3 - Pagination

Output UI

The data is then rendered on the Client Side with rich UI Control.

Datatables .NET (How It Works For Developer): Figure 4 - UI

You can explore more from the DataTables.NET documentation by clicking here.

Introduction of IronXL

IronXL is a library that allows you to work with Excel files in .NET applications. It can create, read, edit, and save Excel documents in various formats, such as XLS, XLSX, CSV, and TSV. It does not require Microsoft Office or Excel Interop to be installed. It supports .NET 8,7, 6, 5, Core, Framework, and Azure.

We often have a requirement to export data into Excel or CSV files. IronXL is the best choice in this case. Now, we will write a code to export our data into an Excel file.

Install IronXL

Install the IronXL library in our project by entering the following command in the Package Manager Console.

Install-Package ironXL.Excel
Install-Package ironXL.Excel
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'Install-Package ironXL.Excel
VB   C#

This will install IronXL and the required dependencies in our project.

Export Data to Excel

Let's write a code to convert our Product list into an Excel File.

public void ExportToExcel(List<Product> productList)
   {
       WorkBook wb = WorkBook.Create(ExcelFileFormat.XLSX);
       WorkSheet ws = wb.DefaultWorkSheet;
       int rowCount = 1;
       foreach (Product product in productList)
       {
           ws["A" + (rowCount)].Value = product.Id.ToString();
           ws["B" + (rowCount)].Value = product.ProductName;
           ws["C" + (rowCount)].Value = product.ProductDescription;
           ws["D" + (rowCount)].Value = product.ProductPrice;
           ws["E" + (rowCount)].Value = product.ProductWeight;
           ws["F" + (rowCount)].Value = product.ProductManufacturingDate;
           ws["G" + (rowCount)].Value = product.ProductExpiryDate;
           rowCount++;
       }
       wb.SaveAs("product.xlsx");
   }
public void ExportToExcel(List<Product> productList)
   {
       WorkBook wb = WorkBook.Create(ExcelFileFormat.XLSX);
       WorkSheet ws = wb.DefaultWorkSheet;
       int rowCount = 1;
       foreach (Product product in productList)
       {
           ws["A" + (rowCount)].Value = product.Id.ToString();
           ws["B" + (rowCount)].Value = product.ProductName;
           ws["C" + (rowCount)].Value = product.ProductDescription;
           ws["D" + (rowCount)].Value = product.ProductPrice;
           ws["E" + (rowCount)].Value = product.ProductWeight;
           ws["F" + (rowCount)].Value = product.ProductManufacturingDate;
           ws["G" + (rowCount)].Value = product.ProductExpiryDate;
           rowCount++;
       }
       wb.SaveAs("product.xlsx");
   }
Public Sub ExportToExcel(ByVal productList As List(Of Product))
	   Dim wb As WorkBook = WorkBook.Create(ExcelFileFormat.XLSX)
	   Dim ws As WorkSheet = wb.DefaultWorkSheet
	   Dim rowCount As Integer = 1
	   For Each product As Product In productList
		   ws("A" & (rowCount)).Value = product.Id.ToString()
		   ws("B" & (rowCount)).Value = product.ProductName
		   ws("C" & (rowCount)).Value = product.ProductDescription
		   ws("D" & (rowCount)).Value = product.ProductPrice
		   ws("E" & (rowCount)).Value = product.ProductWeight
		   ws("F" & (rowCount)).Value = product.ProductManufacturingDate
		   ws("G" & (rowCount)).Value = product.ProductExpiryDate
		   rowCount += 1
	   Next product
	   wb.SaveAs("product.xlsx")
End Sub
VB   C#

We have created an Excel file from the list in a very simple and easy way.

Datatables .NET (How It Works For Developer): Figure 5 - Excel Output

IronXL provides comprehensive tutorials, code examples, and documentation to use its comprehensive API in the best way possible.

In optimizing ASP.NET performance, we exclusively rely on Only Core Software, ensuring a lean and efficient development environment. Utilizing DataTables.NET as locally hosted packages further enhances responsiveness, minimizing external dependencies for streamlined data handling and Excel exportation. Additionally, contributing code efficiently becomes seamless within this optimized and self-contained ecosystem.

Conclusion

In summary, leveraging DataTables.NET for server-side processing in ASP.NET distribution repo projects proves to be a good strategy for handling substantial datasets efficiently. This approach ensures optimized performance by transmitting data in manageable chunks, mitigating bandwidth usage, and enhancing user experience. The integration of IronXL further extends the application's capabilities, enabling effortless export of tabular data to Excel for comprehensive data analysis and reporting.

By adopting these technologies, developers can create web applications that strike a balance between rich interactivity and resource efficiency, providing users with a seamless and responsive experience, especially in scenarios where large datasets are involved. IronXL offers various licensing, depending on the number of developers, projects, and redistribution needs. The licenses are perpetual and include free support and updates.