Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Building RESTful Web Services with .NET Core

You're reading from   Building RESTful Web Services with .NET Core Developing Distributed Web Services to improve scalability with .NET Core 2.0 and ASP.NET Core 2.0

Arrow left icon
Product type Paperback
Published in May 2018
Publisher Packt
ISBN-13 9781788291576
Length 334 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Authors (3):
Arrow left icon
Gaurav Aroraa Gaurav Aroraa
Author Profile Icon Gaurav Aroraa
Gaurav Aroraa
Tadit Dash Tadit Dash
Author Profile Icon Tadit Dash
Tadit Dash
Sharbani Bhattacharya Sharbani Bhattacharya
Author Profile Icon Sharbani Bhattacharya
Sharbani Bhattacharya
Arrow right icon
View More author details
Toc

Table of Contents (13) Chapters Close

Preface 1. Getting Started 2. Building the Initial Framework – Laying the Foundation of the Application FREE CHAPTER 3. User Registration and Administration 4. Item Catalogue, Cart, and Checkout 5. Integrating External Components and Handling 6. Testing RESTful Web Services 7. Continuous Integration and Continuous Deployment 8. Securing RESTful Web Services 9. Scaling RESTful Services (Performance of Web Services) 10. Building a Web Client (Consuming Web Services) 11. Introduction to Microservices 12. Other Books You May Enjoy

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.
You can read the whole dissertation at https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm.

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.

For example, in HTML, you link to another resource through the anchor element. The following is one anchor element that links to Packt's IoT book catalog page:

<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.

POST versus PUT: This is a very common topic of discussion on the internet, and one that is very easy to understand. Both POST and PUT can be used to insert or update a resource. However, POST is nonidempotent, meaning that it isn't repeatable. The reason is that each time you call using POST, it will create a new resource if you don't provide the exact URI of the resource. The next time you use POST, it will again create a new resource. However, in PUT, it will first validate the existence of the resource. If it exists, it will update it; otherwise, it will create it.

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
lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime