Create complete reports using DataTables and ASP.NET MVC Core

Create complete reports using DataTables and ASP.NET MVC Core

DataTables is a very nice JavaScript library that will improve the reports on your web applications

A bit of history

One of the most important things when we think of reporting is a table with plenty of features. Such as ordering, filtering, selecting and so on. Back in the good old days of webforms and Rapid Application Development we had a very good control called GridView. It was clunky and, thanks to its ViewState, the page was getting very heavy after some interactions. In case you are not familiar with what I said, I'm talking about times where a simple ordering would trigger a page refresh (PostBack) and the state of the page controls was kept in a hidden field (the ViewState).

Some time later we had the infamous ASP.NET AJAX, which allowed us to use webform controls without page refresh. Unfortunately, all it did was to send the whole ViewState through Ajax. Meaning: We didn’t see the PostBack anymore but it was still happening in the background. The Ajax way. However, the page was still heavy.

Gridview
Source: https://www.youtube.com/watch?v=_Ms5_6e7Fu4

 

With ASP.NET MVC we gained more control over the HTML output but we had to say goodbye to the Gridview control. Instead, we must use HTML table which, in all fairness, does the job. However, in more advanced scenarios, we would have to go for external libraries. And I am going to show you how to use my favorite one - DataTables.

DataTables

The DataTables is one of the many JavaScript libraries we can use to enrich the tables in our web projects. In its basic implementation it allows the user to view, filter and order the data with ease. And better yet, without so much extra work for us. And if you are working with more advanced scenarios, you can customize it without problems.

datatables-example.png

Let’s see below how to implement it in a simple ASP.NET MVC Core website. You can get the demo on GitHub.

Implementation

The normal implementation is relatively simple. All you need is a data source and a View. However, my implementation has some extra things to consider since I am going for a more flexible scenario. The whole idea is to have the backend do most of the data work and leave the library with the formatting. And for that we will use:

  1. Data source – No matter which. Memory, SQL Server, Oracle. Your choice;
  2. Models and ViewModels – We need some specific objects to make our job easier;
  3. Attributes – Important if we want to control the columns in the DataTable;
  4. Service, Helpers – Used to transform the raw data into something we can use;
  5. Reflection – Because we want the implementation to be as dynamic as possible;
  6. JavaScript configuration – Important as we will need to customize a bit the implementation;
  7. The API – We will load the data via Ajax, so we need a small API to work with;
  8. A View – Because we need to show the DataTable at some point

Data source

If you need to implement a data table it means you have a data source of some sort. In this demo we are going to use in-memory data but it could easily come from any kind of database. Here it is:

As you can see the PersonRepository should return all people (read only) and return the total amount of people in the imaginary “People table”.

Models and ViewModels

Some of these objects should help with data binding, others to help with the data formatting. You can find all of them here but the most important are:

DataParameters

We will use it to help with the data binding coming from the UI. It contains all we need to filter and order our data.

PersonTableViewModel

Used to shape the Person data coming from the data source into exactly what we need for the UI. It uses some custom attributes to help shaping the data and also some static methods to help with ordering and filtering.

TableViewModel

This is the DataTable itself.

Attributes

Since I am generating the DataTable information on the backend I decided to create some custom attributes to help me with it. You can see them here but, for short, they are:

  • Orderable – In case the property has this attribute it means we can order our data;
  • Searchable – The property containing this attribute will be used in the search field;
  • ShowOnDataTable – It allows the property to be shown in the UI. You can also use it to set the order it will appear and a custom column name.

Service and Helpers

The Service is just a small mock of a Service Layer but it could be anything depending on the architecture you are following in your project. The most important is to create a specific method which return values formatted for the DataTable, as you can see below:

Notice that:

  • The method accepts an argument of type DataParameters, which contains the values coming from the UI control;
  • The static methods of PersonTableViewModel are being used to filter and order the data;
  • The return type is a tuple.

As for the Helpers I have 2 classes. The first one is the ExpressionBuilder (bad name, I know), which will help us to build the expression queries for filtering. I am using because since the query is handling the data in-memory. Another scenario where the ExpressionBuilder would be useful is when we are using Entity Framework as we would dynamically build the query before sending to the database.

The other helper is the DataTableHelper. It will prepare both header and content for the UI based on the custom attributes we have in each property of PersonTableViewModel.

Reflection

As you could see I am using a little bit of reflection to get the properties and custom attributes. In this way we would be able to add and remove columns by simply editing the PersonTableViewModel without breaking the UI.

JavaScript configuration

As of now, there is no web without JavaScript. And since DataTables is a JavaScript library we need to do a small configuration. Here we will enable a couple of things:

  • processing – Enables the process indicator;
  • serverSide – Enables server-side processing of data;
  • ajax – Loads the data from an Ajax source. In our case a dedicated method in the HomeController.

The API

There are 2 things we need to make it happen in order to make the DataTable look good. The first is to setup the table headers. We will achieve that by returning a List<string> values when we call the page. That is done by using the BuildDataTableHeader method we made in the DataTableHelper, as seen below:

The second is to return the content data. We will create a specific method for that and name it GetPeopleData:

The idea here is to load the data and pass it into the BuildDataTable method in order to make it compatible with the DataTable library. The library, then, will get the data we are returning and format it into the HTML table.

A View

Our view should be very simple – a <table> tag, a CSS call and some JavaScript configuration. However, since we are aiming for some flexibility, let’s tweak the View a little bit:

From the top of the View:

  • @model List<string> – Since we need to load the table headers in the beginning, we are passing it in the first request.
  • The @foreach loop – Not the best place to do this but we need to prepare the header and footer tags in order to use it in the DataTable
  • <table> – A the simple HTML table with some styles and the header/footer we just created
  • @section Scripts – With the library and our JavaScript configuration

Don’t forget that the data coming via Ajax should match our columns perfectly, thanks to the DataTable script and the preparation we made in the backend.

Conclusion

And here we have, ladies and gentleman. A nice table with search and ordering:

conclusion.png

The demo may seem overly complex for such a small thing but it scales quite well. I am using it both in my website and in a project at work with zero problems so far. Of course, some tweaks will be necessary when adapting to your project but it should be a no brainer. And once you grasp the concept it’s very easy to replicate it.

Once again, you can get the source code here: https://github.com/davidsonsousa/DataTables-With-AspNetCore

Maybe I will create a NuGet out of it someday 😉