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:
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:
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:
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 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
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:
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:
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:
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:
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 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:
Enough theory. Let us create a simple web service using ASP.NET Web API.
Fire up Visual Studio 2015:
When you click OK, a Web API solution will be created. Just as the ASP.NET Core application controller inherits from the Controller class.
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:
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:
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:
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:
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:
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
:
Right-click on the Models
folder and select Add | New 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:
GetAllEmployees
API method will return all the employees as the IEnumerable
interface.AddEmployee
method will add the employee (passed as a parameter) to the list.GetEmployee
method will return the employee whose ID matches that of the parameter.RemoveEmployee
method will remove the employee from the list.UpdateEmployee
method will update the employee information.GetNextRandomId
method will return the next available random integer. This integer value is being used to generate the employee ID.