Book Image

ASP.NET Core: Cloud-ready, Enterprise Web Application Development

By : Mugilan T. S. Ragupathi, Valerio De Sanctis, James Singleton
Book Image

ASP.NET Core: Cloud-ready, Enterprise Web Application Development

By: Mugilan T. S. Ragupathi, Valerio De Sanctis, James Singleton

Overview of this book

ASP.NET Core is the new, open source, and cross-platform, web-application framework from Microsoft. ASP.NET Core MVC helps you build robust web applications using the Model-View-Controller design. This guide will help you in building applications that can be deployed on non-Windows platforms such as Linux. Starting with an overview of the MVC pattern, you will quickly dive into the aspects that you need to know to get started with ASP.NET. You will learn about the core architecture of model, view, and control. Integrating your application with Bootstrap, validating user input, interacting with databases, and deploying your application are some of the things that you will learn to execute with this fast-paced guide. You will test your knowledge as you build a fully working sample application using the skills you’ve learned throughout the book. Moving forward, this guide will teach you to combine the impressive capabilities of ASP.NET Core and Angular 2. Not only will you learn how Angular 2 can complement your .NET skills and toolkit, you'll also learn everything you need to build a complete, dynamic single-page application. Find out how to get your data model in place and manage an API, before styling and designing your frontend for an exceptional user experience. You will find out how to optimize your application for SEO, identify and secure vulnerabilities, and how to successfully deploy and maintain your application. From here, you will delve into the latest frameworks and software design patterns to improve your application performance. The course offers premium, highly practical content on the recently released ASP.NET Core, and includes material from the following Packt books: Learning ASP.NET Core MVC Programming, ASP.NET Core and Angular 2, and ASP.NET Core 1.0 High Performance.
Table of Contents (5 chapters)

Chapter 10. Building HTTP-based Web Services Using ASP.NET Web API

So far, we have learned how to create web applications using ASP.NET Core. But there are times when simply creating a web application is not enough. Let's assume you are using ASP.NET Core to create a web application that provides weather information for all the cities across the world. People access your web application to find out weather information, and they are satisfied with the service. But this weather information may be needed by many other websites or web applications, such as tourism websites, news websites, and many other mobile applications.

Instead of writing the code all over again for their websites, you can create and publish the web services and the websites can consume the required web services whenever they need to.

In this chapter, you are going to learn about the following topics:

  • What an HTTP-based service is and how it is useful
  • What Fiddler is
  • How to compose an HTTP request using Fiddler and fire the same in order to get an HTTP response
  • How to design and implement the HTTP service using Web API

Microsoft provides ASP.NET Web API for programmers to build HTTP-based services. But HTTP is not just used to serve the webpages. You can use HTTP as a platform. This brings several advantages:

  • As web services built using ASP.NET Web API use HTTP for communication, these web services can be consumed from all kinds of applications from console applications to web applications, and from WCF services to mobile applications
  • Whenever there is any change in the logic/code of the web services, the clients (the websites that consume the services) do not need to change anything. They can consume the web services just as they were consuming them earlier

HTTP basics

HTTP is a powerful platform for building services. You can use the existing HTTP verbs to build services. For example, you can use the existing HTTP verb GET to get the list of products or POST to update information about the product. Let's take a quick look at how HTTP works with respect to building the services.

There is no difference in the underlying mechanism between serving the HTML pages in ASP.NET MVC and serving the data in the context of HTTP services. Both follow a request-response pattern and the same routing mechanism.

An HTTP request can be sent from any client (desktop, laptop, tablet, mobile, and so on) to the server and the server will respond back with an HTTP response. An HTTP response can be sent to the client in any format such as JSON or XML. This is shown in the following figure:

HTTP basics

In the preceding diagram, a request is sent from the desktop computer (it could equally be sent from a mobile or tablet; it makes no difference) and the server sends back the HTTP response for the request. As HTTP is supported in most of the devices, it is ubiquitous.

HTTP verbs

HTTP verbs describe how the request has to be sent. These are the methods defined in HTTP that dictate how the HTTP requests are sent from the client to the server

GET method

When we use an HTTP GET request, the information is passed through the URL itself:

GET api/employees/{id} 

This GET request gets the employee information based on the passed ID. The advantage of using the GET request is that it is lightweight, and all the required information will be passed in the URL or header itself, as shown in the following diagram:

GET method

PUT method

The PUT method is used to create a resource or to update it. PUT is an idempotent operation, meaning that the expected behavior would not change even if it is executed multiple times:

PUT method

POST method

You can use POST to create or update the resource. Usually, POST is used to create the resource rather than update it. As per HTTP standards, whenever you create a new resource, you should return a 201 HTTP status code:

POST method

DELETE method

The DELETE method is used to delete the resource. Usually, when you delete a resource, you would be passing the ID as a parameter, and you would not be passing anything in the body of the request:

DELETE method

Usually, HTTP services would be consumed by other applications and services. Applications that consume services are referred to as clients. One of the options to test HTTP services is to build the clients. But this would be time-consuming, and we may throw away the client code once we test the HTTP services.

Another option, which is widely used, is to use applications that enable us to fire HTTP requests and monitor the responses. There are many applications available, Fiddler being one such widely used application.

Fiddler tool

Fiddler is the proxy server application used to monitor the HTTP and HTTPS traffic. You can monitor the requests that are being sent to the server from the client, the responses that are sent to the client, and the responses that are being received from the server. It is like seeing the traffic in the pipe between the server and the client. You can even compose a request, fire it, and analyze the response received without ever needing to write the client for the services.

You can download Fiddler at http://www.telerik.com/fiddler. You'll see the following window:

Fiddler tool

Enough theory. Let us create a simple web service using ASP.NET Web API.

Fire up Visual Studio 2015:

Fiddler tool

When you click OK, a Web API solution will be created. Just as the ASP.NET Core application controller inherits from the Controller class.

Fiddler tool

The Web API class will also inherit from the same Controller class. This is the difference between ASP.NET Core and earlier versions of ASP.NET MVC. In earlier versions, all Web API controller classes inherited from the ApiController class. In ASP.NET 5, it has been unified, and the same base Controller class is being used for both building web applications and services.

The following is the ValuesController class that will be created by default when you choose the Web API template option when creating the project:

Fiddler tool

Before we create our own custom Controller, let's analyze the default API Controller. In the ValuesController file, several API methods are already defined.

There are two overloaded GET methods—one with a parameter and another without a parameter. The GET method without a parameter returns all the resources of the type. In this case, we are returning just a couple of strings. In the real world, we would be returning the metadata of the resources. For example, if we fire the GET request on the movies API Controller, it would return information about all the movies. The GET method with an id parameter returns the resource whose ID matches with the passed ID. For example, if you pass a movie ID, it would return the information about that movie. The body of the other methods, such as PUT, POST, and DELETE, are empty in this Controller, and we will talk about these methods later.

When you run the application, you will get the following output:

Fiddler tool

By default, it fires a request to api/values, and the values are displayed in the browser.

Let's learn how to fire an HTTP request from the Fiddler application. Open the Fiddler application. In the bottom left-hand corner, select the Web Browsers option in the red box. Choosing this option will enable us to view the traffic coming from the Web Browsers:

Fiddler tool

Select the Composer tab, enter the URL http://localhost:49933/api/values, as shown in the following screenshot, and click the Execute button in the top right-hand corner:

Fiddler tool

Once you click the Execute button, an HTTP session will be created, visible on the left-hand side pane (highlighted in the blue box). Click on the session and select the Inspectors tab on the top right-hand side pane. Select the JSON tab in the bottom right-hand side pane (highlighted by the purple-bordered box in the following screenshot).

You can see the JSON data returned from the HTTP request—value1 and value2 in the following screenshot:

Fiddler tool

Now it's our turn to write a custom API.

In this custom API, we are going to provide API methods to create an employee object, list all the employee objects, and delete an employee object.

First, let us create a model for the employee. We need to create a folder to hold these models. Right-click on the project, select Add | New folder, and name the folder as Models:

Fiddler tool

Right-click on the Models folder and select AddNew Item… to create an employee model class. This employee model class is just a POCO class. See the following code:

public class Employee
{
  public int Id {get; set;}
  public string FirstName {get; set;}
  public string LastName {get; set;}
  public string Department {get; set;}
}

Then, we define the repository interface to handle the model:

public interface IEmployeeRepository
{
  void AddEmployee(Employee e);
  IEnumerable<Employee> GetAllEmployees();
  Employee GetEmployee(int id);
  Employee RemoveEmployee(int id);
  void UpdateEmployee(Employee employee);
}

Then we implement the interface for this model:

public class EmployeeRepository : IEmployeeRepository
{
  private static List<Employee> employees = new List<Employee>();

  public EmployeeRepository()
  {

    Employee employee1 = new Employee
    {
      FirstName = "Mugil",
      LastName = "Ragu",
      Department = "Finance",
      Id = 1
    };

   Employee employee2 = new Employee
   {
      FirstName = "John",
      LastName = "Skeet",
      Department = "IT",
      Id = 2
   };

  employees.Add(employee1);
  employees.Add(employee2);
  }

  public IEnumerable<Employee> GetAllEmployees()
  {
    return employees;
  }

  public void AddEmployee(Employee e)
  {
    e.Id = GetNextRandomId();
    employees.Add(e);
  }

  public Employee GetEmployee(int id)
  {
    return employees.Where(emp => emp.Id == id).FirstOrDefault();
  }

  public Employee RemoveEmployee(int id)
  {
    Employee employee = employees.Where(emp => emp.Id ==   id).FirstOrDefault();
    if (employee !=null )
    {
      employees.Remove(employee);
    }
    return employee;
  }

  public void UpdateEmployee(Employee emp)
  {
    Employee employee = employees.Where(e => e.Id ==  emp.Id).FirstOrDefault();
    if(employee != null)
    {
    employee.Department = emp.Department;
    employee.FirstName = emp.FirstName;
    employee.LastName = emp.LastName;
    }
  }

  private int GetNextRandomId()
  {
    int id = -1;
    bool isIdExists;
    Random random = new Random();
    do
    {
      id = random.Next();
      isIdExists = employees.Any(emp => emp.Id == id);
    } while (isIdExists);
    return id;
  }
}

There are few things to be noted in the implementation class:

  • We have decided not to use the database as our objective is to create an HTTP service using Web API, and not to write the data access code.
  • We are using an in-memory list to hold the data. All the operations will be performed on this list. As a matter of fact, the data could be in any form, ranging from relational databases to a simple in-memory list.
  • In the constructor method, we are adding an object to the list. This list will be acting as the database for our HTTP service.
  • The GetAllEmployees API method will return all the employees as the IEnumerable interface.
  • The AddEmployee method will add the employee (passed as a parameter) to the list.
  • The GetEmployee method will return the employee whose ID matches that of the parameter.
  • The RemoveEmployee method will remove the employee from the list.
  • The UpdateEmployee method will update the employee information.
  • The GetNextRandomId method will return the next available random integer. This integer value is being used to generate the employee ID.

Dependency Injection

In most real-world projects, we do not instantiate any objects using the new instance in any of the Controllers, the reason being that we don't want to have tight coupling between the dependent components (between the Controller and the repository). Instead, we pass an interface to the Controller, and the Dependency Injection container (such as Unity) will create an object for us when it is needed for the Controller. This design pattern is commonly referred to as Inversion of Control.

Let's say that a class by the name of ClassA uses another class, ClassB. In this case, it is enough for ClassA to know about the behavior, methods, and properties of ClassB, and it doesn't need the internal implementation details of ClassB. So, we can abstract ClassB and make an interface out of the class, and then have that interface as the parameter instead of the concrete class. The advantage of this approach is that we can pass any class at runtime as long as it implements a commonly agreed contract (interface).

In ASP.NET 5 (including ASP.NET Core and Web API), we have inbuilt support for Dependency Injection. In the ConfigureServices method, we have added the line (highlighted in bold) that performs the Dependency Injection. We instruct the inbuilt Dependency Injection container to create the EmployeeRepository class wherever we are referring to the IEmployeeRepository interface and we also instruct it to be a singleton; meaning that the same object (which is to be created by the Dependency Injection container) is to be shared for the entire lifecycle of the application:

public void ConfigureServices(IServiceCollection services)
{
  // Add framework services.
  services.AddApplicationInsightsTelemetry(Configuration);
  services.AddMvc();
  services.AddSingleton<IEmployeeRepository, EmployeeRepository>();

}

In the preceding code, we have used the Singleton pattern for the Dependency Injection, which creates services only the first time they are requested. There are other types of lifetime services such as Transient and Scoped. Transient lifetime services are created each time they are requested and Scoped lifetime services are created once per request. The following are code snippets created when you use such lifetimes:

services.AddTransient
  <IEmployeeRepository, EmployeeRepository>();


services.AddScoped  <
IEmployeeRepository, EmployeeRepository>();

Now it's time to get into the meat of the action creating the API controller. Right-click on the Controllers folder and select Add | New Item. Then select Web API Controller Class from the list, as shown in the following screenshot. Name your Controller, and click the Add button:

Dependency Injection

Remove the generated code in the Controller and add the following constructor:

public EmployeeController(IEmployeeRepository employeesRepo)
{
  employeeRepository = employeesRepo;
}
private IEmployeeRepository employeeRepository {get; set;}

In the preceding constructor, we are injecting the dependency. At the time of calling this constructor, the EmployeeRepository object will be created.

Let us implement a couple of GET methods—the first one will return all the employees' details and the second GET method will return the employee based on the passed employee ID:

public IEnumerable<Employee> GetAll()
{
  return employeeRepository.GetAllEmployees();
}

[HttpGet("{id}",Name ="GetEmployee")]
public IActionResult GetById(int id)
{
  var employee = employeeRepository.GetEmployee(id);
  if(employee == null)
  {
  return NotFound();
  }
  return new ObjectResult(employee);
}

Let us call these HTTP methods from Fiddler.

Run the solution, open the Fiddler application, and click on the Composer tab.

Select the HTTP method (we have chosen the GET method as we have a GET API method) and enter the URL http://localhost:49933/api/employee .

Please note that when I run my application, it runs on port 49933; the port number will be different in your case, so construct your URL accordingly.

Once you enter the URL and the method is selected, click the Execute button as shown in the following screenshot:

Dependency Injection

Once you click the Execute button, an HTTP session will be created, and the request will be fired.

Click on the session on the left-hand side pane (as shown in the following screenshot) and select the Inspectors tab in the right-hand side pane. You can view the result in the JSON tab in the bottom right-hand side pane:

Dependency Injection

Let us fire another HTTP request to get a particular employee's information, say the employee whose ID is 2. We would construct the URL by appending the ID  http://localhost:49933/api/employee/2  as following:

Dependency Injection

Select the recently created HTTP session and click on it:

You can see the result in JSON format in the right-hand side pane.

Now, we are going to add Create, Update, and Delete operations to our service. To start with, we are going to provide the Create functionality to add employees' to our service:

[HttpPost]
public IActionResult Add([FromBody] Employee emp)
{
  if (emp == null)
  {
    return BadRequest();
  }
  employeeRepository.AddEmployee(emp);
  return CreatedAtRoute("GetEmployee", new { id = emp.Id }, emp);
}

The following points should be considered when following the preceding Add method:

  1. We are passing the Employee object as a parameter. We are instructing the Add method to take that object from the body of the request by specifying a [FromBody] attribute:
    • If no employee object is passed, we would be returning the bad request to the calling client
    • If it is not null, we would be calling the repository method to add the employee to our list (in the real world, we would be adding it to the database)
  2. Once we have added the employee, we are returning the 201 status code (as per the HTTP standards) when a new resource is created.

Open the Fiddler application and follow these steps to add the employee:

  1. Select the HTTP method as POST and enter the URL http://localhost:54504/api/employee/.
  2. You need to specify the content type as application/json in the request header. Please see the following screenshot, where we have added Content-Type: application/json to the request header.
  3. As mentioned in the code, we have to pass the employee object in the form of JSON in the body of the request. In the following request, we have formed a JSON that contains the properties of the Employee object with the values in the brackets { "FirstName" : "James", "LastName" : "Anderson","Department" : "IT"}:

    Dependency Injection

Once you have composed the request, you can click the Execute button to fire the request. This will return the 201 HTTP status code, which is the standard HTTP response for creating a new resource:

Dependency Injection

As soon as we have created the resource in the server, we are redirecting the response to get the newly created resource. This occurs when we call the CreatedAtRoute method with the newly created employee ID passed as a parameter.

Click on the session on the left-hand side and select the Inspector tab in the right-hand side pane. Now you can see the response of the request. The response contains the Employee object which was newly created in the server. We have to note that the ID of the Employee object is generated at the server, and is available in the following response. In this case, the ID generated for the employee is 1771082655:

Dependency Injection

In the bottom right-hand side panel in the preceding Fiddler window, we can see the complete JSON response of the newly created resource.

Now we are going to add a Web API method to update the resource. The method for updating the resource is very similar to that used to create the resource, with only a few differences. When we created the resource, we used the HTTP POST method, whereas when we updated the resource, we used the HTTP PUT method.

If the passed employee ID could not be found in the repository, we return a 404 error response, the HTTP standard error response for a resource that has not been found.

The following is the Web API controller method code for updating the resource:

[HttpPut]
public IActionResult Update([FromBody] Employee emp)
{
  if( emp == null)
  {
    return BadRequest();
  }
  Employee employee = employeeRepository.GetEmployee(emp.Id);
  if(employee == null)
  {
    return NotFound();
  }
  employeeRepository.UpdateEmployee(emp);
  return new NoContentResult();
}

The following is the repository layer code for updating the employee:

public void UpdateEmployee(Employee emp)
{
  Employee employee = employees.Where(e => e.Id == emp.Id).FirstOrDefault();
  if (employee != null)
  {
    employee.Department = emp.Department;
    employee.FirstName = emp.FirstName;
    employee.LastName = emp.LastName;
  }
}

Open the Fiddler application, and compose a request of HTTP PUT. As we are going to pass the Employee object in the body of the request, we need to mention the content type as application/json. In the body of the request, we need to supply the Employee object in JSON format, as shown in the following screenshot:

Dependency Injection

When you click the Execute button, the HTTP PUT request will be fired and our Web API method will get called. Once it succeeds, the HTTP 204 response will be returned:

Dependency Injection

Delete method

The HTTP DELETE method should be used when deleting a resource. There is no need to pass anything in the body of the request.

The Web API method for deleting a resource

The Delete Web API method has a void return type, which will return an HTTP 200 response:

[HttpDelete("{id}")]
public void Delete(int id)
{
  employeeRepository.RemoveEmployee(id);
}

Web Repository layer code for deleting the employee data

In the following repository layer method, we are removing the employee (whose ID matches with that of the parameter passed) from the internal list of employees. But in the real world, we would be interacting with the database to delete that particular employee. Consider the following code:

public Employee RemoveEmployee(int id)
{
  Employee employee = employees.Where(emp => emp.Id ==   id).FirstOrDefault();
  if(employee != null)
  {
    employees.Remove(employee);
  }
  return employee;
}

Open the Fiddler application, select the DELETE HTTP method, pass the URL with the parameter, and click on the Execute button. Please note that we are not passing the content type in the request header as we are not passing any employee object in the body of the request:

Web Repository layer code for deleting the employee data

As we are returning void, the Web API DELETE method returns an HTTP 200 status, as you can see in the left-hand side pane of the Fiddler application:

Web Repository layer code for deleting the employee data

Delete method

The HTTP DELETE method should be used when deleting a resource. There is no need to pass anything in the body of the request.

The Web API method for deleting a resource

The Delete Web API method has a void return type, which will return an HTTP 200 response:

[HttpDelete("{id}")]
public void Delete(int id)
{
  employeeRepository.RemoveEmployee(id);
}

Web Repository layer code for deleting the employee data

In the following repository layer method, we are removing the employee (whose ID matches with that of the parameter passed) from the internal list of employees. But in the real world, we would be interacting with the database to delete that particular employee. Consider the following code:

public Employee RemoveEmployee(int id)
{
  Employee employee = employees.Where(emp => emp.Id ==   id).FirstOrDefault();
  if(employee != null)
  {
    employees.Remove(employee);
  }
  return employee;
}

Open the Fiddler application, select the DELETE HTTP method, pass the URL with the parameter, and click on the Execute button. Please note that we are not passing the content type in the request header as we are not passing any employee object in the body of the request:

Web Repository layer code for deleting the employee data

As we are returning void, the Web API DELETE method returns an HTTP 200 status, as you can see in the left-hand side pane of the Fiddler application:

Web Repository layer code for deleting the employee data

The Web API method for deleting a resource

The Delete Web API method has a void return type, which will return an HTTP 200 response:

[HttpDelete("{id}")]
public void Delete(int id)
{
  employeeRepository.RemoveEmployee(id);
}

Web Repository layer code for deleting the employee data

In the following repository layer method, we are removing the employee (whose ID matches with that of the parameter passed) from the internal list of employees. But in the real world, we would be interacting with the database to delete that particular employee. Consider the following code:

public Employee RemoveEmployee(int id)
{
  Employee employee = employees.Where(emp => emp.Id ==   id).FirstOrDefault();
  if(employee != null)
  {
    employees.Remove(employee);
  }
  return employee;
}

Open the Fiddler application, select the DELETE HTTP method, pass the URL with the parameter, and click on the Execute button. Please note that we are not passing the content type in the request header as we are not passing any employee object in the body of the request:

Web Repository layer code for deleting the employee data

As we are returning void, the Web API DELETE method returns an HTTP 200 status, as you can see in the left-hand side pane of the Fiddler application:

Web Repository layer code for deleting the employee data

Web Repository layer code for deleting the employee data

In the following repository layer method, we are removing the employee (whose ID matches with that of the parameter passed) from the internal list of employees. But in the real world, we would be interacting with the database to delete that particular employee. Consider the following code:

public Employee RemoveEmployee(int id)
{
  Employee employee = employees.Where(emp => emp.Id ==   id).FirstOrDefault();
  if(employee != null)
  {
    employees.Remove(employee);
  }
  return employee;
}

Open the Fiddler application, select the DELETE HTTP method, pass the URL with the parameter, and click on the Execute button. Please note that we are not passing the content type in the request header as we are not passing any employee object in the body of the request:

Web Repository layer code for deleting the employee data

As we are returning void, the Web API DELETE method returns an HTTP 200 status, as you can see in the left-hand side pane of the Fiddler application:

Web Repository layer code for deleting the employee data

Summary

In this chapter, you learned about the HTTP service and its purpose. We discussed how to design and implement the HTTP service using Web API. We used the Fiddler tool to construct the HTTP request and get the response back. We also learned how to write the Web API method to perform CRUD operations end to end, from writing the Web API methods to firing the requests and getting the responses back.