Building RESTful Web services with .NET Core

4.5 (4 reviews total)
By Gaurav Aroraa , Tadit Dash
    Advance your knowledge in tech with a Packt subscription

  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Getting Started

About this book

REST is an architectural style that tackles the challenges of building scalable web services. In today's connected world, APIs have taken a central role on the web. APIs provide the fabric through which systems interact, and REST has become synonymous with APIs. The depth, breadth, and ease of use of ASP.NET Core makes it a breeze for developers to work with for building robust web APIs. This book takes you through the design of RESTful web services and leverages the ASP.NET Core framework to implement these services. This book begins by introducing you to the basics of the philosophy behind REST. You'll go through the steps of designing and implementing an enterprise-grade RESTful web service. This book takes a practical approach, that you can apply to your own circumstances. This book brings forth the power of the latest .NET Core release, working with MVC. Later, you will learn about the use of the framework to explore approaches to tackle resilience, security, and scalability concerns. You will explore the steps to improve the performance of your applications. You'll also learn techniques to deal with security in web APIs and discover how to implement unit and integration test strategies. By the end of the book, you will have a complete understanding of Building a client for RESTful web services, along with some scaling techniques.

Publication date:
May 2018
Publisher
Packt
Pages
334
ISBN
9781788291576

 

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

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.

About the Authors

  • Gaurav Aroraa

    Gaurav Aroraa is a serial entrepreneur and start-up mentor. He has done an M.Phil in computer science. He is a Microsoft MVP award recipient. He is a lifetime member of the Computer Society of India (CSI), is an advisory member and senior mentor at IndiaMentor, is certified as a Scrum trainer/coach, is ITIL-F certified, and is PRINCE-F and PRINCE-P certified. He is an open source developer and a contributor to the Microsoft TechNet community. Recently, Gaurav was awarded "Icon of the year excellence in Mentoring Technology Startups" for 2018-19 by Radio City, a Jagran initiative, for his extraordinary work during his 22-year career in the industry in the field of technology mentoring.

    Browse publications by this author
  • Tadit Dash

    Tadit Dash is a senior software engineer and a hardcore tech community contributor. Due to his exceptional contribution to the technical community, Microsoft has awarded him with the Microsoft Most Valuable Professional accolade since 2014. CodeProject has awarded him the CodeProject MVP accolade (the first from Odisha). For his constant mentorship, IndiaMentor featured him as a young mentor on their site. He was a featured speaker at DevTechDay Nepal and C# Corner Annual Conference, India. You can follow him on Twitter: @taditdash.

    Browse publications by this author

Latest Reviews

(4 reviews total)
Good book. Very informative.
Great to understand, easy to learn
This book gives a good introduction of the material.
Building RESTful Web services with .NET Core
Unlock this book and the full library for FREE
Start free trial