Web API Tutorial: How to Create a Simple HTTP Service using Web API

18. April 2017 Web API 0

Introduction

Web API is a framework where you can create Web Services transmitting data over HTTP. In these series of tutorials, we are going to see how to create simple RESTful service with Web API and test it with Postman.

Web API service operations are accessible via a URL like any other URL which we use to browse a website online. Browsing a website is nothing just an HTTP GET request which the content contains the website and interpreted by our browser (let’s say Google Chrome).

I will use Visual Studio 2017 Enterprise and .NET 4.6.2. With a little twist, you can use the older versions of Visual Studio and .NET framework.

Scenario

We are going to use a simple Employee management scenario to develop our services and test it.

Architecture

A simple multi-layer application is considered to develop the service:

  • Entities: contains the data structure used in the system.
  • Business Layer: contains the logics and program flow.
  • Service Layer: contains the service endpoints exposing the Business Layer functionality.

In real word scenarios, we might be having Data Layer to persist data in database which for simplicity I will use an in-memory list.

Normally a client, a web browser for instance, communicating with the API to provides the functionality of the system to the end user. In this tutorial, we are going to use Postman (https://www.getpostman.com/) which is a very handy tool to test our APIs.

Create the solution in Visual Studio

Create an empty solution in Visual Studio

Open Visual Studio, go to File, New, Project. Under Installed, Templates, Other Projects Types, Visual Studio Solutions, select Blank solution and name it EmployeeManagement.

Create Entities Project

Create a class library project to hold the entities. Right click on the newly created solution, Add, New Project, select Class Library and name it EmployeeManagement.Entities.

Remove Class1.cs and add a new class called Employee.cs to the project and modify it as below:

namespace EmployeeManagement.Entities
{
    public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public byte Age { get; set; }
        public DateTime DateOfBirth { get; set; }
    }
}

Entities are normally mapped to a database structure and has a DAC which manipulates its CRUD operations. For the sake of this tutorial we will add a static list and manage the CRUD in the same entity.

Modifies the Employee class as below:

using System;
using System.Collections.Generic;
using System.Linq;

namespace EmployeeManagement.Entities
{
    public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public byte Age { get; set; }
        public DateTime DateOfBirth { get; set; }

        private static List<Employee> _employees;
        private static int _id = 10000;

        static Employee()
        {
            _employees = new List<Employee>();
        }

        public static void Seed()
        {
            _employees.Add(new Employee() { Id = _id++, Name = "Liza", Age = 24, DateOfBirth = new DateTime(1993, 5, 22) });
            _employees.Add(new Employee() { Id = _id++, Name = "Macy", Age = 35, DateOfBirth = new DateTime(1982, 3, 7) });
            _employees.Add(new Employee() { Id = _id++, Name = "Joe", Age = 28, DateOfBirth = new DateTime(1989, 4, 10) });
            _employees.Add(new Employee() { Id = _id++, Name = "Max", Age = 19, DateOfBirth = new DateTime(1998, 11, 15) });
        }

        public static void Add(Employee employee)
        {
            employee.Id = _id++;
            _employees.Add(employee);
        }

        public static Employee Get(int id)
        {
            return _employees.Where(e => e.Id == id).FirstOrDefault();
        }

        public static List<Employee> List()
        {
            return _employees;
        }

        public static void Update(Employee employee)
        {
            var currenctEmployee = _employees.Where(e => e.Id == employee.Id).FirstOrDefault();

            if (currenctEmployee is null)
                return;

            currenctEmployee.Name = employee.Name;
            currenctEmployee.Age = employee.Age;
            currenctEmployee.DateOfBirth = employee.DateOfBirth;
        }

        public static void Delete(int id)
        {
            _employees.RemoveAll(e => e.Id == id);
        }
    }
}

Create Business Layer

Create a class library project to hold the business logics. Right click on the newly created solution, Add, New Project, select Class Library and name it EmployeeManagement.Business.

Add a reference to EmployeeManagmeent.Entities class from EmployeeManagement.Business.

Remove Class1.cs and add a new class called EmployeeBusiness.cs to the project and modify it as below:

using EmployeeManagement.Entities;
using System.Collections.Generic;

namespace EmployeeManagement.Business
{
    public class EmployeeBusiness
    {
        public Employee Create(Employee employee) => Employee.Insert(employee);

        public Employee Get(int id) => Employee.Select(id);

        public IEnumerable<Employee> List() => Employee.List();

        public void Update(Employee employee) => Employee.Update(employee);

        public void Remove(int id) => Employee.Delete(id);
    }
}

The EmployeeBusiness should communicate with a data layer to perform CRUD operations. Here we are simulating the such interaction using our static list of employees.

Create the Service Layer

Create a ASP.NET Web Application project to hold the Web API servives. Right click on the newly created solution, Add, New Project, and select ASP.NET Web Application and name it EmployeeManagement.Service.

In template selection choose Empty, and select Web API under Add folder and code references for.

Add references to the Entities and Business projects from the Service project:

Add the new Web API controller to the service project by right clicking on the Controller folder, Add, Controller, and select Web API 2 Controller – Empty. Name it EmployeeController.

HTTP Verbs

We need to add 5 service operations to our service which do the CRUD operation by communicating to the Business Layer. HTTP uses different verbs which each determines the characteristic of the HTTP message set from client to the service. The most famous one to use are:

  • POST: use to create a resource
  • GET: use to retrieve a resource
  • PUT: use to update a resource
  • DELETE: use to remove a resource

Each service operations need to decorate with what verbs it uses.

Route Prefixes

Route prefixes are used to define the relative URL were a specific service operation is accessible. Web API can automatically map the request to the name of the controller. But in this example, we will specify the route prefix ourselves.

We use RoutePrefixAttribute to specify the relative URL on how the operation is accessible:

[RoutePrefix("api/employee")]
public class EmployeeController : ApiController
{
}

So, this service will be accessible through: http://localhost/api/employee/[opration].

Map Routes to the HTTP Verbs

The best practice in service method naming is we use a unify name, only the verb is telling what that method is doing. For example, to create an employee our route will be api/employee with POST verb, and the route to get an Employee is api/employee/{id} with GET verb and the employee id as the parameter. Below is the of routes and corresponding verbs in our service:

  • [POST] api/employee: creates new employee
  • [GET] api/employee/{id}: gets an employee by id
  • [GET] api/employee: gets the list of all employees
  • [PUT] api/employee: updates and employee
  • [DELETE] api/employee/{id}: deletes an employee by id

Implementing Service Methods

Below is a service operation which is going to create an employee:

[Route("")]
[HttpPost]
public HttpResponseMessage Create(Employee employee)
{
    try
    {
        var bc = new EmployeeBusiness();
        var result = bc.Create(employee);

        return Request.CreateResponse(HttpStatusCode.Created, result);
    }
    catch (Exception ex)
    {
        return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
    }
} 

The RouteAttribute specified on each method are the relative url from the RoutePrefix. When specifying RouteAttribute Web API use it rather than the method name, so the method name can be anything.

Each method returns the HttpResponseMessage with creates an HTTP response message with a status code and body content.

Request.CreateResponse creates a response with a status code and result. HTTP Status Codes returns the result of the operation, whether it is successful or not, or many other messages related to how the operation processed by the server and its result.

Full implementation of all methods is as below:

using EmployeeManagement.Business;
using EmployeeManagement.Entities;
using System;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace EmployeeManagement.Service.Controllers
{
    [RoutePrefix("api/employee")]
    public class EmployeeController : ApiController
    {
        [Route("")]
        [HttpPost]
        public HttpResponseMessage Create(Employee employee)
        {
            try
            {
                var bc = new EmployeeBusiness();
                var result = bc.Create(employee);

                return Request.CreateResponse(HttpStatusCode.Created, result);
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
        }

        [Route("{id}")]
        [HttpGet]
        public HttpResponseMessage Get(int id)
        {
            try
            {
                var bc = new EmployeeBusiness();
                var result = bc.Get(id);

                return Request.CreateResponse(HttpStatusCode.OK, result);
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
        }

        [Route("")]
        [HttpGet]
        public HttpResponseMessage List()
        {
            try
            {
                var bc = new EmployeeBusiness();
                var result = bc.List();

                return Request.CreateResponse(HttpStatusCode.OK, result);
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
        }

        [Route("")]
        [HttpPut]
        public HttpResponseMessage List(Employee employee)
        {
            try
            {
                var bc = new EmployeeBusiness();
                bc.Update(employee);

                return Request.CreateResponse(HttpStatusCode.Accepted);
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
        }

        [Route("{id}")]
        [HttpDelete]
        public HttpResponseMessage Remove(int id)
        {
            try
            {
                var bc = new EmployeeBusiness();
                bc.Remove(id);

                return Request.CreateResponse(HttpStatusCode.Accepted);
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
        }
    }
}

Take note of the HTTP Verbs for each method.

Testing the Service

Set the EmployeeManagement.Service as the starting project and run the solution.

I will use Postman to test the service. Run the Postman.

Get a list of employees

URL (GET): http://localhost:22303/api/employee

Result: 200 (OK)

Get an employee by id

URL (GET): http://localhost:22303/api/employee/10000

Result: 200 (OK)

Create an employee

URL (POST): http://localhost:22303/api/employee

Result: 201 (Created)

Note that the Verb for creating an employee is POST. In POST we need to pass the content, Employee in this case, in its body (as JSON). The result is the newly created Employee.

Update an employee

URL (PUT): http://localhost:22303/api/employee

Result: 202 (Accepted)

In this case the there is no result body, only the status code 202 which states the request is Accepted. You can use the Get endpoint with id 10004 to see the changes.

Remove an employee

URL (DELETE): http://localhost:22303/api/employee/10004

Result: 202 (Accepted)

Note that in all cases out URL hasn’t changed, only the HTTP Verb and whether we need to pass id.

Download

Download the sample code


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.