A step by step guide on how to implement clean, maintainable RESTful APIs
RESTful is not a new term. It refers to an architectural style where web services receive and send data from and to client apps. The goal of these applications is to centralize data that different client apps will use.
Choosing the right tools to write RESTful services is crucial since we need to care about scalability, maintenance, documentation, and all other relevant aspects. The ASP.NET Core gives us a powerful, easy to use API that is great to achieve these goals.
In this article, I’ll show you how to write a well structured RESTful API for an “almost” real world scenario, using the ASP.NET Core framework. I’m going to detail common patterns and strategies to simplify the development process.
I’ll also show you how to integrate common frameworks and libraries, such as Entity Framework Core and AutoMapper, to deliver the necessary functionalities.
I expect you to have knowledge of object-oriented programming concepts.
Even though I’m going to cover many details of the C# programming language, I recommend you to have basic knowledge of this subject.
I also assume you know what RESTful is, how the HTTP protocol works, what are API endpoints and what is JSON. Here is a great introductory tutorial on this subject. The final requirement is that you understand how relational databases work.
To code along with me, you will have to install the .NET Core 2.2, as well as Postman, the tool I’m going to use to test the API. I recommend you to use a code editor such as Visual Studio Code to develop the API. Choose the code editor you prefer. If you choose this code editor, I recommend you to install the C# extension to have better code highlighting.
Let’s write a fictional web API for a supermarket. Let’s imagine we have to implement the following scope:
- Create a RESTful service that allows client applications to manage the supermarket’s product catalog. It needs to expose endpoints to create, read, edit and delete products categories, such as dairy products and cosmetics, and also to manage products of these categories.
- For categories, we need to store their names. For products, we need to store their names, unit of measurement (for example, KG for products measured by weight), quantity in the package (for example, 10 if the product is a pack of biscuits) and their respective categories.
To simplify the example, I won’t handle products in stock, product shipping, security and any other functionality. The given scope is enough to show you how ASP.NET Core works.
To develop this service, we basically need two API endpoints: one to manage categories and one to manage products. In terms of JSON communication, we can think of responses as follow:
API endpoint: /api/categories
JSON Response (for GET requests):
API endpoint: /api/products
JSON Response (for GET requests):
Creating the API
First of all, we have to create the folders structure for the web service, and then we have to use the .NET CLI tools to scaffold a basic web API. Open the terminal or command prompt (it depends on the operating system you are using) and type the following commands, in sequence:
Let’s get started writing the application.
The first two commands simply create a new directory for the API and change the current location to the new folder. The last one generates a new project following the Web API template, that is the kind of application we’re developing. You can read more about these command and other project templates you can generate checking this link.
The new directory now will have the following structure:
The diagram shows that the system will have four layers:
- Database – Here we store data and nothing more, no logic.
- DAL – To access the data, we use the Unit of Work pattern and, in the implementation, we use the ORM EF Core with code first and migration patterns.
- Business logic – to encapsulate business logic, we use query processors, only this layer processes business logic. The exception is the simplest validation such as mandatory fields, which will be executed by means of filters in the API.
- RESTful API – The actual interface through which clients can work with our API will be implemented through ASP.NET Core. Route configurations are determined by attributes.
In addition to the described layers, we have several important concepts. The first is the separation of data models. The client data model is mainly used in the RESTful API layer. It converts queries to domain models and vice versa from a domain model to a client data model, but query models can also be used in query processors.
To improve your API with some advanced techniques you might want to check out:
Paginate your API requests to limit response results and make them easier to work with. We use offset and count in the URL query string to paginate because it provides greater control over how you view your data.
Flexibility on Filtering
Use a unique query parameter for all fields or a query language for filtering.
GET /api/v1/products? Price>1000 Returns a list of products (Id, Name, Description, Code, Price), which price is greater than 1000
GET /api/v1/products? Code=P123 Returns a list of products (Id, Name, Description, Code, Price) which code is “P123”
If you provide multiple filters, you can only return resources that match all filters.
What is Searching?
There is no doubt in our minds that you’ve seen a search field on almost every website on the internet.
It’s easy to find something when we are familiar with the website structure or when a website is not that large. But, if we want to find the most relevant topic for us, or if we don’t know what we’re going to find, or maybe we’re first-time visitors of a large website, we’re probably going to use a search field.
Basic search is not that hard to implement, but if taken lightly, the search function can be useless. Sometimes it’s better to just revert back to Google, or use a google dork to search the website. If you are not familiar with Google dorks, we highly recommend you try them out.
How to Implement Searching in ASP.NET Core Web API
Since we’re going to implement the most basic search in our project, the implementation won’t be complex at all. We have all we need infrastructure-wise since we already covered paging and filtering. We’ll just extend our implementation a bit.
What we want to achieve is something like this:
This should return just one result: Anna Bosh. Of course, the search needs to work together with filtering and paging, so that’s one of the things that we need to keep in mind too.
Like we did with filtering, we’re going to extend our Own Parameters class first since we’re going to send our search query as a query parameter:
We’ve added just one new property – Name.
Simple as that.
Now we can write queries with name=”term” in them.
Next thing we need to do is to actually implement the search functionality in our Own Repository class
First, we need to check if the name parameter is actually sent, by doing a simple IsNullOrWhiteSpace check on the Name property. If it’s not, there’s no point in searching for anything really.
After that, we are using the Where clause with trimmed Name string (just in case). We are doing this after the filtering is done to search through fewer results.
Everything else stays the same.
That’s it for our implementation. As you can see it really isn’t that hard since it is the most basic search, and we already had an infrastructure set.
Testing Our Implementation
Now, let’s try to find Anna:
Sure enough, we get our result.
Allow ascending and descending sorting over multiple fields.
GET /api/v1/products? Sort=-price
– Retrieves a list of products in descending order of price
GET /api/v1/products? Sort=+price, name
– Retrieves a list of products in ascending order of price and name
Swagger basically is a framework for describing, consuming, and visualizing Restful APIs. It provides a rich discovery, documentation (documentation of methods, parameters, and models are tightly integrated into the server code) and playground experience to their API consumers.
Steps to add Swagger to ASP.NET Web API
Step 1 :
Install the swagger NuGet Package
Open NuGet Package Manager Console and install the below package.
Install-Package Swash buckle
Once you add the package, “swaggerconfig.cs” file will be added automatically.
Step 2 :
Enable generating XML documentation
This is not a mandatory step to use “Swashbuckle” but I believe it is very useful for API consumers, especially if you have complex data models. So, to enable XML documentation, go to project properties >> Build. Then, enable check box for documentation. This will add an XML file to the bin folder which contains all the XML comments you added as annotation to the controllers or data models.
Step 3 :
Configure Swashbuckle to use XML Comments
By default, Swashbuckle doesn’t include the annotated XML comments on the API Controllers and data models into the generated specification and the UI. To include them, we need to configure it. So open file “SwaggerConfig.cs” and add the below line.
Start running my application and append “swagger” at end of the URL.
Changes that don’t break existing code using the API can be handled within one version. If there are breaking changes i.e. it risks breaking the code which is using the API, those changes should be introduced in a new version of the API.
Every developer should do some planning ahead of your web API. Make the API Version mandatory and never release an un versioned API.
Sample of URL version schema: /api/v1/products /api/products? Version=v1 /api/products? api-version=1
/api/v2-Alpha/products /api/products? api-version=2-Alpha
/api/v2015-05-01.3.0/products /api/products? api-version=2015-05-01.3.0