.NET Core has become a very interesting framework to develop with. Version after version, it has grown and included significative improvements. However, more often than not, those changes were translated into repetitive changes (in APIs, libraries, dependencies, possibilities, the way of coding, etc) which became time-consuming and frustrating.
Two ways to install the extension:
- through Visual Studio
- through the Visual Studio Marketplace
To install an extension from Visual Studio, go to Extensions -> Manage Extensions. Once there, look for “rest api” on the Online/Visual Studio Marketplace section.
Follow the instructions after clicking on “Download”.
Visual Studio Marketplace
You can download the extension from the Visual Studio Marketplace.
This is the direct link to the extension.
The “Download” button will start the download of the VSIX file. Once downloaded locally, double-click on the file to install it and follow the instructions.
How to create a new solution with the template?
The creation of a new solution based on the new template is quite straightforward. The process is identical to any other creation of a project/solution. This was important to provide good user experience.
First step, open Visual Studio.
Click on the “Create a new project” button.
Choose the template and click on “Next”.
Note: if you do not find the template, use the search field or the filters on the top of the window.
The window after will request common information for new projects/solutions.
The process will take a couple of seconds and it will create a Visual Studio solution with the structure below.
Description of the created solution
We now have a brand new solution which already includes valuable items:
- a controller illustrating how to use it (UserController).
- layers separation in terms of responsabilities.
- integration of Unit Tests (controllers and REST flows).
- DI and IoC integration based on .NET Core 3.1 practices, with no external dependencies.
- mapping configurations among layers (based on Automapper)
- OpenAPI configuration with authomatic generation according to code and comments (XML comments).
- OpenAPI automatic versioning according to code and tags (versioning based on URL routes but editable if needed).
- exception handling according to .Net Core 3.1 practices.
- implementation of all the layers except the repositories (hard to generalize nowadays a repository type). Not even sure your API needs one.
- minimal dependencies.
- condensed of common best practices in terms of REST API coding.
- an already running API with automatically created OpenAPI, which makes things much easier for developers starting with all these concepts.
Let us go a bit further and understand the main concepts.
Structure of the solution
The solution is organized according to the conceptual layers below:
The solution contains a folder for each of these layers.
In addition to these folders, the solution includes a Tests folder and a Common folder, including factorized components.
All that looks like this:
Note: the numbers of the folders are set to order them in a practical way.
The API folder contains the entry point of the project.
- SolutionName.API (entry point, Startup project)
- SolutionName.API.Common, factorized components at API level
- SolutionName.API.DataContracts, exposed data types
- SolutionName.Services, implementation of the business logic of the solution
This folder is empty on purpose. It is created to anticipate where to create your repository (in case you need it).
No repository implementation has been provided because there is a wide variety of persistence models. Additionnaly, your solution maybe does not need any.
- SolutionName.API.Tests.Controllers, testing the controllers directly
- SolutionName.API.Tests.REST, testing the rest routes through REST data flows
- SolutionName.IoC.Configuration, DI and Automapper configurations
- SolutionName.Tools, different types of Tools or Helpers
All in all, the solution creates 8 projects, named, organized and referenced according to a certain set of practices.
- SolutionName.API (entry point)
All this may seem a bit overwhelming. Let us understand what are the principles followed and all will make more sense.
The whole template follows basic architectural and developing principles.
The layers are separated conceptually according to their roles and responsibilities.
Every layer exposes its entity types through given contracts. Those contracts are implemented and resolved by DI. The entities among layers are mapped. One entity type from a given layer should not be used in another one.
The API folder includes a separated project for each layer. This makes things really clear conceptually and phisically at this level.
Services folder includes only one project merging Contracts, Models and Services. Being puristic and rigurous, each of them should be implemented in its own project. That would add another 2 projects, maybe complexifiying the solution too much. This separation is recommended though in projects of a certain size. For small projects, you will maybe have the feeling of “over-architecturing” (at least, physically). But the conceptual practices are all followed all the time and in the same way.
IoC and DI are factorized in a common project (Common folder) to use exactly the same settings in the application and in the test projects. This enables unit testing with closest configurations to real execution contexts.
The dependencies are set automatically by the template.
The external dependencies or additional packages have been avoided (when possible) in order to minimize the dependencies. This reduces the size of the final package.
Controllers are the “exposed” part of the whole REST API solution.
They contain the implementation of the different REST endpoints. Those endpoints expose data contracts (conceptually speaking).
The controllers rely on services to gather data or operate actions.
Mapping entity types between layers is not the most funny coding party. Automapper helps us with this.
DI and IoC
The DI settings have been placed out of the projects to factorize them and reuse them.
This is an important point, mainly for the test projects. Indeed, this practice allows to load exactly the same settings in different projects (for instance, unit tests and the actual application).
The projects included in the solution focus on two aspects:
- testing the controllers
- testing the REST endpoints
In other words, the test projects will test the exposed surface of the project.
This tests may be completed with other projects to control the quality at the Service level.
How to add code and logic to the solution?
Created code by default
Once the solution is created, you can run it.
The url http://localhost:port/swagger shows the Swagger UI (OpenAPI) with the whole description of the API (dynamically generated according to the code and XML comments).
The versioning is automatically generated too.
The data contracts are described according to the code definitions and constraints.
The created UI allows to go down into the details of each endpoint (response types, media type, parameters and their types, etc). You can even test the endpoint from the UI.
All the information, comments and descriptions come from the code, which makes an interesting way to document APIs in a very productive way.
To add your own code, you should respect the principles of the template.
Find and follow your own way to build and separate the controllers. Avoid creating only one controller containing endpoings of all types.
For instance, we will add an endpoint to get a car by its plate number.
For this, we will need to follow the steps below.
- create a Car class in the Services project (Model project folder)
- create the ICarService interface in the Services project (Contracts project folder)
- create the CarService class implementing the ICarService interface in the Services project (Services project folder)
- add a data contract Car to the DataContracts project
- add a controller to the API project (in the folder corresponding to the right version, let us say in the V1 project folder)
- implement the GET endpoint
Register the service (Configuration project, DI project folder, ServiceCollectionExtensions.cs file)
public static void ConfigureBusinessServices(this IServiceCollection services, IConfiguration configuration)
if (services != null)
- configure the mappings between the service entity and the data contract entity (Configuration project, Automapper/Profiles project folder, APIMappingProfile.cs file)
At this stage, you can run the REST API. If you load the OpenAPI (former Swagger), you will see the new endpoint.
If you expand one of the endpoints (both are identical but one is accessed through the “V1” route and the other one by a “default route”. This behavior can be changed to avoid default routes.), you can test it.
- add the controller level unit test in the Controllers project (ControllerTests/V1 project folder)
And that is all.
You will maybe have the feeling you need to keep in mind too many things or you have too much work to accomplish for adding simple things.
When projects grow or if you need to create REST APIs in an industrialized way in teams of developers, you will probably see things differently ;).