Bouw een web API in 4 klikken

-

Iets meer dan een maand geleden kwam er een klant naar ons toe met de vraag of wij een reactie systeem voor hun intranet konden bouwen. Van te voren leek het een erg lang traject te worden maar met de juiste middelen was het toch snel te realiseren. Op dit moment zijn er al vele honderden reacties geplaatst, met nog meer (dis)likes en worden de reacties enkele duizenden keren per dag opgevraagd. Het ontwikkelen van dit systeem is met veel plezier gebeurd en ik heb veel van dit project geleerd. Wil je weten hoe de ontwikkeling zo snel heeft kunnen gaan en waarom ik er zoveel plezier in heb gehad? Lees snel verder.

Je eigen web API in 4 klikken

Als .NET ontwikkelaar had ik nog nooit een dergelijke opdracht gehad maar deze opdracht was voor mij de ultieme kans om eens kennis te maken met het ‘Web API’ template in Visual Studio.

commentsysteem

Verbazingwekkend hoe je in 4 klikken een klant-en-klare (RESTful!) web API hebt die je out-of-the-box al kunt gebruiken. Om dit te testen kan je via je browser naar localhost:[portnummer]/api/values gaan en dan krijg je een voorbeeld response terug. Deze request staat in de ValuesController. Die kan als voorbeeld gebruikt worden om je eigen request te bouwen.

Response type instellen

Uiteraard wil je als standaard response type JSON hebben, dat kan heel eenvoudig door het volgende aan de Global.asax file toe te voegen:

commentsysteem

Wil je toch gebruikers de mogelijkheid geven om gegevens als XML op te vragen dan doe je dat op de volgende manier (in deizelfde Gobal.asax file):

commentsysteem

Als er nu een request gedaan wordt met de querystring ‘type=xml’ dan wordt er XML teruggeven.

Attributen

Als je er nog nooit mee gewerkt hebt dan ga je dat vanaf nu zeker doen. Attributen zijn namelijk erg eenvoudig te maken en het maakt je code erg ‘clean’, de droom van elke goede (lees luie) ontwikkelaar dus. Tijdens het bouwen van het reactie systeem wilde ik dat mensen alleen over HTTPS requests zouden kunnen doen. Daarvoor heb ik de volgende ActionFilterAttribute aangemaakt:

commentsysteem

(voorbeeld gestolen van: http://www.asp.net/web-api/overview/security/working-with-ssl-in-web-api)

Vervolgens kan je dit eenvoudig toepassen voor elke gewenste request door het attribuut boven de Action methode te plaatsen.

commentsysteem

Je kunt attributen in talloze situaties gebruiken, zo kunnen ze ook gebruikt worden om parameters al van te voren te controleren voordat de request uitgevoerd wordt. Dit kan handig zijn voor het controleren van bijvoorbeeld een meegestuurde hash die je serverside nog eens wil controleren.

commentsysteem

Let op, het gebruik van deze attributen kan verslavend zijn.

Entity Framework, gevaarlijk simpel

Als er één ding is waar .NET ontwikkelaars lyrisch over zijn, dan is het wel Entity Framework (EF). Het wegschrijven van gegevens naar de database en het ophalen kan gewoon níet eenvoudiger. Het gevaar van deze eenvoud is dat je er niet bij nadenkt wat er ‘onder water’ eigenlijk gebeurt. Wat gebeurt er eigenlijk als je onderstaande code uitvoert?

commentsysteem

En maakt het uit of je de context één keer aanmaakt in je controller of eentje voor elke request? En voegt de ToList() nog wat toe? Zelfs als je onderzoek gedaan hebt en denkt de juiste oplossing te hebben voor jouw situatie dan is er nog een valkuil (waar ik met open ogen ingelopen ben).

Er zit namelijk nogal een groot verschil in de versies van EF. Om die reden ga ik hier geen voorbeelden geven van code, dat heeft mij alleen maar misleid. Bovenstaande vragen wil ik wel mee geven zodat je jezelf de juiste vragen stelt.

Wat ik je niet kan onthouden is de grote onbekende SqlAzureExecutionStrategy. Door deze eenvoudige setting aan te zetten in je class die overerft van DbConfiguration zorg je er voor dat veel EF transacties die mislukken automatisch opnieuw geprobeerd worden. Waarbij de eerste parameter staat voor het aantal pogingen die gedaan worden om de transactie toch te laten slagen.

commentsysteem
Omdat elke database-transactie die gedaan wordt een risico heeft van falen is het van belang om altijd te zorgen dat je met zo weinig mogelijk requests toch je doel bereikt en ook ervoor zorgt dat de gebruikers van je applicatie geen onnodige requests kunnen doen. Een voorbeeldje hierbij? Bij het reactie systeem is het mogelijk om reacties een duimpje omhoog of omlaag te geven. Zodra een gebruiker op een van de twee heeft geklikt wordt die button uitgeschakeld (met jQuery). Toen dit er nog niet inzat is het een (flinke) groep testers gelukt om de applicatie omver te trekken, door het wereld-record klikken te vestigen op die ene button. Elke keer dat iemand op de button klikte wordt er gecheckt of deze persoon al gestemd had.

Verder wil ik in dit kader ook het volgende meegeven: cache zoveel mogelijk, zodat je niet onnodig de database aanroept voor dezelfde data. Denk hierbij wel na wat je cachet en wat te gevolgen zijn. Iets wat altijd up-to-date moet zijn kan je niet cachen, zoals een reactie thread. Dat veranderd echter wanneer er besloten is om na een bepaalde tijd de thread te sluiten, dan kan diezelfde thread weer wel gecached worden. Denk hier dus goed over na. Het cachen is uiteraard in de praktijk ook weer makkelijker dan je durft te denken, zie volgende code voorbeeld:

commentsysteem

Log, log ,log

Als laatste wil je nog dit meegegeven, teveel loggen bestaat niet en kan veel hoofdpijn besparen. Als je applicatie een keer omvalt, of dat nou is terwijl je nog aan het ontwikkelen bent of als hij al in productie is genomen, je kan zo vaak eenvoudig herleiden waar het probleem is ontstaan zodat je gelijk met de oplossing aan de slag kunt.

Mijn favoriete library daarvoor is log4net, eenvoudig te installeren via de NuGet Package Manager in Visual Studio. Zelf zet ik het log niveau de eerste paar weken op ‘info’ en controleer dan regelmatig de logs. Als zich dan niets vreemds voor doet dan zet ik hem daarna op ‘error’.

commentsysteem

Ik hoop dat ik je wat hebt kunnen leren van dit artikel, zo niet dan ben ik toch blij dat je onderaan dit artikel gekomen bent. Veel plezier bij het ontwikkelen!