Sunday, August 10, 2014

AngularJS Consuming ASP.NET Web API RESTful Services

In this post let’s see how we can use AngularJS to consume RESTful ASP.NET Web API services. Please note that I am not going to go deeper in ASP.NET Web API here. Even though ASP.NET Web API is related to our subject today, it should be discussed under it’s own separate topic. Today I assume that you have some knowledge in working with ASP.NET Web API. (If you are not, go and have some quick lessons on Learn About ASP.NET Web API)

In one of my previous posts, I wrote about Creating an Empty ASP.NET Project Powered by AngularJS using Visual Studio and for this post I am going to use that sample as the base and modify from there.

So now I have a ASP.NET Empty project all configured with AngularJS. Let’s add a new project to the solution. I am right clicking on the solution and clicking on Add –> New Project.

image
New Project
I am giving a name and clicking on OK. From the next dialog window, I am selecting Web API and clicking on OK.

image
Web API
Once the project is created, I am going to do some configuration changes in the project.

First right click on the AngularJSSample project and click on Properties. There under Web tab, copy the Project Url.

image
Project URL
Now right click on the Web API project and click on Properties. There on the Web tab change the Project Url as follows.

image
Project URL
If you are prompted for creating a Virtual Directory, Click on OK. Basically what I have done here is making our ASP.NET Web API run on the same host under a different virtual directory. For example, if the AngularJSSample project Url is “http://localhost:2222”, the Web API project Url will be “http://localhost:2222/api”. 

Now let’s start modifying the Web API project. First Let’s add a my favorite “Employee” model to the project. Right click on the “Model” folder and add a new class named “Employee”.
using System.Collections.Generic;

namespace WebAPI.Models
{
    public class Employee
    {
        public int EmployeeId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public static List<Employee> GetEmployees()
        {
            return new List<Employee>()
            {
                new Employee()
                {
                    EmployeeId=1,
                    FirstName="Jaliya",
                    LastName="Udagedara"
                },
                new Employee()
                {
                    EmployeeId=2,
                    FirstName="John",
                    LastName="Smith"
                },
                new Employee()
                {
                    EmployeeId=3,
                    FirstName="Jane",
                    LastName="Smith"
                }
            };
        }
    }
}
Now  in the Web API project, I am clicking on the Controllers folder and Add –> Controller. There I am selecting Web API 2 Controller – Empty.

image
Web API 2 Controller - Empty
I am giving the Controller names as “EmployeesController”.

image
EmployeesController
Here for demonstration purposes, my “EmployeesController” would be exposing data which is returned by “Employee.GetEmployees()” method. In real implementations, you can be retrieving data from databases etc.

I am writing the following method to return all employees.
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using WebAPI.Models;

namespace WebAPI.Controllers
{
    public class EmployeesController : ApiController
    {
        [HttpGet]
        [Route("employees")]
        public IEnumerable<Employee> GetEmployees()
        {
            return Employee.GetEmployees().AsEnumerable();
        }
    }
}
Here I have decorated my Action with HttpGet and Route attributes. These attributes are for saying when you request a HttpGet on "http://localhost:2222/api/employees", call the GetEmployees() method. Here you don't actually have to decorate the method with Route attribute unless you want to mention a custom route. Default route would be Controllers name without the Controller part of it (EmployeesController -> Route would be "http://localhost:2222/api/employees"). These of course, comes with ASP.NET Web API theories and practices.

Now run the Web API project, and navigate to Employees controller through the url. If all is good, you should be able to see the following.

image
Result
Now our task for today is consuming the above ASP.NET Web API REST service using AngularJS. In my Web API project, I will have a service with a HttpGet which will return me all the employees.

Let’s move into the AngularJSSample project. I am going to show all the employees in my home page. So let’s go to “App –> controllers” and start modifying the “homeController.js”.
'use strict';

app.controller('homeController', ['$scope', 'employeeService', function ($scope, employeeService) {
    $scope.message = "Now viewing home!";
 
    $scope.employees = {
        EmployeeId: "",
        FirstName: "",
        LastName: ""
    };
 
    employeeService.getEmployees($scope);
}])

app.service('employeeService', ['$http', function ($http) {
    this.getEmployees = function ($scope) {
        return $http({
            method: "GET",
            url: "../api/employees",
            headers: { 'Content-Type': 'application/json' }
        }).success(function (data) {
            $scope.employees = data;
            console.log(data);
        }).error(function (data) {
            console.log(data);
        });;
    };
}]);
Here I have used AngularJS Service named “employeeService” to call ASP.NET Web API. There I have a method named getEmployees() which is responsible for calling the Web API and setting the values in $scope object which was passed in as a parameter.

In my “homeController”, I am injecting the “employeeService” and making use of it. Then let’s modify the home template which was located in “App/views”, to show the values retrieved from the service.
<div ng-controller="homeController">
    <h1>{{message}}</h1>
 
    <div ng-repeat="employee in employees">
        <label>{{employee.EmployeeId}}</label>
        <label>{{employee.FirstName}}</label>
        <label>{{employee.LastName}}</label>
    </div>
</div>
Here I have used the ng-repeat directive which kind of acts as a foreach in C#. Now when I run the "AngularJSSample" project, I can see the following.

image
Result

Here I have only wrote about AngularJS querying values from ASP.NET Web API through HttpGet. It’s up for you to discover how AngularJS makes other operations such as HttpPost etc. on RESTful services.

I am uploading the sample to OneDrive.


Happy Coding.

Regards,
Jaliya

19 comments:

  1. I'm going to give this a shot. Thanks!

    ReplyDelete
  2. Great information to read. Thanks for sharing. Angular js article is very useful for my upcoming project. Ruby on Rails Developers

    ReplyDelete
  3. Really useful couple of posts - helped a lot. Thank you!

    ReplyDelete
  4. Very Nice..Easy to Implement and Understand. Thanks

    ReplyDelete
  5. thanks for sharing... ^_^

    ReplyDelete
  6. Thanks for sharing!!

    ReplyDelete
  7. I have a couple of questions about this. First, I found that since the api directory _is_ the Web Services directory, I had to change the routing in WebAPIConfig to remove "api." Is there a way around this?
    Also, with the virtual directories, etc., it's not clear how you'd publish this, especially with that routing change.

    ReplyDelete
  8. thank you. project url part was extremely helpful. I was suffering from it for 8 hours.

    ReplyDelete
  9. while writing "EmployeesController", I am getting error saying 'Employee' could not be found (are you missing a using directive or an assembly reference?).. Am I missing something??

    ReplyDelete
  10. I figured that out. The file "EmployeesController.cs" was missing one line "using WebAPI.Models;".

    ReplyDelete
  11. Great work!! I was able to do this successfully.

    ReplyDelete
  12. First I built my own Web API project with AngularJS (in Visual Studio Community), but it kept failing with the error shown below. So I built the project shown here and (after about an hour's work) I ran it, and I get the same error. Do you have any idea why my system is giving me this error with both your data and code and mine?

    SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data.

    ReplyDelete
  13. I created a Web API that used AngularJS to retrieve the data and it always failed with the error shown below. So I built your sample project here and when I ran it I got the same error. Do you have any idea why my system keeps getting this JSON error? Maybe there's some component I need to install? I'm using Visual Studio Community 2015.

    SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data

    ReplyDelete
    Replies
    1. There is nothing wrong with your Visual Studio installation. This is due to a formatting error in what ever the data you trying to POST.

      Delete
  14. I solved the question I posted earlier. It was CORS blocking the response.

    ReplyDelete
  15. Great example app, Jaliya. Finally, someone has posted a WORKING example of what I was trying to accomplish.

    ReplyDelete
  16. Hello - This worked for me except the employee list is not being printed out. I see the employee list in the Chrome console. What am I missing?

    ReplyDelete
  17. To check the Web service, right click on the Web service file and view it on the Browser. You will see the following, as the result. Click on the method GetAllEmployees. After clicking the Invoke button, you will see the employee data in JSON format.

    ReplyDelete