Building an interactive grid with ASP.NET Web API and AngularJS: The basic setup (Part 1)

6 minute read

Introduction

I am currently involved in a project in which we use a combination of ASP.NET MVC and AngularJS powered by a ASP.NET Web API backend. For one of the pages we need to display tabular data in a grid where the user can filter, sort and page through the data. The Web API backend is a pretty standard REST based API and for communication between the API and the Angular frontend I have been using Restangular. Looking on the Angular Modules website it seemed as though most people favour the use of ngTable as an AngularJS table plugin. I did a small proof of concept and it seemed to work for my purposes, so I decided to use it for this project.

I learned quite a few things in building this seemingly simple little feature and I thought it would make for a nice little tutorial on how to put all these technologies together. This is the first in a series of blog posts in which I will walk you through the process of creating a filterable, sortable grid with paging using the combination of ASP.NET Web API, AngularJS, Restangular and ngTable.

Creating the basic ASP.NET MVC project

To start off we create a normal ASP.NET Web Project in Visual Studio

Select the template for an MVC project and make sure you also select the Web API check box. Click OK.

Once the project has been created I find it good practice to ensure that all the Nuget packages are updated to the latest versions, so go ahead and do that if you want to.

Install the required libraries

Next up we need to install all of the Javascript libraries we will need. You can do that by either installing the Nuget packages for these (if available) or alternatively download them from the web and copy the relevant javascript files into you scripts folder. In the case of ngTable there are also some CSS stylesheets you will need to copy into your Content folder.

Let’s run over each of these quickly:

Angular

For Angular there is an up to date Nuget package, so search for the Nuget package with the ID angularjs and install it.

The Nuget package will install a whole bunch of javascript files into the Scripts folder of your project.

Restangular

The Nuget package for Restangular was outdated so you can go to the Github releases for Restangular (https://github.com/mgonto/restangular/releases) and download the latest version. Extract the .ZIP file and copy the files restangular.js and restangular.min.js to your Scripts folder.

Underscore

Restangular requires either Lodash or Underscore to be installed. Go to the Underscore page at http://documentcloud.github.io/underscore/ and download the latest minified version. Copy the file (underscore-min.js) to your Scripts folder. You can also optionally download the source map file (underscore-min.map) and copy that to the Scripts folder.

ngTable

Go to to ngtable website (http://bazalt-cms.com/ng-table/), download the latest version and extract the .ZIP file. Copy the files ng-table.js, ng-table.min.js and ng-table.map to your Scripts folder. Copy the stylesheet files (ng-table.css, ng-table.min.css and ng-table.less) to your Content folder.

Update the Bundles

We need to update the CSS bundle to include the ngTable CSS file, so open the file App_Start/BundleConfig.cs and edit the definition of your CSS bundle to also include the file ng-table.min.css.

bundles.Add(new StyleBundle("~/Content/css").Include(
            "~/Content/bootstrap.css",
            "~/Content/ng-table.min.css",
            "~/Content/site.css"));

Also create a new script bundle called app to include all of the Javascript files we will need for the AngularJS application:

bundles.Add(new ScriptBundle("~/bundles/app").Include(
    "~/Scripts/angular.min.js",
    "~/Scripts/underscore-min.js",
    "~/Scripts/restangular.js",
    "~/Scripts/ng-table.min.js"
    ));

Create the AngularJS application

For the AngularJS application I create a separate folder called App. Inside this folder I create a file called app.js which declares my AngularJS application. Make sure to also add restangular and ngTable as dependencies.

(function () {
    'use strict';

    angular.module('app', [
        // Angular modules 

        // Custom modules 

        // 3rd Party Modules
        'restangular',
        'ngTable'
    ]);
})();

Next up create the AngularJS controller. For this example we will demonstrate how to bind the grid to a list of customers, so I create a file called customers.controller.js in my App folder and inside of this file I define the controller called CustomersController.

(function () {
    'use strict';

    angular
        .module('app')
        .controller('CustomersController', CustomersController);

    CustomersController.$inject = ['$location']; 

    function CustomersController($location) {
        /* jshint validthis:true */
        var vm = this;
        vm.title = 'CustomersController';

        activate();

        function activate() { }
    }
})();

At this point I just want to make a quick mention of the fact that I used the SideWaffle templates to create my AngularJS app and controller. If you have not done so before have a look at the SideWaffle website (http://sidewaffle.com/) as it adds a whole bunch of really nice project and file templates to Visual Studio. In my case I used the AngularJs Module template to create the AngularJS application and the AngularJs Controller template to create the Customers Controller.

Add the files to your script bundle

We need to update our application script bundle to add the 2 files we just created, so open the BundleConfig class again and update the bundle definition inside the RegisterBundles() method.

bundles.Add(new ScriptBundle("~/bundles/app").Include(
    "~/Scripts/angular.min.js",
    "~/Scripts/underscore-min.js",
    "~/Scripts/restangular.js",
    "~/Scripts/ng-table.min.js",
    "~/App/app.js",
    "~/App/customers.controller.js"
    ));

I also suggest that you disable optimization in your bundles, i.e. no combining of scripts / stylesheets or minifications. It is going to make your life a whole lot easier if you need to debug later to find issues, so locate the line BundleTable.EnableOptimizations = true in your BundleConfig class and comment it out:

// Set EnableOptimizations to false for debugging. For more information,
// visit http://go.microsoft.com/fwlink/?LinkId=301862
//BundleTable.EnableOptimizations = true;

Update the HTML

We need to add the app bundle to our layout file, so open your _Layout.cshtml file and add the app bundle after the two existing bundles:

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/app")

We also need to hook up the Angular application so edit the <body> tag of your layout file to add the ng-app directive:

<body ng-app="app">
    <div class="container body-content">
        @RenderBody()
    </div>

    ...
</body>

The last bit is to declare the ng-controller in our home page. Open the Views\Home\Index.cshtml file and delete all of the existing content and add the HTML snippet below:

<div ng-controller="CustomersController as vm">
    <h1></h1>    
</div>

You will notice in the HTML snippet that I have added the expression `` to my <H1> element. This is just a temporary checkpoint so we can run the application at this point and make sure that everything is hooked up correctly. So go ahead and run the application.

If you see the text “CustomersController” like in the screenshot above it means all the scripts are loading correctly and the Angular application and controller has run without any errors.

If you see the text “” it means the expression was not successfully evaluated and something is not hooked up correctly. If this is the case you will need to use your browser developer tools to ensure that all scripts loaded correctly and if there are any Javascript errors you will need to see what they are and correct them. Unfortunately I am not available for remote debugging, so you’re on your own if this is the case ;)

Conclusion

In this blog post I created the basic framework for the application and ensured that all the infrastructure is in place. Next time will will create an API to get the list of customers and hook it up to the grid.

In Part 2, we will be adding a basic grid.

Did you notice an error? Please help me and the other readers by heading over to the GitHub repo for this blog and submit a Pull Request with the corrections.