Using an AngularJS Factory to Interact with a RESTful Service

If you’re new to AngularJS check out my AngularJS in 60-ish Minutes video tutorial or download the free eBook. Also check out The AngularJS Magazine for up-to-date information on using AngularJS to build Single Page Applications (SPAs).

 

 

What’s covered in this Post?

  • Creating a RESTful Service
  • Creating an AngularJS Module
  • Creating a Factory
  • Creating a Controller

AngularJS provides a great framework for building robust Single Page Applications (SPAs) and provides built-in support for routing, MV*-style programming, services and factories, modules, testing, and much more. Although Angular can consume virtually any HTTP resource, in this post I’m going to focus on using it to consume a RESTful API created using ASP.NET Web API (note that any back-end service could be used). If you’ve worked with jQuery before then you’re used to calls such as $.getJSON() or $.ajax(). Although Angular plays really well with jQuery, it has built-in HTTP functionality that can be used out of the box and a way to encapsulate data functionality using factories or services.

Here’s a quick review of some of the key players in AngularJS. I’ll touch on modules, routes, factories, and controllers in this post and discuss how data functionality (such as RESTful service calls) can be encapsulated in factories that can be called from controllers.

image


Let’s kick things off by taking a look at a basic backend service written using ASP.NET Web API and then walk through several AngularJS features including a factory that talks to the service.

 

Creating a RESTful Service

 

ASP.NET Web API is a great back-end framework for exposing data to a variety of clients. Although I’ll focus on how JSON data can be exposed in this post, it can be used to serve up a variety of formats ranging from XML to images to custom formats. Here’s an example of a simple service that exposes customer and order resources to clients. When the service is called from Web clients it will automatically return JSON data.

 

    public class CustomersController : ApiController
    {
        ICustomerRepository _Repository;

        public CustomersController()
        {
            //CustomerRepository could be injected if desired
            _Repository = new CustomerRepository();
        }

        // GET api/customers
        public HttpResponseMessage Get()
        {
            var custs = _Repository.GetCustomers();
            if (custs == null) throw new HttpResponseException(HttpStatusCode.NotFound);
            return Request.CreateResponse<IEnumerable<Customer>>(HttpStatusCode.OK, custs);
        }

        // GET api/customers/5
        public HttpResponseMessage Get(int id)
        {
            var cust = _Repository.GetCustomer(id);
            if (cust == null) throw new HttpResponseException(HttpStatusCode.NotFound);
            return Request.CreateResponse<Customer>(HttpStatusCode.OK, cust);
        }

        // POST api/customers
        public HttpResponseMessage Post([FromBody]Customer cust)
        {
            var newCust = _Repository.InsertCustomer(cust);
            if (newCust != null)
            {
                var msg = new HttpResponseMessage(HttpStatusCode.Created);
                msg.Headers.Location = new Uri(Request.RequestUri + newCust.ID.ToString());
                return msg;
            }
            throw new HttpResponseException(HttpStatusCode.Conflict);
        }

        // PUT api/customers/5
        public HttpResponseMessage Put(int id, [FromBody]Customer cust)
        {
            var status = _Repository.UpdateCustomer(cust);
            if (status) return new HttpResponseMessage(HttpStatusCode.OK);
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }

        // DELETE api/customers/5
        public HttpResponseMessage Delete(int id)
        {
            var status = _Repository.DeleteCustomer(id);
            if (status) return new HttpResponseMessage(HttpStatusCode.OK);
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }

        [HttpGet]
        public List<Order> Orders(int custID)
        {
            var orders = _Repository.GetOrders(custID);
            if (orders == null) 
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound)); return orders; } }


Looking through the code you can see that all of the main players are there including methods to handle GET, PUT, POST, and DELETE operations. Each method relies on a repository object behind the scenes to handle interacting with the actual data source. There are a lot of articles out there on using the ASP.NET Web API to build services so I won’t go into more detail here. Check out the Web API site for additional information.

Now that you’ve seen the service let’s switch to the client-side and talk about how AngularJS can be used to consume the service.

 

Creating an AngularJS Module


AngularJS provides several different options for encapsulating data functionality including services, factories, and providers. In this example I’ll discuss factories (my personal favorite) and another object built-into the framework named $http. Before jumping into the factory code, let’s take a quick look at the module that’s configured for the application that I’ll be discussing throughout this post:

 

var app = angular.module('customersApp', ['ngRoute']);

app.config(['$routeProvider', function ($routeProvider) {

    $routeProvider.when('/', {
        controller: 'customersController',
        templateUrl: '/app/views/customers.html'
    })
    .otherwise({ redirectTo: '/' });

}]);


In this example a customersApp module is created that acts as a container for other components used in the application such as the factory that will be discussed next. Notice that in addition to defining the cutomersApp module, the code also references the ngRoute module which handles routing. This module is found in a file named angular-route.js which is new in AngularJS 1.2 – see my previous post for additional information.

Once the module is defined it’s used to configure routing for the application. This is done by calling the module’s config() function which accepts a $routeProvider object. In this simple example a single route is defined to handle the root path but additional routes can certainly be defined using the $routeProvider.when() function.

Now that the module is created it’s time to take a look at how a factory can be created and used to call the ASP.NET Web API service.

 

Creating a Factory

 

Although AngularJS controllers can call directly into back-end services, I prefer to put that type of functionality into factories so that it’s more re-useable and easier to maintain. The application discussed here relies on a factory named dataFactory to make calls into the ASP.NET Web API service.

If you’re new to factories they can be created by calling the angular.module(‘YourModule"’).factory() function (note that modules can also create services, providers, values, and constants):

 

image

 

A factory is responsible for creating and returning an object that can be used to work with data, validate business rules, or perform a variety of other tasks. Angular factories are singletons by default so the object returned by a factory is re-used by the application.

Here’s an example of a factory that handles GET, PUT, POST, and DELETE calls to the ASP.NET Web API service. The factory creates an object that handles making calls to the server.

angular.module('customersApp')
    .factory('dataFactory', ['$http', function($http) {

    var urlBase = '/api/customers';
    var dataFactory = {};

    dataFactory.getCustomers = function () {
        return $http.get(urlBase);
    };

    dataFactory.getCustomer = function (id) {
        return $http.get(urlBase + '/' + id);
    };

    dataFactory.insertCustomer = function (cust) {
        return $http.post(urlBase, cust);
    };

    dataFactory.updateCustomer = function (cust) {
        return $http.put(urlBase + '/' + cust.ID, cust)
    };

    dataFactory.deleteCustomer = function (id) {
        return $http.delete(urlBase + '/' + id);
    };

    dataFactory.getOrders = function (id) {
        return $http.get(urlBase + '/' + id + '/orders');
    };

    return dataFactory;
}]);

 


The $http object is injected into the factory at runtime by AngularJS and used to make Ajax calls to the server. Looking through the code you can see that it exposes get(), post(), put(), and delete() functions that make it a piece of cake to work with RESTful services. Because the functions defined in the factory don’t know what to do with the data they handle, each one returns a promise that can be wired up to callback functions by the caller.

As mentioned earlier, factories are singletons by default so the object returned by the factory can be re-used over and over by different controllers in the application. While AngularJS services can also be used to perform this type of functionality, a service returns an instance of itself (it’s also a singleton) and uses the “this” keyword as a result. Factories on the other hand are free to create their own objects inside of the factory function and return them. To make this more clear let’s compare the factory shown earlier to a service.

Here’s an example of a service named dataService. Note that the function defined in the service is the object returned to the caller rather than an object defined inside of the function as with a factory.

 

angular.module('customersApp')
    .service('dataService', ['$http', function ($http) {

        var urlBase = '/api/customers';

        this.getCustomers = function () {
            return $http.get(urlBase);
        };

        this.getCustomer = function (id) {
            return $http.get(urlBase + '/' + id);
        };

        this.insertCustomer = function (cust) {
            return $http.post(urlBase, cust);
        };

        this.updateCustomer = function (cust) {
            return $http.put(urlBase + '/' + cust.ID, cust)
        };

        this.deleteCustomer = function (id) {
            return $http.delete(urlBase + '/' + id);
        };

        this.getOrders = function (id) {
            return $http.get(urlBase + '/' + id + '/orders');
        };
    }]);

 

 

Creating the Controller

 

Now that the factory is created a controller can use it to make calls to the ASP.NET Web API service. Here’s an example of a controller named customersController that relies on the dataFactory for data retrieval and manipulation. All of the dataFactory functions return a promise which is resolved by the controller using the success() and error() functions. Once data is returned from the factory (assuming success) the $scope is updated which will drive the user interface.

 

angular.module('customersApp')
    .controller('customersController', ['$scope', 'dataFactory', 
        function ($scope, dataFactory) {

    $scope.status;
    $scope.customers;
    $scope.orders;

    getCustomers();

    function getCustomers() {
        dataFactory.getCustomers()
            .success(function (custs) {
                $scope.customers = custs;
            })
            .error(function (error) {
                $scope.status = 'Unable to load customer data: ' + error.message;
            });
    }

    $scope.updateCustomer = function (id) {
        var cust;
        for (var i = 0; i < $scope.customers.length; i++) {
            var currCust = $scope.customers[i];
            if (currCust.ID === id) {
                cust = currCust;
                break;
            }
        }

        dataFactory.updateCustomer(cust)
          .success(function () {
              $scope.status = 'Updated Customer! Refreshing customer list.';
          })
          .error(function (error) {
              $scope.status = 'Unable to update customer: ' + error.message;
          });
    };

    $scope.insertCustomer = function () {
        //Fake customer data
        var cust = {
            ID: 10,
            FirstName: 'JoJo',
            LastName: 'Pikidily'
        };
        dataFactory.insertCustomer(cust)
            .success(function () {
                $scope.status = 'Inserted Customer! Refreshing customer list.';
                $scope.customers.push(cust);
            }).
            error(function(error) {
                $scope.status = 'Unable to insert customer: ' + error.message;
            });
    };

    $scope.deleteCustomer = function (id) {
        dataFactory.deleteCustomer(id)
        .success(function () {
            $scope.status = 'Deleted Customer! Refreshing customer list.';
            for (var i = 0; i < $scope.customers.length; i++) {
                var cust = $scope.customers[i];
                if (cust.ID === id) {
                    $scope.customers.splice(i, 1);
                    break;
                }
            }
            $scope.orders = null;
        })
        .error(function (error) {
            $scope.status = 'Unable to delete customer: ' + error.message;
        });
    };

    $scope.getCustomerOrders = function (id) {
        dataFactory.getOrders(id)
        .success(function (orders) {
            $scope.status = 'Retrieved orders!';
            $scope.orders = orders;
        })
        .error(function (error) {
            $scope.status = 'Error retrieving customers! ' + error.message;
        });
    };
}]);

 

 

Summary


AngularJS has all of the building block components needed to integrate with back-end services. In this post you’ve seen how the $http object can be used to call a RESTful ASP.NET Web API service without writing a lot of code. You’ve also seen how data functionality can be encapsulated into a factory (or service) so that it can be re-used throughout an application. Keep in mind that although I used ASP.NET Web API in this example, the same general AngularJS code could be used to call a different back-end service created using Node.js, Python, or a variety of other languages/frameworks. Although the sample shown here is quite simple, I hope it gets you started using AngularJS and back-end services.


Check out my other posts on AngularJS

Published Friday, August 16, 2013 10:48 AM by dwahlin

Comments

# re: Using an AngularJS Factory to Interact with a RESTful Service

Friday, August 16, 2013 10:58 PM by Demetrius

Why didn't you use the $resource instead of $http? Is $resource no good?

# re: Using an AngularJS Factory to Interact with a RESTful Service

Saturday, August 17, 2013 12:19 AM by dwahlin

Demetrius:

$resource is definitely another option. If I get a chance I'll convert the code to use $resource just as a comparison.

Dan

# re: Using an AngularJS Factory to Interact with a RESTful Service

Saturday, August 17, 2013 12:02 PM by Tucaz

Great starting guide. However, resources are exactly what you should use in cases like this.

# re: Using an AngularJS Factory to Interact with a RESTful Service

Saturday, August 17, 2013 1:04 PM by steve strong

Nice job. Very complete post

# re: Using an AngularJS Factory to Interact with a RESTful Service

Saturday, August 17, 2013 2:43 PM by Lidoma

RESTful applications use HTTP requests to post data. right!!

Now, Are there any server or client side dependencies for implementing REST in an APIs?

# re: Using an AngularJS Factory to Interact with a RESTful Service

Saturday, August 17, 2013 5:09 PM by dwahlin

Tucaz:

Thanks for checking out the post. $resource is another way to do this and I may post about that in the near future. However, it's definitely not the preferred or only way - that depends on the dev and the app.  There are several fringe cases with $resource that can actually make it challenging in some scenarios.

If you're interested in some of the fringe stuff you can read more here:  github.com/.../restangular (as a side note I'm not inferring Restangular is the way to go - only played with it at this point - they just had a nice write-up about $resource)).

Dan

# re: Using an AngularJS Factory to Interact with a RESTful Service

Saturday, August 17, 2013 6:57 PM by quinntyne

Are you going to continue to update github.com/.../CustomerManager

# Using an AngularJS Factory to Interact with a RESTful Service - Dan Wahlin - ?????????????????????

Pingback from  Using an AngularJS Factory to Interact with a RESTful Service - Dan Wahlin - ?????????????????????

# re: Using an AngularJS Factory to Interact with a RESTful Service

Saturday, August 17, 2013 9:25 PM by dwahlin

quinntyne:

Yes - I plan to do additional updates once I can get back to it. I have some new code already done but need to refactor it a bit more before checking it in.

Dan

# re: Using an AngularJS Factory to Interact with a RESTful Service

Monday, August 19, 2013 2:56 AM by mehta.rahulit

fantastic

# re: Using an AngularJS Factory to Interact with a RESTful Service

Monday, August 19, 2013 2:57 AM by Darren Hunter

Another terrific article Dan. This is exactly what the docs a missing. Would be interested to know if you intend on pushing the limits of Restangular - from my quick look - looks like it has a lot of potential.

thanks again

# Dew Drop &ndash; August 19, 2013 (#1,606) | Alvin Ashcraft&#039;s Morning Dew

Pingback from  Dew Drop &ndash; August 19, 2013 (#1,606) | Alvin Ashcraft&#039;s Morning Dew

# Using an AngularJS Factory to Interact with a R...

Monday, August 19, 2013 2:09 PM by Using an AngularJS Factory to Interact with a R...

Pingback from  Using an AngularJS Factory to Interact with a R...

# Services/Factories | Pearltrees

Monday, August 19, 2013 7:10 PM by Services/Factories | Pearltrees

Pingback from  Services/Factories | Pearltrees

# Building an AngularJS Dialog Service

Monday, August 19, 2013 11:10 PM by Dan Wahlin

If you’re new to AngularJS check out my AngularJS in 60-ish Minutes video tutorial or download the free

# Using an AngularJS Factory to Interact with a R...

Tuesday, August 20, 2013 2:15 AM by Using an AngularJS Factory to Interact with a R...

Pingback from  Using an AngularJS Factory to Interact with a R...

# Using an AngularJS Factory to Interact with a R...

Tuesday, August 20, 2013 4:07 AM by Using an AngularJS Factory to Interact with a R...

Pingback from  Using an AngularJS Factory to Interact with a R...

# Using an AngularJS Factory to Interact with a R...

Tuesday, August 20, 2013 6:47 AM by Using an AngularJS Factory to Interact with a R...

Pingback from  Using an AngularJS Factory to Interact with a R...

# re: Using an AngularJS Factory to Interact with a RESTful Service

Wednesday, August 21, 2013 5:02 AM by dotnetdreamer

this is exactly what i needed :)

# re: Using an AngularJS Factory to Interact with a RESTful Service

Thursday, August 22, 2013 8:13 PM by Glenn

Great post Dan, and thank you for sharing.  

Based on your post, when deleting/adding resource items we have to manually remove those items from the array in $scope after a successful REST call.   I'm wondering if there is a more elegant way of doing this because if we use AngularFire all we have to do is remove the element from the array and the library would take care of any http/websocket calls to the responsible service/server.

Would  you care to jump into how we could implement the Observer pattern for this scenario?

# re: Using an AngularJS Factory to Interact with a RESTful Service

Thursday, August 22, 2013 11:35 PM by dwahlin

Glenn:

Thanks - glad the post was helpful. As far as the Observer pattern, you can setup a watch on properties and be notified as they change. That way you can simply remove the item from the collection and then handle updating the back end in the watch. Something like this

$scope.$watch('yourProperty', function (oldVal, newVal) {

   console.log(oldVal, newVal);

   //Act on the change here

}, true);

It would definitely be nice to have a factory tied into the watch process to automatically handle changes to a collection. I'll have to think through that a bit more.

Dan

# The AngularJS Magazine – What’s New this Week?

Friday, August 23, 2013 7:57 PM by Dan Wahlin

&#160; Click to view the FlipBoard magazine &#160; AngularJS Magazine Updates for August 23rd Configuring

# AngularJS Link Roundup &#8211; 26th August 2013 | Well Technically&#8230;

Pingback from  AngularJS Link Roundup &#8211; 26th August 2013 | Well Technically&#8230;

# The AngularJS Magazine – What’s New this Week?

Tuesday, September 3, 2013 10:10 AM by Dan Wahlin

&#160; Click to View &#160; AngularJS Magazine Updates for September 30th Custom Validations in AngularJS

# re: Using an AngularJS Factory to Interact with a RESTful Service

Friday, September 6, 2013 1:11 PM by Cristian

Hey Dan,

What do you mean with several fringe cases with $resource?

Could you tell me an example?

Do you think is to good to use it in a production environment?

# re: Using an AngularJS Factory to Interact with a RESTful Service

Friday, September 6, 2013 2:13 PM by dwahlin

Check out the link below for some info there. I haven't compared the change doc for 1.2 RC though so some of these issues may potentially be gone now:

github.com/.../restangular

Dan

# Using an AngularJS Factory to Interact with a R...

Friday, September 13, 2013 12:08 PM by Using an AngularJS Factory to Interact with a R...

Pingback from  Using an AngularJS Factory to Interact with a R...

# The AngularJS Magazine – What’s New this Week?

Tuesday, September 17, 2013 12:38 AM by Dan Wahlin

&#160; Click to View Here’s what’s new in the world of AngularJS. Check out the Flipboard magazine above

# re: Using an AngularJS Factory to Interact with a RESTful Service

Wednesday, October 9, 2013 3:59 AM by Taiseer Joudeh

Hello Dan,

Thanks for your post, I've small question here.

I've noticed that other tutorials use the code below in the factory using $q.defer()

var _getMovies = function () {

       var deferred = $q.defer();

       $http.get('/api/v1/movies')

          .then(function (result) {

              //scucess

              angular.copy(result.data, _movies);

              deferred.resolve();

          }, function () {

              //failure

              deferred.reject();

          });

       return deferred.promise;

   };

Can you elaborate more when we should use $q.defer() because I found your way easier to call WebAPI in factory.

Regards,

Taiseer

# Pro ASP.NET Web API: HTTP Web Services in ASP.NET | AUTOMOBILISS.NET

Pingback from  Pro ASP.NET Web API: HTTP Web Services in ASP.NET | AUTOMOBILISS.NET

# Using an AngularJS Factory to Interact with a R...

Tuesday, October 15, 2013 4:19 PM by Using an AngularJS Factory to Interact with a R...

Pingback from  Using an AngularJS Factory to Interact with a R...

# Pro ASP.NET Web API: HTTP Web Services in ASP.NET | AUTOMOBILISS.NET

Pingback from  Pro ASP.NET Web API: HTTP Web Services in ASP.NET | AUTOMOBILISS.NET

# AngularJS Highlights: Best of 2013 | SyntaxSpectrum

Saturday, December 28, 2013 6:03 AM by AngularJS Highlights: Best of 2013 | SyntaxSpectrum

Pingback from  AngularJS Highlights: Best of 2013 | SyntaxSpectrum

# AngularJS???2013???????????? / Owen Chen

Friday, January 3, 2014 9:43 AM by AngularJS???2013???????????? / Owen Chen

Pingback from  AngularJS???2013???????????? / Owen Chen

# AngularJS???????????? | ??????????????? geek521.com

Friday, January 3, 2014 10:30 PM by AngularJS???????????? | ??????????????? geek521.com

Pingback from  AngularJS???????????? | ??????????????? geek521.com

# Woche 22 | Blog von Michael

Friday, January 17, 2014 10:33 AM by Woche 22 | Blog von Michael

Pingback from  Woche 22 | Blog von Michael