Tuesday, 27 August 2013

Consuming Web API OData using $resource service of Angular JS

In one of the previous posts, we saw exposing an OData Endpoint from an ASP.NET Web API service and then we consumed it using .NET and JavaScript clients. In this post, we will continue with consuming the service using Angular JS.

$resource is a wrapper around $http service of Angular JS to interact with RESTful data services. If we use $resource, we don’t need to deal with the low level HTTP calls that we used to do with $http.

Since $resource is targeted for REST based services, it has to be configured with the service URL and a few of other optional settings to get it work. Following snippet shows syntax of a sample configuration:

$resource(url, { key:val, .. }, {
    ‘getValues’: {method: ‘GET’, params: { param: val }, … },

$resource is not a part of Angular’s core module. To use $resource in an Angular JS application, the module ngResource has to be injected into the module depending on it. To know more about $resource, visit the official documentation page on website of Angular JS.

$resource can be configured to perform all of its operations on a single URL or even the URL can be over-written in the action configuration, if required. To consume a Web API OData service, we need to use the second approach as the URL differs based on the operation we will be performing.

Following factory returns a $resource object to perform CRUD operations on the OData resource:

var app = angular.module('employeeApp', ['ngResource']);
app.factory('employeeSvc', function ($resource) {
    var odataUrl = "/odata/Employees";
    return $resource("", {},
        'getAll': { method: "GET", url: odataUrl },
        'save': { method: "POST", url: odataUrl },
        'update': { method: 'PUT', params: { key: "@key" }, url: odataUrl + "(:key)" },
        'query': { method: 'GET', params: { key: "@key" }, url: odataUrl + "(:key)" },
        'remove': { method: 'DELETE', params: { key: "@key" }, url: odataUrl + "(:key)" }

This factory can be injected inside any component and used there. Each action configured above is exposed as a method on the object returned from the factory with a dollar($) symbol prepended to each of them. Since these methods deal with AJAX, they return a $q promise.

Following controller uses the methods defined above to operate on the data service:

app.controller('EmployeeCtrl', function ($scope, employeeSvc) {

    //Getting all employees and assigning to a scope variable           
    function refreshEmployees() {
        (new employeeSvc()).$getAll()
            .then(function (data) {
                $scope.employees = data.value;

    //Add a new employee to the resource
    function createEmployee(emp) {
        return emp.$save();

    //Modify details of an existing employee
    function editEmployee(emp) {
        return (new employeeSvc({
            "Id": emp.Id, "Name": emp.Name, "Salary": emp.Salary
        })).$update({ key: emp.Id });

    //Delete an employee
    function deleteEmployee(id) {
        return (new employeeSvc()).$remove({ key: id });

    //rest of the controller definition.......

Take a look at the refreshEmployee function created above. It calls then() on the returned object from the $getAll() method to grab the response as soon as the GET request is completed. As Web API OData sets actual data to the property value, the scope variable is assigned with this property.

Happy coding!


  1. What about get with filters and counts for pagination

    1. Check this blog post: http://sravi-kiran.blogspot.com/2013/09/ExploringWebApiODataQueryOptions.html. If you want to do this with datajs, check the documentation of datajs on codeplex.

  2. How do authentication with resources ?

    1. Wander,

      I will do a blog post on that.