Danny van der Kraan
Danny van der Kraan Software Engineer
| 4 reactie(s)

ASP.NET Core 1.0: Web API Automatic Documentation with Swagger and Swashbuckle

Intro

Het problem met REST API’s is het handmatig beheren van de documentatie welk de API beschrijft (zelfs als er een tool gebruikt wordt voor het genereren is dit vaak nog semi-automatisch). Hierdoor loopt de documentatie vaak achter, is het niet adequaat en het is al helemaal niet interactief. Hier hebben we dus tegenwoordig Swagger [http://swagger.io/] voor. Swagger biedt een krachtige representatie van RESTful API’s door dit automatisch te genereren. Swagger is Open Source, niet platform specifiek en in dit artikel gaan we Swagger toepassen in een ASP.NET Core Web API project. Om dit voor elkaar te krijgen is er een specifieke implementatie van Swagger nodig op ASP.NET Core en hier komt Swashbuckle 6.0.0 van pas [https://github.com/domaindrivendev/Ahoy].

Opstarten

Swashbuckle voegt Swagger naadloos toe aan een ASP.NET Core project door MVC’s ingebouwde API Explorer te combineren met Swagger’s swagger-ui om zodoende de API te onderzoeken en interactieve documentatie te generen voor je API gebruikers. Swashbuckle is een release candidate (RC) op het moment van schrijven dus de interface kan nog veranderen. Voor nu is de beste manier om te starten de twee NuGet pakketjes te installeren die “Swashbuckle.SwaggerGen” en “Swashbuckle.SwaggerUi” heten, beide versie “6.0.0-rc1-final”. Voeg dus deze twee items toe aan de dependencies sectie van je project.json bestand:

Kanttekening: Geen teken gezien van de RTM NuGet pakketjes op het moment van schrijven, maar laten we hopen dat de interface niet al te veel wijzigt.

Wanneer dit gedaan is kunnen we Swagger configureren in de Startup class. Eerst voegen we benodigde services toe in de ConfigureServices method van de StartUp class om zodoende de bestanden te generen die Swagger nodig heeft, als volgt:

Dit is al een implementatie van ISwaggerProvider met de default settings. Dan in dezelfde class in deConfigure method moet je als volgt middleware toevoegen aan de HTTP request pipeline:

Dit zal het gegenereerde Swagger JSON als een JSON endpoint serveren. Als je nu de web applicatie opstart en je navigeert naar de standaard route, wat: “/swagger/v1/swagger.json” is, dan zou je de volgende JSON moeten zien:

Kanttekening: Je kan de standard route wijzigen, daar het een optie is van extension method UseSwaggerGen.
Nou, laten we Swagger nu eens echt aan het werk zetten, door een MVC controller toe te voegen! Voeg de volgende code toe aan de ConfigureServices method van de StartUp class:

Voeg de volgende code toe aan de Configure method van de StartUp class:

Voeg een folder toe genaamd “Controllers”.

Voeg een class toe aan deze folder genaamd “HomeController” en zorg dat het overerft van Controller. Voeg de volgende action method toe aan de Home controller:

Run de web applicatie en navigeer naar “/swagger/v1/swagger.json” en je zou de volgende JSON moeten zien:

Let op hoe de key “paths” nu gevuld is, door de standaard API discovery die Swashbuckle simpelweg gebruikt om de swagger.json te genereren als brandstof als het ware voor de Swagger motor. Om swagger-ui nu te kunnen gebruiken en interactieve documentatie te kunnen verkrijgen moeten we de volgende code toevoegen aan de Configure method in de Startup class:

Dit zal middleware toevoegen aan de HTTP request pipeline die de interactieve documentatie zal genereren op basis van de swagger.json. Als je de web applicatie weer opstart en navigeert naar “swagger/ui” zou het er als volgt uit moeten zien:

figure1_swaggerui

Kanttekening: UseSwaggerUI heeft twee parameters, “baseRoute” (om de “swagger/ui” standaard route te wijzigen) en “swaggerURL” (om de standard locatie “/swagger/v1/swagger.json” te wijzigen waar swagger.json bestand staat).

De interactive documentatie is opgebouwd op een RESTful manier. Eerst zie je de link “Home”, want de ‘resource’ “About” valt onder de resource “Home”. En als je op beide klikt zou je het volgende moeten zien:

figure2_swaggerui
We kunnen zien dat het een “Get” method is en we zien het relatieve pad “/About”. Als je op “/About” klikt zou je het volgende moeten zien:

figure3_swaggerui

Zoals je kan zien kan het de response berichten opsommen en je ziet een “Try it out!” knop. En als je daar op klikt zou je het volgende moeten zien:

figure4_swaggerui

Je ziet de “CURL”, de “Request URL”, “Response Body”, “Response Code” en zelfs de “Response Headers” door maar drie regeltjes code te tikken! Nou, dat vind ik wel erg sjiek!

Meerdere versies

Een algemeen probleem met API’s voor extern gebruik is dat je niet weet precies hoeveel mensen leunen op je API en wanneer je veranderingen maakt wil je niet andere mensen hun code ook omver gooien en dus ga je jouw API versies geven. Gelukkig heeft Swagger ondersteuning voor meerdere versies en samen met Swashbuckle kan je dit gemakkelijk configureren. Laten we beginnen met het maken van een tweede versie van de “About” action method op de “Home” controller. Verander de methodes zoals hieronder wordt aangegeven:

In de ConfigureServices method van de StartUp class voeg je de volgende code toe:

Kanttekening: Als je Web API gehost wordt in IIS moet je versienummers zoals “1.0” vermijden. De punt aan het einde van de URL zorgt ervoor dat IIS de URL behandelt als een statisch bestand (met andere woorden een bestand met een extensie) en dit gaat om de URL Routing Module (en daardoor de Web API) heen.

De “ConfigureSwaggerDocument” method is een extension method waarmee je de Swagger document kan configureren. Als parameter accepteert het een Action of SwaggerDocumentOptions, die een “MultipleApiVersions” methode heeft welk een collective van Info objecten kan bevatten waarmee je jouw versies kan beschrijven. Het is echter niets meer dan het beschrijven van je versies.

Het echte werkpaard is de tweede parameter welk een “Function” is die een instantie van “ApiDescription” accepteert en een string genaamd “version” en welk geacht wordt een boolean te retourneren. ‘True’ als de specifieke versie gehit wordt, ‘false’ als dit niet aan de orde is. De oplossing voor meerdere versies is namelijk niet eenduidig opgelost en daarom lost Swashbuckle het op deze manier op zodat je eigenlijk zelf je versie kan achterhalen op welke manier dan ook. In dit voorbeeld verwacht ik in de route de versie (bijvoorbeeld “v1” of “v2”) meteen na de “api/”.

Als alles nu goed gedaan is zou je weer naar “swagger/ui” moeten kunnen navigeren en “v1” naar “v2” kunnen wijzigen in de URL die naar het swagger.json bestand wijst en vervolgens op “Explore” kunnen klikken zodat je versie 2 van de “About” action method uit kan proberen:

figure5_swaggerui

Complexe Modellen

Dit is allemaal prima, maar echte API’s hebben vaak complexere use cases waar de action method een object verwacht en wellicht een object retourneert. Laten we de volgende twee classes toevoegen zodat we kunnen zien hoe dit in Swagger er uit ziet:

Voeg de volgende action method toe aan HomeController:

Start de web applicatie en navigeer naar “swagger/ui”. Merk op dat “GiveMeSomething” ontdekt is. Zie ook hoe er gezien is dat het een parameter nodig heeft genaamd “something”. Bekijk “Model Schema” rechts, klik op de beschrijving om het toe te voegen als waarde voor de parameter “something”. Vervang de waardes en klik op “Try it out!” en als alles goed is gegaan moet je het volgende zien:

figure6_swaggerui

Kanttekening: Zie hoe Swagger de name gebruikt die via de JSON attributen boven de properties zijn gedefinieerd.

XML notaties toevoegen

Tot dusver is de documentatie verder niet echt omschrijvend geweest. Gelukkig kan Swashbuckle gebruik maken van XML commentaar boven classes, properties en methods en toevoegen aan het Swagger document. Eerst vinken we “Produce outputs on build” aan in de “Build” tab van de properties van het project:

figure7_produceoutputsonbuild

Dit zal het bestand creëren met alle XML commentaar er in, welk Swashbuckle kan gebruiken om het document mee te genereren. Om dit voor elkaar te krijgen moeten we een zogenaamde operation filter toevoegen via ConfigureSwaggerDocument als volgt:

Dit voegt alle XML commentaar boven action methods in controllers toe. Om echter de XML commentaar boven properties van classes toe te voegen moet de volgende code aan de ConfigureServices method in de StartUp class toegevoegd worden.

Kanttekening: De variabele _outputPath is het pad naar mijn output folder en mijn project heet MyWebApiHasSwagger. Pas dit aan naar je eigen situatie.

De ConfigureSwaggerSchema extension method is voor alle schema gerelateerde configuratie, daarom is deze method nodig voor de classes die gebruikt worden. Voeg XML commentaar toe aan de controllers and classes als volgt:

public class HomeController: Controller { ///

/// [HttpGet(“api/v1/About”)] public ContentResult About() { return Content(“An API to sample Swagger with Swashbuckle in ASP.NET Core.”); } ///

/// /// [HttpPost(“api/v1/GiveMeSomething”)] public IActionResult GiveMeSomething([FromBody] Something something) { return Ok(new SomeResponse() { SomeResponseInt = something.SomeInt, SomeResponseString = something.SomeString }); } ///

/// [HttpGet(“api/v2/About”)] public ContentResult About2() { return Content(“An API (v2) to sample Swagger with Swashbuckle in ASP.NET Core.”); } } ///

public class Something { ///

[JsonProperty(“someint”)] public int SomeInt { get; set; } ///

[JsonProperty(“somestring”)] public string SomeString { get; set; } } ///

public class SomeResponse { ///

[JsonProperty(“someresponseint”)] public int SomeResponseInt { get; set; } ///

[JsonProperty(“someresponsestring”)] public string SomeResponseString { get; set; } }

En als je de web applicatie opstart en navigeert naar “swagger/ui” zou je het volgende moeten zien:

figure8_xmlcomments

Let er alsjeblieft op dat in bovenstaand screenshot “Model” is aangeklikt en niet “Model Schema” onder “Data Type” om het XML commentaar zichtbaar te maken. Merk ook het XML commentaar nu op achter de relatieve URL’s van de action methods.
We zijn bijna klaar met de basis, maar voordat dit artikel klaar is moeten we toch echt ook nog even aandacht besteden aan de response, welk op dit moment minimal is.

Meerdere Responses

Wat als we de “GiveMeSomething” action method aan zouden passen zodat het “SomeInt” zou checken en indien die minder dan 50 is een BadRequest laten retourneren, als volgt:

/// /// [SwaggerResponse(HttpStatusCode.OK, “Something’s id is <= 50 and is approved.”, typeof(SomeResponse))] [SwaggerResponse(HttpStatusCode.BadRequest, “Something’s id is > 50 and is denied!”, typeof(SomeResponse))] [HttpPost(“api/v1/GiveMeSomething”)] public IActionResult GiveMeSomething([FromBody] Something something) { if (something.SomeInt <= 50) { return Ok(new SomeResponse() { SomeResponseInt = something.SomeInt, SomeResponseString = something.SomeString }); } else { return new BadRequestObjectResult(new SomeResponse() { SomeResponseInt = 0, SomeResponseString = string.Empty }); } }

Nu retourneert deze action method twee mogelijke responses, een OK status en een BadRequest. Om voor Swashbuckle dit gegeven bruikbaar te maken voor in de documentatie moeten de SwaggerResponse attributen erboven gezet worden. Die accepteren een status code waarop ze reageren en een optioneel beschrijven en een optionele type response. En als je dus een type opgeeft dan is Swashbuckle in staat om het XML commentaar in de betreffende class toe te voegen aan de documentatie. Start de web applicatie op, navigeer naar “swagger/ui” en het volgende zou te zien moeten zijn:

figure9_multipleresponses

Eerst zie je “”Response Class (Status 200)” direct onder de relatieve URL “/api/v1/GiveMeSomething”. Het XML commentaar voor “someresponseint” en “someresponsestring” is zichtbaar. En onder de “Parameters” sectie zie je de “Response Messages” sectie waar alle overige responses opgesomd worden. In dit geval zien je de http status code 400 en de beschrijving onder “Reason” en het XML commentaar van “Respone Model”.

Outro

Dit zijn in vogelvlucht de basis features van Swagger met Swashbuckle en ASP.NET Core wat je een vliegende start zou moeten geven. Veel succes met het automatisch documenteren van je eigen Web API in ASP.NET Core met behulp van Swagger en Swashbuckle!

 

Wil je meer lezen van Danny van der Kraan? Bezoek zijn eigen site dan hier: https://dannyvanderkraan.wordpress.com/about/

Want to read this article in English? You can do so here.

 

Reacties (4)

  1. Richard Nobel schreef:

    Interessant artikel Danny! Duidelijk opgezet met lekker veel screenshots en code-voorbeeldjes.
    Ook goed dat je even waarschuwt voor de naamgeving (gebruik van een punt aan het einde) wanneer het project draait op Microsoft’s IIS webserver. Diverse keren heb ik al ‘ruzie’ gehad met IIS op dat vlak 😉 (in “gewone” MVC projecten, nog zonder WebAPI).

    Een paar maanden terug probeerde ik ASP.NET Core in combinatie met AngularJS v2. Dat voelde allemaal nog erg beta aan. 😕 Inclusief de bijbehorende tooling in Visual Studio 2015. Maar ik ga er vanuit dat in de tussentijd een hoop verbeterd zal zijn. Dus binnenkort eens ’n nieuwe poging wagen. In elk geval hoef ik zo minder te documenteren wat betreft de Web API 🙂

    Bedankt voor deze kennismaking met Swagger en Swashbuckle.

    1. Hey Richard,

      Jij bedankt voor die lovende woorden! Echt top, bedankt!

      Ben benieuwd naar je bevindingen met Angular 2 en .Core!

      Laat het me weten of het nu een betere ervaring is. 😉

  2. Sergi Papaseit schreef:

    Tof artikel Danny!

    Ik heb pas een maand of 5 geleden Swagger ontdekt en ik was meteen gehoekt. Gelijk op alle projecten toegepast. En Swagger UI is een echte life-saver wat API calls testen betreft.

    Ik had me nog niet verdiept in de mogelijkheid tot API versioning te configureren; dus bedankt voor een duidelijke uitleg.

    Hele goede post, hopelijk gaan hierdoor veel meer mensen snel met Swagger aan de gang!

    1. Hey Sergi,

      Bedankt voor je toffe reactie. Echt leuk! Ik ben gewoon blij als mensen wat hebben aan mijn blog, dus mijn dag kan niet meer stuk.

      Veel plezier nog met het gebruik van Swagger!

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

Meer weten over onze werkwijze en dienstverlening? Neem gerust contact met ons op!