Getting Started
Modern web development demands interaction with servers without any hassle. What this means is that with the evolution of different UI and backend frameworks, developers need to find a way of sharing data with any available framework without any dependencies. This means there should be a way of sharing data from the server with clients, irrespective of their language and framework. To bring a uniformity to sharing data, the first thing that comes to mind is .xml and .json. These formats are supported by every framework.
In this chapter, we will look at an architectural style by which we can get or send data from any program written in any language using any framework. With REST, the architecture we will be discussing, we can bring in methods that can be easily consumed by clients for data operations.
This chapter will cover the following topics:
- RESTful services
- Why should we use RESTful services? The difference between RESTful and RESTless services
- Client-server architecture
- ASP.NET Core and RESTful services
Discussing RESTful services
REST stands for representational state transfer. It is an architectural style that defines a set of guidelines for building web services.
What is an architectural style? It's nothing but a concept with predefined principles. We will talk about these principles in a moment. When you follow REST, you are actually implementing the principles that are the building blocks of REST in your application.
However, the implementation of REST will definitely differ from developer to developer. There is no fixed implementation style. Don't get confused with architectural patterns, which are not concepts but the actual implementations. MVC is an architectural pattern as it has a fixed structure that defines how the components interact with each other where they can't be differently implemented.
The following is a very simple diagram of a REST-based service:

To simplify things, consider the preceding diagram, which shows you a service that has certain methods, such as GET, POST, PUT, and DELETE. That is what this style is all about. When you design your service, which will have all these methods—with the intended operations inside them—we can consider it as a REST-based service, otherwise known as a RESTful service. More importantly, the service can be called from an application built in any platform and language as the service has a standard architecture.
As discussed, a RESTful service is a service that supports REST. Let's talk about the characteristics of REST so that we can understand what is expected from a service that is RESTful.
REST characteristics
The main building blocks of web services are the client and server architectures. The response sent from the server is actually a reply to the client's request. It's like you are asking a question and the server responds if it finds the answer. The response that comes from the server is actually a resource in a certain format or representation. The formats that are usually seen are .json, .xml, .pdf, .doc, and so on.
REST is stateless. Stateless means that the state of the system is always different. So, when a request comes to the server, it is served and forgotten. Thus, the next request does not depend on the state of the previous one. Each request is handled by the server independently.
The requests are performed in an HTTP connection. They each take the form of a uniform resource identifier (URI). This identifier helps us to locate the required resource on the web server.
Roy Fielding’s PhD dissertation, entitled Architectural Styles and the Design of Network-Based Software Architectures, defined REST. The following are some key points extracted from his research:
- Like many distributed architectures, REST imposes layers, statelessness, and caching.
- REST improves efficiency, interoperability, and overall performance.
- REST introduces uniformity by following a set of rules on how to identify and manipulate resources, along with the process to simplify the description about its operations through metadata so that the messages passed will be self-explanatory. We will talk more about this uniformity, which is called the uniform interface.
- As REST is an architectural style, a service can be developed using any language or platform as long as it supports HTTP.
Resource-oriented architecture
Every resource on the web has been given a unique identifier, otherwise known as a URI. The uniform resource locator (URL) is the most common type of URI used on the web today. The URL https://www.packtpub.com/ identifies and locates the Packt Publishing site.
Let's look at a quick picture of the architecture. In the following diagram, a client is trying to access a resource through an identifier (URL). The resource is present on the server and has a representation that can be returned to the client when requested:

As the name suggests, the URL is something that is tied to only one resource; therefore, if I want to point someone to one resource, I can easily share that identifier in email, chat, and so on.
These identifiers can by easily remembered if they are named with company or resource names. The best example is www.google.com, which is very easy to remember as the name Google is present. Therefore, we can spread the resource link by word of mouth and you can enter it into a web browser, such as Chrome or Firefox, within seconds.
You might find hyperlinks on a particular web page that link to another website for another resource. That means that resources are now interconnected because of the hyperlinks.
These interconnected resources form the resource-oriented architecture. Hyperlinks make it easy to navigate from one resource to another by using the target resource URI.
<a href="https://www.packtpub.com/tech/Internet%20of%20
Things">Packt IoT Books</a>
By default, the anchor element is rendered as an underlined text. When you hover over it, you can see the attached URI at the bottom, as shown in the following screenshot:

You can click on the anchor text (Packt IoT Books), which then fires a GET request for the target resource URI.
Note that the moment you click the hyperlink, you will land on a web page that is actually a representation of a resource. The most common representation you will encounter is in HTML format. Some other common formats are (X)HTML, JPEG, GIF, WMV, SWF, RSS, ATOM, CSS, JavaScript/JSON, and so on. When a browser receives one of these representations, it tries to parse it and then renders it for viewing, if parsing succeeds.
URI
We have talked a lot about resources. They are actually the pages that we see on a particular website. However, resources in HTTP are not just simple files in the form of HTML web pages. Generally, a resource is defined as any piece of information that can be uniquely identified by a URI, such as http://packtpub.com/.
Let's talk about URIs for a moment. A URI consists of a few components: a URI scheme name, such as http or ftp is the first part, followed by a colon character. After the colon character comes the hierarchical part:
<scheme name> : <hierarchical part> [ ? <query> ] [ # <fragment> ]
Let's analyze one URI:
https://www.flipkart.com/men/tshirts/pr?sid=2oq%2Cs9b%2Cj9y
Let's break down the preceding URI:
- The scheme name is https.
- The scheme name is followed by the hierarchical part, //www.flipkart.com/men/tshirts/pr. The hierarchical part starts with //.
- The hierarchical part also contains an optional query, which is sid=2oq%2Cs9b%2Cj9y, in this case.
The following is an example of a URI containing the optional fragment part:
https://en.wikipedia.org/wiki/Packt#PacktLib
REST constraints
REST is defined by six constraints, as shown in the following diagram. One of them is optional:

Each of these constraints enforce a design decision for the service that is to be followed. If it is not followed, the service can't be denoted as RESTful. Let's discuss these constraints one by one.
Client-server architecture
The client or the consumer of the service should not worry about how the server processes the data and stores it in the database. Similarly, the server does not need to depend on the client's implementation, especially the UI.
Think of an internet of things device or sensor that doesn't have much of a UI. However, it interacts with the server to store data using APIs, which are programmed to be fired on specific events. Suppose you are using an IoT device that alerts you when your car runs out of petrol. At the time of a petrol shortage detection by the sensor in the IoT device, it calls the configured API, which then finally sends an alert to the owner.
What that means is that the client and server are not one entity and each can live without the other. They can be designed and evolved independently. Now you might ask, How can a client work without knowing about the server's architecture, and vice versa? Well, that is what these constraints are meant for. The service, when interacted with by the clients, provides enough information about its nature: how to consume it, and what operations you can carry out using it.
As we go ahead in this section, you will realize that there is absolutely no relation between the client and the server, and they can be completely decoupled if they adhere to all these constraints perfectly.
Stateless
The term stateless means that the state in which the application remains for a particular time may not persist to the next moment. A RESTful service does not maintain the application's state, and thus it is stateless.
A request in a RESTful service does not depend on a past request. The service treats each request independently. On the other hand, a stateful service needs to record the application's current state when the request is performed so that it can act as required for the next request.
Moreover, because of an absence of these complications, stateless services become very easy to host. As we need not worry about the state of the application, it becomes easy to implement, and maintenance becomes smooth.
Caching
To avoid generating the same data with every request, there is a technique called caching that is used to store the data either on the client's or the server's side. This cached data may be used for further reference whenever it is required.
When using caching, it is important that you manage it properly. The reason for this is simple. We are storing data that won't be replaced by fresh data from the server. While this is an advantage that increases the performance of the service, at the same time, if we are not careful as to what to cache and configure during its lifetime, we might end up seeing outdated data. For example, suppose we are showing the live price of gold on our website and we cached this figure. The next time the price changes, it won't be reflected unless we expire the cache that was previously stored.
Let's look at the different kinds of HTTP headers and how to configure caches:
Header |
Application |
Date |
Date and time of the generation of the representation. |
Last modified |
Date and time when this representation was last modified by the server. |
Cache-control |
The HTTP 1.1 header used to control caching. We will look at this in more detail after this table. |
Expires |
This header helps to tag an expiration date and time for this representation. |
Age |
Denotes the time in seconds since the representation was fetched from the server. |
The configuration of the preceding five headers depends upon the nature of the service. Take the example of the service that provides the live price of gold—ideally, it would have the cache age limit as low as possible, or even have caching turned off, because users should see the latest results every time they refer to the site.
However, a site that contains many images would hardly change or update them. In that case, the cache can be configured to store them for a longer duration.
These header values are consulted in accordance with the cache-control header to check whether the cached results are still valid or not.
The following are the most common values for the cache-control header:
Directive |
Application |
Public |
This is the default directive. This allows every component to cache the representation. |
Private |
Only the client or server can cache the representation. However, intermediary components are restricted. |
no-cache/no-store |
With this value, we can turn off caching. |
max-age |
This value is the time in seconds after the date and time is mentioned in the Date header, which denotes the validity of the representation. |
s-maxage |
This does the same as max-age, but only targets intermediary caching. |
must-revalidate |
This states that the representation must be revalidated if the max-age has passed. |
proxy-validate |
This does the same as max-revalidate, but only targets intermediary caching. |
Code on demand (optional)
As the phrase code on demand suggests, the service may try to execute code on the client to extend the functionality. However, this is optional, and not every service does this.
Consider an example of a web application that calls a ticketing service to fetch all the available tickets. The service wants always to show this information in an alert. In order to do this, the service can return a JavaScript code along with the data, which has an alert message with the number of available tickets. Thus, as soon as the client receives the response from the service, an alert is executed and the data is shown.
Uniform interface
When we encounter the word interface, the first thing that comes to our mind is decoupling. We create interfaces to have loosely coupled architecture, and the same type of architecture is seen in the case of RESTful.
While implementing REST, we use the same concept to decouple the client from the implementation of the REST service. However, to implement such a decoupling between the client and the service, standards are defined that every RESTful service supports.
Note the word standard in the preceding line. We have so many services in the world and, obviously, the consumers outnumber the services. As a result, we have to follow some rules while designing the services because every client should understand the service easily without any hassle.
REST is defined by four interface constraints:
- Identification of resources: A URI is used to identify a resource. The resource is a web document.
- Manipulation of resources through representations: When a client has a given resource—along with any metadata—they should have enough information to either modify or delete the resource. So, for example, GET means that you want to retrieve data about the URI-identified resource. You can describe an operation with an HTTP method and a URI.
- Self-descriptive messages: The messages passed should contain enough information about the data to be understood and processed for further operations. MIME types are used for this purpose.
- Hypermedia as the engine of the application state (HATEOAS): The representation returned from the service should contain all the future actions as links. It is the same as visiting a website in which you find different hyperlinks providing you with the different types of available operations.
HTTP 1.1 provides a set of methods, called verbs. Implementing these verbs in our services would mark them as standardized. The important verbs are as follows:
Method |
Operation Performed on Server |
Method Type |
GET |
Read/retrieve a resource. |
Safe |
PUT |
Either insert a new resource or update the resource if it already exists. |
Idempotent |
POST |
Insert a new resource. Can be used to update an existing resource as well. |
Nonidempotent |
DELETE |
Delete a resource . |
Idempotent |
OPTIONS |
Get a list of all the allowed operations for a resource. |
Safe |
HEAD |
Return only the response headers with no response body. |
Safe |
The preceding table is quite self-explanatory, except the Method Type column. Let me clarify this.
A safe operation when performed on the service does not have any effect on the original value of the resource. As the GET, OPTIONS, and HEAD verbs only retrieve or read the resource-related stuff and does not update that, they are safe.
An idempotent (can be repeated) operation when performed gives the same result no matter how many times we perform it. For example, when you make a DELETE or PUT operation, you are actually operating on a particular resource, and the operation can be repeated with no issues.
More explanation
Among all the available methods, GET is the most popular one, as it is used to fetch the resource.
The HEAD method will only return the response headers with an empty body. This is mostly only required when we don't need the whole representation of the resource.
The OPTIONS method is used to get a list of the allowed or available operations on the resource.
Consider the following request:
OPTIONS http://packtservice.com/Authors/1 HTTP/1.1 HOST: packtservice
If the request is authorized and authenticated, it might return something like the following:
200 OK Allow: HEAD, GET, PUT
The response is actually saying that the service can be called using only all these methods.
Make sure you use the HTTP methods according to their specification. If you design the service to allow GET, but perform a delete operation inside that, then clients will get confused. As they try to GET something, it will actually delete the resource, which is weird.
The following is a request that is made with GET, but it actually deletes the resource inside the server (just imagine):
GET http://packtservice.com/DeleteAuthor/1 HTTP/1.1 HOST: packtservice
The preceding request might work and delete the resource, but this is not regarded as a RESTful design. The recommended operation would be to use DELETE method to delete a resource like the following:
DELETE http://packtservice.com/Authors/1 HTTP/1.1 HOST: packtservice
POST versus PUT explained
The use of POST and PUT can be summarized in the following two points:
- PUT is idempotent—it can be repeated, and yields the same result every time. If the resource does not exist, it will create it; otherwise, it will update it.
- POST is nonidempotent—multiple resources will be created if it is called more than once.
The preceding contrast between these verbs is just a general difference. However, there is a very important and significant difference. When using PUT, specifying the complete URI of the resource is necessary. Otherwise, it won't work. For example, the following won't work as it does not specify the exact URI of the author, which can be done by specifying an ID:
PUT http://packtservice.com/Authors/
To fix this, you can send an ID with this URI using something like the following:
PUT http://packtservice.com/Authors/19
created/updated.
This means that the author with the ID 19 will be processed, but if that does not exist, it will be created first. Subsequent requests with this URI will be considered as requests to modify the author resource with an ID of 19.
On the other hand, if we do the same with a POST request like the following, it will create a new author resource with the posted data:
POST http://packtservice.com/Authors/
Interestingly, if you repeat this, you will be responsible for duplicate records with the same data. That is why it is nonidempotent in nature.
Note the following request with POST with an ID. Unlike PUT, POST won't consider this for a new resource, if that is does not exist. It will always be treated as an update request:
POST http://packtservice.com/Authors/19
updated.
The following are the main points to focus on in this section:
- PUT creates or updates one resource, as long as you are calling the same URI
- PUT and POST behave the same, if the resource already exists
- POST, without an ID, will create a resource each time it is fired
Layered system
Most modern applications are designed using multiple layers, and the same is expected from a RESTful service. In a layered system, each layer is restricted to only seeing or knowing the next layer in the hierarchy.
Having a layered architecture helps improve the code's readability, hides complexities, and improves the code's maintainability. Imagine that you have one layer and everything takes place in it, from authentication to database operations. This is absolutely not recommended, as the primary components, such as authentications, business logic, and database operations, are not separated out.
Thus, this constraint is expected from a RESTful service, and no client can actually say that it is connected to the final layer.
Advantages and disadvantages of RESTful services
The following are some advantages and disadvantages of RESTful services:
Advantages
The advantages of using RESTful services are as follows:
- No dependency on a platform or any programming language
- Standardized methods through HTTP
- It doesn't store the state of the clients on the server
- Supports caching
- Accessible to any type of client, such as mobile, web, or desktop
Disadvantages
While there are advantages, there must be some cons. Let's look at some disadvantages of RESTful services:
- If the standards are not followed correctly, they are difficult for clients to understand
- Documentation becomes problematic as no such metadata is provided
- Security is a concern, if no such process is followed to restrict the access of resources
ASP.NET Core and RESTful services
.NET Core is defined as a cross-platform, open-source, cloud-ready, and modular .NET platform for creating modern web apps, microservices, libraries, and console applications that run everywhere (Windows, Linux, and macOS).
ASP.NET Core is a free and open-source web framework, and the next generation of ASP.NET. It is a modular framework consisting of small packages of framework components that run on both the full .NET Framework, Windows, and the cross-platform .NET Core.
The framework is a complete rewrite from the ground up. It unites the previously separate ASP.NET MVC and ASP.NET Web API into a single programming model.
ASP.NET Web API has been built to map the web/HTTP programming model to the .NET Framework programming model. It uses familiar constructs, such as Controller, Action, Filter, and so on, which are used in ASP.NET MVC.
ASP.NET Web API is designed on top of the ASP.NET MVC runtime, along with some components that simplify HTTP programming. We can leverage Web API technology to perform actions on the server with .NET Framework; however, to be RESTful, we should adhere to the standards that we discussed earlier in this chapter. Fortunately, Web API automatically manages all the low-level transport details of HTTP while maintaining all the required constraints.
Because of the uniformity that Web API provides, enforcing the RESTful principles, clients such as mobiles, web applications, the cloud, and so on can easily access it without any problem:

Prior to ASP.NET Core, MVC and Web API were different as they inherited Controller and ApiController classes respectively. On the other hand, in ASP.NET Core, they follow the same structure.
The following is the Solution Explorer view of both MVC and Web API. You can see that they have a similar structure:

The following is a controller that was automatically created when I clicked on File | New | Project | ASP.NET Core Web Application | Web API. You can see the base class of the controller is Controller instead of ApiController:
namespace WebAPIExample.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody]string value)
{ }
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody]string value)
{ }
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{ }
}
}
Don't worry about codes now; we will discuss everything later in this book.
Summary
REST defines how to use the uniform interface through additional constraints, how to identify resources, how to manipulate resources through representations, and how to include metadata that makes messages self-describing.
The web is built on HTTP’s uniform interface, and the focus is on interacting with resources and their representations. REST isn’t tied to any specific platform or technology; the web is the only major platform that fully embodies REST. The basic style of the architecture of RESTful web services is client–server.
Here, the client requests a resource and the server processes and responds to the requested resource. The response of the server is user-based and platform-independent. The separation of concerns is the principle behind the client–server constraints. Because in client–server architecture, the storage and user interfaces are roles taken by the server and client respectively, it has improved portability of the user interface across multiple platforms.
We should document every resource and URI for client developers. We can use any format for structuring our document, but it should contain enough information about resources, URIs, available methods, and any other information required for accessing the service.
Swagger is a tool that can be used for documentation purposes, and provides all the information regarding the API endpoints on one screen, where you can visualize the API and test it by sending parameters as well. Developers can use another tool called Postman for testing out APIs. Both of these tools will be explained with examples in the upcoming chapters of this book.
ASP.NET Web API is a development environment constructed to develop RESTful web services that allow applications to send and receive HTTP requests (web requests) easily and perform operations based on the types of requests that are made to it (such as providing information about a user when given their ID, and so on).
Web API design in ASP.NET Core has been simplified following the same programming model as MVC.
In the next chapter, we will start coding by setting up the environment and look into the various fundamentals of the HTTP verbs in Web API.