Web API Server Controllers

  1. Inleiding
  2. API
  3. ASP .NET Web API
    1. .Net Framework en .Net Core
    2. Client
    3. Web API Server Controller
  4. Hosted Solution
    1. Model Definition
    2. Web API Server Controller
      1. Helper Methods
      2. URL
      3. Postman
    3. Client Razor Component
  5. Slot

up

Inleiding

Web APIs spelen een belangrijke rol in een web applicatie, maar wat zijn het? API staat voor “Application Programming Interface” en in deze post gaan we in op wat APIs zijn, hoe je ze bouwt en hoe een Blazor web applicatie gebruik kan maken van een Web API. De voorbeeldcode kun je in deze GitHub repository vinden.

up | down

API

Een Application Programming Interface (API) is een interface waarmee communicatie en gegevensuitwisseling tussen verschillende stukken software mogelijk is.

APIs zijn er in allerlei soorten en maten en zo kan bijvoorbeeld een application programming interface bestaan tussen de software op je smartphone en de firmware* op je Internet of Things (IOT) koelkast.

*firmware = in hardware ingeprogrammeerde software.

Een ander voorbeeld is de firmware op de hardware onderdelen van een computer zoals de BIOS en de software van het besturingssysteem op die computer. Ook daar zijn application programming interfaces aanwezig.

In web applicaties hebben we Web APIs waarbij gebruik wordt gemaakt van de Hypertext Transfer Protocol (HTTP) voor de benodigde communicatie.

Web applicaties zitten verweven in een Client/Server-architectuur en bij een Client/Server-architectuur doet de client een verzoek naar de server. De server voert het verzoek uit waarbij de client het gewenste terugkrijgt.

De API is in het gehele verhaal een soort schil die dingen afdekt voor de betrokken partijen. Je kunt het vergelijken met een situatie in een restaurant. Jij bent als klant de client en de ober is de API, zijnde het doorgeefluik naar de keuken. Je geeft je bestelling door aan de ober en hij geeft de bestelling op zijn beurt weer door aan de keuken. Het eindresultaat is uiteindelijk het bestelde gerecht dat op je tafel terecht komt.

Jij (client) weet niet hoe de keuken (server) eruit ziet en hoe het gerecht bereid wordt (en misschien is dat maar beter ook). De keuken is voor jou afgeschermd middels de ober (API).

up | down

ASP .NET Web API

.Net Framework en .Net Core

ASP.NET Web API is een framework dat bovenop het .NET Framework draait. Met ASP .NET Web API kunnen web API server controllers gebouwd worden waarbij de server controllers aangeroepen worden via een Web Application Interface (Web API).

ASP .NET Web API begon met ASP .Net Web API 1.0 welke voor het eerst werd ondersteund door .NET Framework 4.0 en Visual Studio 2010. Een nieuwe versie volgde twee jaar later met ASP. Net Web API 2 die voor het eerst werd ondersteund door .NET Framework 4.5 en Visual Studio 2012.

ASP.NET Web API is sinds ASP .Net Core geen apart framework meer, maar geÏntegreerd in ASP .Net Core.

up | down

Client

Het achterliggende idee van een web API server controller is dat zij benaderd kan worden door verschillende clients.

De web API server controllers staan op een web server en ze hebben een web API waarbij verzoeken naar de server controllers via die web API gaan. De verzoeken hebben een Uniform Resource Locator (url) formaat en het verzoek naar een web API server controller kan bijvoorbeeld als een url in de adresbalk van de browser geplakt worden waarmee de browser de client is.

Een browser biedt wat minder mogelijkheden voor wat betreft het testen van een web API server controller. Tools zoals Postman en Fiddler lenen zich daar beter voor waarbij de tool de client is.

Maar voor een “echte” client met bijbehorende uitgebreide UI (User Interface) kan bijvoorbeeld C# gebruikt worden in het geval van een Blazor Web Assembly client. En dat is weer anders dan bij bijvoorbeeld een Angular web applicatie client. Voor zo’n client zal TypeScript gebruikt moeten worden.

Wie de client ook mag zijn en wat je ook moge gebruiken voor de bouw van je client, het zou voor de web API server controller niet uit moeten maken. Alle clients benaderen via eenzelfde web Api de web API server controller waarbij een universeel berichtformaat wordt gebruikt voor de uitwisseling van data (JSON of XML).

up | down

Web API server controller

De server controller zelf kan gebouwd worden in C#, maar andere programmeertalen zoals Java en Php kunnen ook gebruikt worden voor de bouw van een server controller. Voor de clients zou dat ook niet uit moeten maken. De clients gebruiken een bepaalde web API en wat daarachter hangt, dat is de client om het even.

up | down

Hosted Solution

In deze post zullen we het één en ander toelichten aan de hand van een Blazor Web Assembly hosted solution. In Visual Studio 2019 kiezen we voor de Blazor Web Assembly Hosted template.

We zien dan ook een solution met drie projecten waarbij de server project de web API server controllers zal bevatten. Het betreft een hosted solution en de client project zal in zo’n solution dan ook de belangrijkste client worden van de server controllers in de server project.

Wat ook opvalt is dat de server project het opstart project is van de solution en dat is te verklaren uit het feit dat het merendeel van de hosting binnen de server project wordt geregeld.

up | down

Model Definition

We beginnen in de Shared project met het definiëren van klasse definitie Berekening. Deze klasse definitie zal door zowel de web API server controller als door de Blazor Web Assembly client gebruikt worden.

Een Berekening-object wordt in de client Web Assembly geïnstantieerd en gevuld. Het object zal via de web API bij de web API server controller terecht komen waarbij de server controller de waarde in property Teller door de waarde in property Noemer deelt. De uitkomst wordt in property Uitkomst gezet waarna de server controller het object weer terugstuurt naar de client.

In real life zal je een deling natuurlijk niet op bovenvermelde omslachtige manier doen. Het gaat in dit voorbeeld om het laten zien hoe we als client een object kunnen aanbieden aan een web API server controller waarbij de server controller het object met de gewenste toevoegingen weer aan ons teruggeeft.

up | down

Web API server controller

We creëren in de server project een web API server Controller (dus geen MVC Controller):

Web API server controller BerekeningController ziet er als volgt uit:

De server controller krijgt van de client een uit te voeren Task die asynchroon uitgevoerd kan worden zodat de client in die tussentijd wat anders kan doen. De server geeft de task na de uitvoering weer terug aan de client met datgene wat de client wil.

De taak bevat verder een zogenaamde generieke “ActionResult<T>” en de ActionResult bestaat weer uit een Berekening-object en het gaat ons uiteindelijk om dat object, want we willen met dat object iets doen.

up | down

Helper Methods

De server controller kan gebruik maken van diverse helper methods welke implementaties zijn van de ActionResult en waarbij een specifieke HTTP Status Code wordt geretourneerd naar de client.

We gebruiken helper methode Ok() voor het scenario waarin alles goed gaat. Helper method Ok() zal een HTTP Status Code 200 retourneren waarmee wordt aangegeven dat alles goed is gegaan en dat het verzoek van de client naar behoren is uitgevoerd.

[HttpPost]
[Route("DoeBerekening")]
public async Task<ActionResult
<Berekening>> DoeBerekening(Berekening berekening)
{
   try
   {
    berekening.Uitkomst = 
    Math.Round(berekening.Teller / berekening.Noemer, 2);
    await Task.Delay(0);
    return Ok(berekening);
   }

   catch(Exception e)
   {
    return Problem(
    statusCode: 
       (int)HttpStatusCode.InternalServerError, 
    detail: 
      "Er is iets fout gegaan met uw berekening: " + 
       e.Message);
   }
}

We krijgen een Exception voor het scenario waarin dingen niet gaan zoals verwacht (de unhappy path). Bijvoorbeeld als de noemer de waarde nul bevat en we vervolgens proberen te delen door nul. We maken voor deze “unhappy path” dan ook gebruik van helper method Problem() waarbij een error object naar de client wordt gestuurd.

De klassendefinitie van de error object moet bij zowel de client als de server bekend zijn en we definiëren klassendefinitie Fout dan ook in de Shared project:

up | down

URL

Web API server controller BerekeningController kunnen we nu benaderen. Via een web API worden de verzoeken naar de server controller gestuurd waarbij voor de daadwerkelijke communicatie gebruik wordt gemaakt van de Hypertext Transfer Protocol (HTTP).

Verzoeken naar de web API server controller worden gedaan in een Uniform Resource Locator (url) formaat en het verzoek ziet er als volgt uit: http://localhost:62167/api/Berekening/DoeBerekening

http:
staat voor het feit dat we voor de communicatie gebruik maken van de Hypertext Transfer Protocol (HTTP). Vanuit beveiligingsoogpunt zou je van een secured http (HTTPS) gebruik moeten maken, maar dat doen we in dit voorbeeld even niet.

//localhost:62167
staat voor het gebruikte domein. We demonstreren het één en ander vanuit een ontwikkelomgeving met een IIS Express interne web server waardoor het domein de localhost met een getal is.

/api
Het woord “api” komt terug in de url omdat we bij het optuigen van de server controller dit attribuut hebben gebruikt: [Route(“api/[controller]”)].

Het gebruik van het woord “api” is een conventie om aan te geven dat het een REST web API server controller betreft (wat de server controller BerekeningController ook is). Meer over REST (Representational State Transfer) in deze post over CRUD-action methods.

/Berekening
Dit is de web API server controller die we moeten hebben: de BerekeningController

/DoeBerekening
Dit is de zogenaamde “endpoint” en een endpoint kunnen we beschouwen als het uiteindelijke loket tot welke we ons moeten wenden.

We hebben de web API server controller opgetuigd met attribuut [Route(“DoeBerekening)”] en de DoeBerekening wordt daarmee de “endpoint” die we moeten opgeven om bij de juiste functionaliteit te komen.

Je moet naast de url ook een zogenaamde “verb” (werkwoord) meegeven en we gebruiken in dit geval de POST-verb. De server controller hebben we dan ook opgetuigd met een [HttpPost]-attribuut.

Met een verb geef je aan wat de aard van het verzoek is naar de web API server controller. Met name bij CRUD (Create Read Update Delete)-action methods is dat van belang. Wil je iets toevoegen aan een gegevensbron of wil je juist iets uit die gegevensbron verwijderen? Meer over verbs in deze post over CRUD-action methods.

up | down

Postman

Het verzoek naar de web API server controller bestaat uit een “header” en een “body” en de “body” moet in dit geval een Berekening-object in JSON-formaat bevatten. Als web API server controller BerekeningController een verzoek ontvangt dan gaat hij in de body kijken van het desbetreffende verzoek. In die body moet een Berekening-object in JSON-formaat aanwezig zijn en de server controller gaat daarmee iets doen.

Je kunt een verzoek direct naar een web API server controller sturen door een url in te geven in de adresbalk van de browser, maar we kunnen voor dit specifieke voorbeeld toch geen gebruik maken van de browser.

De browser kent geen mogelijkheden om bij een body-gedeelte te komen en daar moeten we nu juist wel bij. We moeten in de body een Berekening-object zetten welke de BerekeningController nodig heeft voor het doen uitvoeren van het één en ander. Verder moet voor het desbetreffende verzoek een POST-verb gebruikt worden en dat is ook een reden waarom de browser afvalt als client. Tools zoals Postman en Fiddler lenen zich dan ook beter voor de benadering van een web API server controller.

In Postman geven we bij de header van ons verzoek naar de web API server controller bij de Content-Type aan dat we JSON gebruiken:

En we zetten in de body van ons verzoek de Berekening-object waarmee de web API server controller iets moet doen. We hanteren voor het object de JSON-notatie.

We laten het verzoek uitvoeren via Postman en we krijgen het onderstaande terug van de web API server controller. We hebben een HTTP Status Code 200 (OK) ontvangen waarmee wordt aangegeven dat het verzoek naar behoren is uitgevoerd.

We zien ook dat de web API server controller object Berekening heeft teruggegeven waarbij de teller (18) is gedeeld door de noemer (3) en de uitkomst in property Uitkomst is gezet (6):

We doen nogmaals een verzoek naar de web API server controller waarbij we dit in de body zetten:

De noemer heeft nu de waarde nul en bij de server controller zal een exception optreden want “delen door nul is flauwekul”. De web API server controller retourneert n.a.v. de exception een Fout object in de body met daarin wat info waarom het verzoek niet naar behoren is uitgevoerd en een HTTP Status Code 500 (Internal Server Error):

up | down

Client Razor Component

We hebben tot dusver Postman gebruikt om web API server controller BerekeningController aan te roepen, maar we willen de server controller vanuit een “echte” client aanroepen waarbij de client een UI (UserInterface) heeft.

In de client project creëren we dan ook Razor-component BerekenPagina.razor. We gebruiken een @page-directive zodat de Razor-component als een pagina is op te starten vanuit NavMenu.razor. Meer over @page-directives en NavMenu.razor in deze post.

De Razor-component maakt weliswaar gebruik van de browser, maar het is niet de browser die de client is. BerekeningPagina.razor zijnde een Blazor Web Assembly client (met uitgebreide UI) is de client.

We zien nu een formulier waarin we waarden kunnen ingeven voor de Teller en de Noemer. Meer over de <EditForm> in deze post.

We kunnen een validatie inbouwen in de <EditForm> met System.ComponentModel.annotations dat de waarde nul niet geaccepteerd wordt voor de Noemer zodat de web API server controller er nooit mee te maken krijgt. We doen dat in dit geval niet omdat we willen laten zien hoe de web API server controller ermee om moet gaan.

In de “code behind” roepen we de web API server controller aan. We maken voor de aanroep van de Web API gebruik van de HTTPClient-klasse. Meer over HTTPClient in deze post.

Het is niet “best practice” om alles in de “code behind” van een Razor-component te stoppen, maar we doen het deze keer wel omdat het voorbeeld anders te complex wordt. Zie deze post waarin wordt getoond hoe je de componenten van je applicatie via een MVVM design pattern kunt ordenen en wat de voordelen daarvan zijn.

De web API Server Controller geeft aan of hij het verzoek naar behoren heeft kunnen uitvoeren (bijvoorbeeld met HTTP Status Code 200 (OK)). We hebben de <EditForm> “gebind” aan object berekening en we krijgen het object terug van de web API Server Controller zodat we na een refresh kunnen zien wat de web API Server Controller ervan gebakken heeft. In dit voorbeeld delen we 18 door 3 en het resultaat is 6.

De web API zal met een andere HTTP Status Code komen indien hij het verzoek niet naar behoren heeft kunnen uitvoeren. Zo krijgen we een error object terug met een HTTP Status Code 500 (Internal Server Error) als we proberen te delen door nul:

en we laten in BerekenPagina.razor zien wat fout is gegaan:

En in de console:


up | down

Slot

In deze post ben ik ingegaan op Web Application Programming Interfaces (Web APIs). Een application programming interface (API) is een interface waarmee communicatie en gegevensuitwisseling tussen verschillende stukken software mogelijk is.

Microsoft begon in 2010 met ASP.NET Web API zijnde een framework dat bovenop het .NET Framework draaide en waarmee web API server controllers gebouwd konden worden die via een Web Application Interface (Web API) aangeroepen kunnen worden. ASP.NET Web API is sinds ASP .Net Core geen apart framework meer, maar een geïntegreerd onderdeel van ASP .Net Core.

Het één en ander heb ik gedemonstreerd met een Blazor Web Assembly hosted solution. Er wordt gebruik gemaakt van een client server architectuur waarbij de solution bestaat uit een web API server controller in de server project die aangeroepen wordt door een Razor-component in de client project.

Hopelijk ben je met deze posting weer wat wijzer geworden en ik hoop je weer terug te zien in één van mijn volgende blog posts. Wil je weten wat ik nog meer over Blazor heb geschreven? Hit the Blazor button?

up

Laat een reactie achter

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