ASP.Net MVC Web API AngularJS and Bootstrap application structure

AngularJS Route AngularJS UI Bootstrap angular js application structure bundle css and javascript files return json from webapi

Application structure by using ASP.Net MVC, Web API, AngularJs is not complicated but we need to know what NuGet Packages are required and what can make the application easy and speed up the development. In this article we will use MVC 4, Visual Studio 2012, Web API and AngularJS to create a single page application. We will try to use different folders for keeping our controllers, services, directives and views and will see how easy it is to use and link them.

Let’s start by creating our application step by step:

  1. Open Visual Studio
  2. File Menu => New Project
  3. Select ASP.Net MVC 4 Web Application
  4. Give any name say “MVCAngularWeb”
  5. Click Ok
  6. Select “Internet Application” and click OK

Our MVC Application is ready to use, run it and check it is working, but we have to create an AngularJS single page application (SPA) so we need many JavaScript files, we will add different NuGet Packages to make it workable, let’s start adding them, in solution explorer, right click on project name say “MVCAngularWeb” and select Manage NuGet Packages and add following items in our project

  1. AngularJS Core
  2. AngularJS Route
  3. AngularJS Sanitize
  4. Bootstrap (Not necessary but need to design the website)
  5. AngularJS UI Bootstrap (Native angularjs directives for bootstrap)
  6. JQuery (to update with latest version of jquery)

That’s it, now we will add different folders to keep our angular files, here is the structure

  • app
    • Controllers
    • Directives
    • Services
    • Views
    • app.js

I am going to use Customers table in Northwind database and show its content on the customers list page, so add two JavaScript files, one into controllers and other into services as

  1. /app/Controllers/Customer.js
  2. /app/Services/Customer.js

We created all of our required files to work, not time to bundle all these files into our BundleConfig.cs file, so easily we can refer the CSS and JavaScript files, here is the BundleConfig.cs file in App_Start folder

// Default by MVC application
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
             "~/Scripts/jquery-{version}.js"));

// Default by MVC application
bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
              "~/Scripts/jquery-ui-{version}.js"));

bundles.Add(new ScriptBundle("~/bundles/bootstrapjs").Include(
              "~/Scripts/bootstrap.js",
              "~/Scripts/angular-ui/ui-bootstrap-tpls.js",
              "~/Scripts/bootstrap-datepicker.js"
              ));

bundles.Add(new ScriptBundle("~/bundles/angularjs").Include(
                 "~/Scripts/angular.js",
                 "~/Scripts/angular-route.js",
                 "~/Scripts/angular-ui-router.js",
                 "~/Scripts/angular-sanitizer.js"
                 ));
bundles.Add(new StyleBundle("~/Content/css").Include(
                    "~/Content/site.css",
                    "~/Content/bootstrap.css",            
                    "~/Content/bootstrap-theme.css",
                    "~/Content/bootstrap-datepicker.css"));

// Default by MVC application
bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
                    "~/Content/themes/base/jquery.ui.core.css",
                    "~/Content/themes/base/jquery.ui.resizable.css",
                    "~/Content/themes/base/jquery.ui.selectable.css",
                    "~/Content/themes/base/jquery.ui.accordion.css",
                    "~/Content/themes/base/jquery.ui.autocomplete.css",
                    "~/Content/themes/base/jquery.ui.button.css",
                    "~/Content/themes/base/jquery.ui.dialog.css",
                    "~/Content/themes/base/jquery.ui.slider.css",
                    "~/Content/themes/base/jquery.ui.tabs.css",
                    "~/Content/themes/base/jquery.ui.datepicker.css",
                    "~/Content/themes/base/jquery.ui.progressbar.css",
                    "~/Content/themes/base/jquery.ui.theme.css"
                    ));

 // our controller, services, directives and main app js files
 bundles.Add(new ScriptBundle("~/bundles/app").Include(
               "~/app/app.js",
               "~/app/controllers/customer.js",
               "~/app/services/customer.js"
               ));

In future when we will create any new controller, directive or service, we need to add them here.

Let’s adjust our _Layout view to treat it as an Angular application as well as add the above bundled CSS and script files, here is the _layout.cshtml file after modification

<!DOCTYPE html>
<html lang="en">
<head>
    <!-- Other code removed-->
    @Styles.Render("~/Content/css")
    @Styles.Render("~/Content/themes/base/css") 
</head>
<body ng-app="app">
    <!-- Code for page header removed -->

    <div  class="container">
            @RenderBody()
    </div>
    <!-- Footer code removed -->

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

</body>
</html>

Let’s explore what we are doing here, in header section I added both the CSS bundle and rest of the JavaScript files I put at the bottom, note the order of these files, it is important, if we call the app at the first line it will start giving error because those files are dependent on angular js.

ng-app="app" The ngApp directive designates the root element of the application and is typically placed near the root element of the page - e.g. on the body or html tags.

Now open the home folder in view and open index.cshtml, remove everything and replace with

<div ng-view>

</div>

ngView is a directive that complements the $route service by including the rendered template of the current route into the main layout (index.html) file.

Now time to write the code for our customer service to get the data from database, but for now we will use hard coded data, which latter on we will expand to pull data from Web API, open customer.js in services folder and paste following lines

app.factory('CustomerService', function ($http, $q, $log, $rootScope) {    
    var service = {
        data: {
            customers: [
                        { id: 1, name: 'Customer 1' },
                        { id: 2, name: 'Customer 2' },
                        { id: 3, name: 'Customer 3' }
                    ]
        }
    }

    return service;    
});

Let’s pull these data into our controller, so open customer.js file in /app/controllers folder and add these lines

app.controller('CustomerController', function ($scope, CustomerService, $routeParams, $log) {

    $scope.data = CustomerService.data;

});

Before writing code for our app.js file let’s complete the CustomerList.html, so create a new folder Customers into /app/views, and a new html file into it so path will be /app/views/customers/customerlist.html, and here is the code for this file

<h1>Customer List</h1>    
<table class="table table-border">
  <tr>
    <th>ID</th>
    <th> Name</th>
  </tr>
  <tr ng-repeat="item in data.customers">
    <td>{{item.id}}</td>
    <td>{{item.name}}</td>
  </tr>
</table>

Time to write our final code before running the application, so open the app.js file in /app/app.js and add these lines

var app = angular.module('app', ['ngRoute', 'ui.bootstrap']);
app.config(
    function ($routeProvider, $httpProvider, $locationProvider) {

        $routeProvider
            .when('/customers', { templateUrl: 'app/views/customers/customerlist.html', controller: 'CustomerController' })

            .otherwise({ redirectTo: '/customers'});
    }
);

Run the application and try to open http://localhost:xxxxx/#/customers and here is the ouput

alt text

Up to this point everything is smooth now we will add entity framework to access the database to pull the customer records from Northwind database. Add ADO.Net Entity Data Model and add all the tables from Northwind Database, we are not discussing about entity framework so we will not discuss more here about it.

One thing we need to change, if you can see the customer class created by entity model, it will have references of two other tables Order and CustomerDemographic, so when it will try to convert into json it will give error of circular reference, so to fix this problem add code to JsonIgnoreAttribute like this

 [Newtonsoft.Json.JsonIgnoreAttribute]
 public virtual ICollection<Order> Orders { get; set; }
 [Newtonsoft.Json.JsonIgnoreAttribute]
 public virtual ICollection<CustomerDemographic> CustomerDemographics { get; set;  

After adding Entity Data Model rebuild the application and add controller Customers into controller folder.

  1. Right click on the controller folder
  2. Select Add => Controller
  3. Give a controller name “CustomerController”
  4. Select Template “API controller with read/write action, using Entity Framework
  5. Select Model class “Customer (MVCAngularWeb)”
  6. Select Data contect class “NorthwindEntities (MVCAngularWeb)” or whatever you given the name
  7. Click Add

It will create the code for us like this

namespace MVCAngularWeb.Controllers
{
    public class CustomerController : ApiController
    {
        private NorthwindEntities db = new NorthwindEntities();

        // get api/Customer
        public IEnumerable<Customer> GetCustomers()
        {
            return db.Customers.AsEnumerable();
        }
        .......................
        .......................
    }
} 

Change the GetCustomers code a little bit to get only 10 records for now, latter on we will change it to search the customers, when we will use ng-grid.

public IEnumerable<Customer> GetCustomers()
{
      return db.Customers
               .Take(10)
               .AsEnumerable();
}

To test, whatever the tool I know the best is google chrome “REST Console”, if you want you can try it.

Now we will change our Customer.js service to pull the data from database, here is the modified code

app.factory('CustomerService', function ($http, $q, $log, $rootScope) {    
    var baseUrl = '/api/customer';

    var service = {
        data: {
            customers: []
        },
        find: function () {            
            var deferred = $q.defer();
            $http.get(baseUrl)
            .success(function (data) {
                service.data.customers = data;
                deferred.resolve(data);
            }).error(function () {
                deferred.reject();
            });
            return deferred.promise;
        }    
    }
    service.find();
    return service;
});

I use $q.defer(); to get data asynchronously. Here is the changed CustomersList.html

<h1>Customer List</h1>
<table class="table table-hover table-bordered">
  <tr>
    <th>ID</th>
    <th>Contact Name</th>
    <th>Contact Title</th>
    <th>Address</th>
    <th>City</th>
    <th>Postal Code</th>
    <th>Country</th>
  </tr>
  <tr ng-repeat="item in data.customers">
    <td>{{item.CustomerID}}</td>
    <td>{{item.ContactName}}</td>
    <td>{{item.ContactTitle}}</td>
    <td>{{item.Address}}</td>
    <td>{{item.City}}</td>
    <td>{{item.PostalCode}}</td>
    <td>{{item.Country}}</td>
  </tr>
</table>

Run the application and output will be like this:

alt text

In this article we could not add much of the features because we were discussing the application structure, but in our next article, we will use ng-grid to show the result with paging, sorting and searching functionality.

Download source code

See my next article: ng-grid search sort paging with AngularJs WebAP and MVC ASP.Net

Ali Adravi Having 13+ years of experience in Microsoft Technologies (C#, ASP.Net, MVC and SQL Server). Worked with Metaoption LLC, for more than 9 years and still with the same company. Always ready to learn new technologies and tricks.
  • angularjs
  • webapi
  • mvc
  • bootstrap
  • asp.net
By Ali Adravi On 17 Nov, 14  Viewed: 9,668

Other blogs you may like

Angularjs powerful paging on table and searching with delay and demo

Paging on table is the basic requirement and most of us look for some grid so it can provide the complete feature of paging and sorting but in Angularjs it is so easy that anyone can achieve it by writing some code. I checked and found most of the available code give the paging feature in for 1 to... By Ali Adravi   On 14 Aug 2015  Viewed: 15,235

Angularjs Cascading Dropdown/Select with demo

Cascading dropdown with angularjs is easier than MVC and ASP.Net. In Angularjs ng-change is the best event to hook the function to get the second dropdown list items. In this article, we will try to fill the state dropdown on selection change of country and then fill the city dropdown on change... By Ali Adravi   On 06 Aug 2015  Viewed: 50,912

Angularjs CRUD with Web API, Entity Framework & Bootstrap modal popup part 2

Add/Edid Customer in Modal Popup --- In previous article we discussed how to search, delete and show detail of customer and contact list. In this article we will try to open the modal popup to add new customer and edit an existing customer record. I divided article in two parts because of the... By Ali Adravi   On 29 Jul 2015  Viewed: 18,009

Custom Directives in AngularJS with example and demo

Angularjs custom directives are the common to avoid the duplicate code, it is easy powerful and really nice. There are already too many directive have been created by experts but as a developer we need to write our own to achieve our specific goal. ng-model, ng-if, ng-show, ng-repeat all these are... By Ali Adravi   On 29 Jul 2015  Viewed: 4,068

Angularjs CRUD with Web API, Entity Framework & Bootstrap modal popup part 1

Search sort Insert update and delete are the basic features we need to learn first to learn any language, In this article we will try to create these features with Web API, bootstrap modal popup and ui.router. We will use enetity framework code first to save and retrieve data from database. We... By Ali Adravi   On 28 Jul 2015  Viewed: 29,565