.NET Core est un framework open source permettant de créer des applications web avec le langage C#. Dans cet article je présente les étapes de la mise en place d’une API REST avec .NET Core.
Quelques technos utilisées:
- .NET Core (ASP.NET MVC)
- Docker / Kubernetes / Jenkins pipeline
- Swashbuckle pour l’intégration Swagger
- Moq pour les tests unitaires
L’application
Il s’agit d’une API REST de gestion d’une liste de widgets. Chaque widget a un nom et une URL. Le code source du projet est disponible sous Github.
L’API implémente un CRUD. Pour la mise en place, je me suis basé sur ce tutoriel disponible dans la documentation officielle de Microsoft.
Les ressources REST sont crées à l’aide de classes
contrôleur, décorées avec l’attribut [Route]
. Les verbes
REST sont implémentés à l’aide des attributs [HttpGet]
, [HttpPut]
,
etc.
[Route("api/[controller]")]
public class WidgetsController : Controller
...
[HttpGet]
public IEnumerable<Widget> GetAll()
...
Une base de données en mémoire est accédée à l’aide d’un database context EntityFramework.
L’application est “bootstrapée” dans Startup.cs
, qui
contient la configuration des classes, configure ASP.NET MVC
et active l’injection de dépendances.
Environnement de développement
J’ai préféré utiliser la commande dotnet
(dotnet new
,
dotnet add
, etc.) fournie avec le SDK, pour initialiser
le projet en ligne de commande.
On peut également le faire via Visual Studio, mais je trouve
qu’on comprend mieux ce qui se passe avec dotnet
.
Les tutoriels indiqués présentent les deux approches.
Pour l’environnement de développement, il est possible d’utiliser (en théorie) un simple éditeur ou (mieux) VSCode: on trouve pas mal d’aides et de plugins. A la longue, un IDE plus intégré se justifie plus facilement, pour les outils de refactoring et de génération de code automatique qu’il fournit.
J’ai donc installé Visual Studio Community Edition (gratuit, sous conditions) Le top c’est le Rider de JetBrains, si vous arrivez à négocier une licence 🤑.
Activation de CORS
Pour utiliser l’API avec une autre application, j’ai eu besoin
d’activer CORS et Access-Control-Allow-Origin
. Ca se met
en place en quelques lignes avec .NET MVC, je me suis basé sur
ce tutoriel.
Activation de Swagger
Pour simplifier l’utilisation de l’API lors du développement, j’ai ajouté Swagger et son interface graphique SwaggerUI.
L’explication pour la mise en place de Swagger dans ce tutoriel. En l’occurence j’ai utilisé la librairie Swashbuckle comme décrit ici.
Là aussi c’est assez rapide.
Par contre j’ai rencontré un souci pour
servir Swagger dans un
sous-répertoire de mon domaine, par exemple sous exemple.com/back/swagger.json
.
Je n’ai pu configurer Swashbuckle que
directement à la racine exemple.com/swagger.json
. Il faudrait
creuser le souci 🤔.
Dockerisation
L’idée est de conteneuriser l’application avec Docker pour la déployer dans le cluster Kubernetes de l’usine logicielle de la communauté SofteamOuest.
La théorie
Il existe plusieurs images Docker officielles permettant de conteneuriser et d’exécuter une application .NET Core.
L’image dotnet:sdk
permet de construire les binaires de
l’application (.dll) à partir du code source.
Elle est assez lourde (plus d’un gigaoctet) donc patience.
Il est généralement préférable d’utiliser l’image
dotnet:runtime
, plus légère, pour l’exécution.
Il est évidemment possible tout faire
avec l’image dotnet:sdk
, mais le conteneur généré
pour l’application
est alors très volumineux et ce n’est pas recommandé
en production.
En pratique
La construction de l’image de l’application nécessite donc
d’utiliser consécutivement deux images dans le Dockerfile :
dotnet:sdk
pour compiler le binaire puis dotnet:runtime
pour
l’image finale.
FROM microsoft/dotnet:sdk AS build-env
RUN dotnet publish -c Release -o out
...
FROM microsoft/aspnetcore:2.0
COPY --from=build-env /app/out .
...
C’est ce qui est d’ailleurs conseillé dans les tutoriels Docker et Microsoft
Malheureusement cette solution multistage build nécessite une version de Docker assez récente, non possible sur notre plateforme. Nous allons donc utiliser les deux images mais séparément, grâce aux facilités proposées par notre Jenkins pipeline…
Déploiement sur le cluster
L’image dotnet:sdk
est utilisée localement sur la plateforme
d’intégration pour construire les binaires.
Le Dockerfile
utilise alors uniquement l’image dotnet:runtime
et
récupère les binaires générés précédemment dans l’environnement
de travail de Jenkins.
...
containerTemplate(name: 'dotnet', image: 'microsoft/dotnet'),
...
container('dotnet') {
sh 'dotnet publish -c Release -o out'
}
...
container('docker') {
docker build .
}
...
Une fois l’image Docker créee, elle est publiée sur le Nexus. Le déploiement sur le clusteur peut alors être réalisé à l’aide d’un job de déploiement Kubernetes (comme expliqué ici et ici)
Conclusion
J’ai trouvé la création de cette API REST à l’aide de .NET Core assez rapide et efficace. J’ai notamment apprécié la facilité avec laquelle on peut ajouter des outils de sécurisation ou d’aide au développement, comme CORS ou Swagger, avec un minimum de code.
C’est l’avantage d’arriver après tout le monde 😄 : proposer un framework moderne avec des technos éprouvées, adaptable rapidement avec une configuration minimale.
Le framework est suffisament bien documenté, sauf lorsqu’on veut faire des choses un peu plus inhabituelles, et là il faut vraiment chercher…
Prochainement, je souhaite remplacer la base mémoire par MongoDB et ajouter plus de tests avec Specflow.