Cet article est un aide-mémoire concernant les fonctions principales de Swagger UI. La documentation complête se trouve sur le repository GitHub du package Swashbuckle.AspNetCore qui est le package NuGet permettant d’installer Swagger sur une application ASP.NET Core.
Swagger est un outil permettant de documenter un API Web en présentant les différentes fonctions sous forme d’une page web. On peut ainsi utiliser l’interface web pour requêter les différentes fonctions de l’API.
Dans cet article, on va présenter les éléments de paramétrages principaux pour paramétrer Swagger dans le cas d’une API Web ASP.NET Core.
Installation et configuration de Swagger
Améliorer la présentation de la description JSON
Configurer un endpoint
Ajouter des informations globales
Ajouter un titre HTML
Enrichir les informations globales
Prendre en compte les commentaires XML du projet
Informations sur les actions d’un controller
Ajouter les “operation IDs”
Liste des réponses possibles
Attributs FromQueryAttribute et FromBodyAttribute
Indiquer un paramètre obligatoire
Indiquer des metadonnées avec des attributs Swagger
SwaggerOperationAttribute
SwaggerResponseAttribute
SwaggerParameterAttribute
SwaggerTagAttribute
L’exemple d’API Web utilisé dans cet article se trouve dans la branche swagger
du repository GitHub https://github.com/msoft/webapi_example.
Installation et configuration de Swagger
En commençant “from scratch”, pour créer une API Web ASP.NET Core, on peut exécuter la commande suivante après avoir installé la CLI .NET Core:
user@debian:~/% dotnet new webapi --name <nom du projet>
Pour installer Swagger dans une application ASP.NET Core et requêter facilement une API Web, il faut ajouter le package NuGet Swashbuckle.AspNetCore en exécutant la commande suivante:
user@debian:~/% dotnet add <chemin du fichier .csproj> package swashbuckle.aspnetcore
Dans le cas de l’exemple sur le repository GitHub https://github.com/msoft/webapi_example, il faut exécuter la commande:
user@debian:~/% dotnet add webapi_example/webapi_example.csproj package swashbuckle.aspnetcore
Pour configurer Swashbuckle, il faut ajouter les lignes suivantes dans le fichier StartUp.cs
:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "Pizza API", Version = "v1"});
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ...
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Pizza API V1");
});
// ...
}
Dans l’extrait précédent:
services.AddSwaggerGen()
permet de rajouter un service qui va analyser le code pour générer la description de l’API sous forme d’un document JSON (i.e. SwaggerDocument).app.UseSwagger()
va rajouter un middleware pour exposer le contenu du SwaggerDocument (contenant la description de l’API dans un document JSON). En pratique ce middleware va répondre quand une requête est faite à l’adressehttp://localhost:5000/swagger/v1/swagger.json
(adresse par défaut).app.UseSwaggerUI()
permet de rajouter un middleware pour présenter le SwaggerDocument sous forme d’une interface web. L’ajout de ce middleware est facultatif. On peut utiliser seulement le middleware Swagger, générer le SwaggerDocument et copier le code JSON dans https://editor.swagger.io/ pour l’utiliser.
Dans l’exemple, on peut lancer la compilation et l’exécution en exécutant successivement les lignes suivantes:
user@debian:~/% cd webapi_example
user@debian:~/webapi_example/% dotnet build
user@debian:~/webapi_example/% dotnet run
Par défaut:
- La description JSON de l’API se trouve à l’adresse:
http://localhost:5000/swagger/v1/swagger.json
. - On peut accéder à l’interface de Swagger à l’adresse:
http://localhost:5000/swagger/index.html
.
Pour installer .NET Core sur Debian, il faut suivre les étapes suivantes:
Améliorer la présentation de la description JSON
Quand on requête le description JSON à l’adresse http://localhost:5000/swagger/v1/swagger.json
, le document est présenté de façon compacte. On peut améliorer la présentation du document en ajoutant la configuration suivante dans le fichier StartUp.cs
:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.Formatting = Formatting.Indented;
});
}
Configurer un endpoint
On peut spécifier un endpoint particulier pour accéder à Swagger en ajoutant les éléments de configuration suivants:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ...
app.UseSwaggerUI(c =>
{
c.RoutePrefix = "pizza-api-docs"
});
}
Dans cet exemple, Swagger sera ainsi accessible à l’adresse: http://localhost:5000/pizza-api-docs
.
Ajouter des informations globales
Les éléments de configuration suivants permettent d’ajouter des informations globales sur l’API.
Ajouter un titre HTML
Ce titre correspond au titre de la page HTML. Il apparaîtra dans l’onglet du browser. Pour l’ajouter, il faut rajouter la ligne suivante:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ...
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Pizza API V1");
c.DocumentTitle = "Custom HTML title";
});
}
Sans préciser davantage d’éléments de configuration, les informations sont présentées de cette façon sur l’interface web de Swagger:
Enrichir les informations globales
On peut ajouter d’autres informations globales, par exemple:
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info {
Title = "Pizza API",
Version = "v1",
Description = "API for pizza",
TermsOfService = "Terms of Service",
Contact = new Contact
{
Name = "Developer Name",
Email = "developer.name@example.com"
},
License = new License
{
Name = "Apache 2.0",
Url = "http://www.apache.org/licenses/LICENSE-2.0.html"
}
});
});
}
En rajoutant ces informations, on obtient l’affichage suivant:
Prendre en compte les commentaires XML du projet
Swagger peut afficher les commentaires XML du projet, à condition qu’ils soient générés. Avec ASP.NET Core, pour générer les commentaires XML, il faut éditer le fichier .csproj
de l’application ASP.NET Core et ajouter la ligne suivante correspondant au nœud XML <DocumentationFile>
:
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\<nom du fichier>.xml</DocumentationFile>
</PropertyGroup>
Ensuite, il faut indiquer le chemin du fichier XML généré à Swagger dans le fichier StartUp.cs
du projet:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSwaggerGen(c =>
{
// ...
var filePath = Path.Combine(System.AppContext.BaseDirectory, "<nom du fichier>.xml");
c.IncludeXmlComments(filePath);
});
}
Ainsi, si on ajoute des informations dans les commentaires d’une action d’un controller, par exemple au niveau de l’action FindFlavour()
du controller PizzaFlavourController:
/// <summary>
/// Find flavour using flavour name
/// </summary>
/// <remarks>Usefull remark</remarks>
/// <response code="200">Flavour retreived</response>
/// <response code="400">Flavour not found</response>
/// <response code="500">Bad request</response>
[HttpGet("{flavourName}", Name = "FindFlavourByName")]
[ProducesResponseType(typeof(IEnumerable<string>), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(500)]
public ActionResult<IEnumerable<string>> FindFlavour(string flavourName)
{
// ...
}
On peut enrichir les informations relatives à la fonction de l’API:
Ajouter des informations sur les actions d’un controller
Pour que les actions d’un controller soient visibles dans Swagger, il faut utiliser les attributs permettant de définir les routes sur le controller (cf. RouteAttribute
) et sur les actions (cf. HttpGetAttribute
, HttpPostAttribute
, HttpDeleteAttribute
et HttpPutAttribute
).
Par exemple en rajoutant ces attributs dans le controller PizzaFlavourController
:
[Route("api/[controller]")]
[ApiController]
public class PizzaFlavourController : ControllerBase
{
[HttpGet]
public ActionResult<IEnumerable<string>> GetFlavourNames()
{
// ...
}
[HttpGet("{flavourName}")]
public ActionResult<IEnumerable<string>> FindFlavour(string flavourName)
{
// ...
}
[HttpPost]
public ActionResult<int> Post([FromBody, BindRequired]AddPizzaFlavourRequest request)
{
// ...
}
}
Avec cet exemple, on obtient:
Ajouter les “operation IDs”
On peut ajouter des identifiants relatifs aux actions avec le paramétrage suivant dans le fichier StartUp.cs
du projet:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ...
app.UseSwaggerUI(c => {
// ...
c.DisplayOperationId();
});
}
Sans davantage d’éléments de configuration, l’affichage indique les noms des actions:
En utilisant la propriété Name
des attributs HttpGetAttribute
, HttpPostAttribute
, HttpPutAttribute
et HttpDeleteAttribute
, on peut préciser un nom particulier différent du nom de l’action.
Par exemple:
[HttpGet("{flavourName}", Name = "FindFlavourUsingFlavourName")]
public ActionResult<IEnumerable<string>> FindFlavour(string flavourName)
{
// ...
}
[HttpPost(Name = "AddPizzaFlavour")]
public ActionResult<int> Post([FromBody, BindRequired]AddPizzaFlavourRequest request)
{
// ...
}
[HttpGet]
public ActionResult<IEnumerable<string>> GetFlavourNames()
{
// ...
}
On obtient ainsi:
Liste des réponses possibles
En utilisant l’attribut ProducesResponseTypeAttribute
, on peut indiquer toutes les réponses possibles d’une action. Swagger peut prendre en compte ces réponses dans la description d’une action.
Par exemple en rajoutant cet attribut dans l’action suivante:
[HttpGet("{flavourName}", Name = "FindFlavourByName")]
[ProducesResponseType(typeof(IEnumerable<string>), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(500)]
public ActionResult<IEnumerable<string>> FindFlavour(string flavourName)
{
// ...
}
On obtient l’affichage suivant:
Attributs FromQueryAttribute et FromBodyAttribute
Les attributs FromQueryAttribute
et FromBodyAttribute
permettent d’indiquer explicitement si le paramètre d’une action doit se trouver dans l’URL de la requête ou dans le corps d’un message HTTP. Ces attributs sont pris en compte par Swagger dans sa description.
Par exemple, si on utilise ces paramètres de la façon suivante:
[HttpGet("{flavourName}", Name = "FindFlavourByName")]
public ActionResult<IEnumerable<string>> FindFlavour([FromQuery]string flavourName)
{
// ...
}
[HttpPost(Name = "AddPizzaFlavour")]
public ActionResult<int> Post([FromBody]AddPizzaFlavourRequest request)
{
// ...
}
On obtient l’affichage suivant dans Swagger:
Indiquer un paramètre obligatoire
On peut utiliser l’attribut BindRequiredAttribute
sur le paramètre d’une action ou l’attribut RequiredAttribute
sur les propriétés d’une DTO pour indiquer explicitement que le paramètre est obligatoire.
Par exemple en utilisant l’attribut BindRequiredAttribute
pour les actions suivantes:
[HttpGet("{flavourName}", Name = "FindFlavourByName")]
public ActionResult<IEnumerable<string>> FindFlavour([FromQuery, BindRequired]string flavourName)
{
// ...
}
[HttpPost(Name = "AddPizzaFlavour")]
public ActionResult<int> Post([FromBody, BindRequired]AddPizzaFlavourRequest request)
{
// ...
}
On obtient l’affichage:
Indiquer des metadonnées avec des attributs Swagger
Avec les méthodes précédentes, on a précisé les métadonnées d’une API en utilisant:
- Des attributs du framework .NET avec
ProducesResponseType
,HttpGet
,HttpPost
,HttpDelete
ouHttpPut
. - La documentation XML dans le code.
Il est possible de préciser ces informations en utilisant des attributes spécifiques à Swagger. Les informations seront reconnues et utilisées pour enrichir les métadonnées de l’API de la même façon qu’avec la méthode précédente.
L’assembly contenant les attributs spécifiques à Swagger se trouve dans la package NuGet Swashbuckle.AspNetCore.Annotations.
Pour installer ce package, il faut exécuter la commande suivante:
user@debian:~/% dotnet add <chemin du fichier .csproj> package swashbuckle.aspnetcore.annotations
Dans le cas de l’exemple sur le repository GitHub https://github.com/msoft/webapi_example, il faut exécuter la commande:
user@debian:~/% dotnet add webapi_example/webapi_example.csproj package swashbuckle.aspnetcore.annotations
Pour utiliser le package installé, il faut l’activer dans le fichier StartUp.cs
du projet en ajoutant les lignes:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSwaggerGen(c =>
{
// ...
c.EnableAnnotations();
});
}
Les attributs spécifiques à Swagger utilisés par la suite suivants, se trouvent dans le namespace Swashbuckle.AspNetCore.Annotations
, il faut les utiliser en précisant dans l’entête du fichier .cs
:
using Swashbuckle.AspNetCore.Annotations;
SwaggerOperationAttribute
Cet attribut est l’équivalent des commentaires XML pour préciser des informations concernant une action.
Par exemple, en utilisant SwaggerOperationAttribute
dans le code suivant:
[HttpGet("{flavourName}", Name = "FindFlavourByName")]
[SwaggerOperation(
Summary = "Returns the ingredients from a flavour name",
Description = "Returns the ingredients",
OperationId = "FindFlavour")]
public ActionResult<IEnumerable<string>> FindFlavour([FromQuery, BindRequired]string flavourName)
{
// ...
}
Le résultat est le même que dans le cas des commentaires XML:
L’élément Tag
permet d’indiquer dans quelle partie sera rangée l’action.
Par exemple, si on précise les tags "Flavour"
et "Pizza"
, l’action sera rangée dans les parties "Flavour"
et "Pizza"
[HttpGet("{flavourName}", Name = "FindFlavourByName")]
[SwaggerOperation(
Summary = "Returns the ingredients from a flavour name",
Description = "Returns the ingredients",
OperationId = "FindFlavour",
Tags = new[] { "Flavour", "Pizza" }
)]
public ActionResult<IEnumerable<string>> FindFlavour([FromQuery, BindRequired]string flavourName)
{
// ...
}
Le résultat sera:
Il est possible préciser d’autres éléments en utilisant SwaggerOperationAttribute
comme:
Consumes
pour préciser les types MIMES que l’action peut consumer.Produces
pour préciser les types MIMES que l’action peut générer.Schemes
pour indiquer les protocoles de transfert supportés par l’action.
SwaggerResponseAttribute
Cet attribut permet d’indiquer des informations sur les réponses possibles. Il est équivalent à l’attribut ProducesResponseTypeAttribute
.
Par exemple en utilisant SwaggerResponseAttribute
dans le code suivant:
[HttpGet("{flavourName}", Name = "FindFlavourByName")]
[SwaggerResponse(200, "The ingredients for the flavour have been found", typeof(IEnumerable<string>))]
[SwaggerResponse(400, "The flavour has not been found", typeof(string))]
[SwaggerResponse(500, "Internal server error")]
public ActionResult<IEnumerable<string>> FindFlavour([FromQuery, BindRequired]string flavourName)
{
// ...
}
Le résultat de cet exemple est du type:
SwaggerParameterAttribute
Cet attribut permet de fournir des informations sur les paramètres d’une action. Il est l’équivalent de l’attribut BindRequiredAttribute
, toutefois il permet d’indiquer d’apporter une précision supplémentaire comme le nom du paramètre.
Par exemple si on utilise l’attribut SwaggerParameterAttribute
dans le code suivant:
[HttpGet("{flavourName}", Name = "FindFlavourByName")]
public ActionResult<IEnumerable<string>> FindFlavour(
[FromQuery, SwaggerParameter("Flavour name", Required = true)]string flavourName)
{
// ...
}
Le résultat de cet exemple est du type:
SwaggerTagAttribute
Cet attribut permet de préciser des informations supplémentaires concernant le controller.
Par exemple, en utilisant l’attribut sur la classe du controller:
[Route("api/[controller]")]
[ApiController]
[SwaggerTag("Get or create new flavour for pizzas")]
public class PizzaFlavourController : ControllerBase
{
// ...
}
Le résultat de cet exemple est du type:
- Documentation Swashbuckle.AspNetCore: https://github.com/domaindrivendev/Swashbuckle.AspNetCore
- Liste des codes HTTP: https://fr.wikipedia.org/wiki/Liste_des_codes_HTTP
- ASP.NET Core doesn’t create XML comments file: https://stackoverflow.com/questions/41593487/asp-net-core-doesnt-create-xml-comments-file
Merci pour cet article, j’écris moi même un blog C#. NET
Merci pour votre commentaire et pour le partage de l’adresse de votre blog, très intéressant et en français…