Hvordan du utvikler et moderne API som tar imot forespørsler og returnerer data til en front-end løsning.

I forrige artikkel så vi på hvordan man kommer i gang med utvikling av webløsninger, med fokus på det som skjer i nettleseren – HTML, CSS og JavaScript. Dette kalles gjerne front-end løsningen, siden det er denne delen av løsningen brukeren faktisk ser. Nå skal vi se mer på hvordan du kan bygge et API som front-end løsningen din kan kommunisere med for å lagre, hente, eller behandle data. Dette kalles gjerne en back-end løsning. Aller først trenger vi å klargjøre noen begreper som går igjen i artikkelen.

Noen begreper

API (Application Programming Interface) brukes som en generell betegnelse på et program som et annet program kan “snakke” med for å få ut, eller lagre informasjon. Ofte snakker vi om REST API’er, dette er den vanligste typen API å utvikle i en moderne webløsning. Ved hjelp av API’er er det også enklere å få systemer til å snakke sammen på tvers av hverandre, f.eks. kan du hente data fra yr.no eller Wikipedia sitt API – eller fra tusenvis av andre API’er som er tilgjengelige på Internett.

HTTP (Hypertext Transfer Protocol) er “protokollen” en nettleser vil bruke når den sender data til/fra en webserver. Alle nettsider lastes ned til nettleseren via HTTP. I en HTTP forespørsel (request) angir man alltid en metode, normalt GET når man henter data, POST når man oppretter, PUT når man endrer, og DELETE når man sletter data.

JSON (JavaScript Object Notation) er en enkel standard for å utveksle datastrukturer i form av tekst. Data som mottas og sendes til et REST API vil normalt være representert som JSON. En datastruktur kan se slik ut i JSON:

{
  "firstname": "Kjetil",
  "surname": "Ek",
  "employer": { 
    "name": "Appex",
    "website": "http://appex.no" 
  }
}

Hvordan brukes et API?

Lesing

Når en front-end løsning (en klient) skal hente data fra et API vil den sende en forespørsel (request) til en webserver som kjører API’et via HTTP. Webserveren, eller API’et, vil tolke forespørselen (requesten), hente data fra en datakilde (ofte en database), behandle dataene, og sende resultatet (response) tilbake til klienten. Typisk vil det fungere slik:

  1. En bruker åpner en nettside som skal vise en liste med bedrifter med mer enn 1000 ansatte
  2. Nettsiden gjør via JavaScript et HTTP-kall (GET) mot en webserver (API’et), f.eks. Brønnøysundregisteret sitt API: http://data.brreg.no/enhetsregisteret/enhet.json?page=0&size=20&$filter=antallAnsatte ge 1000 (request)
  3. Webserveren henter så relevante data fra databasen sin og gjør det om til JSON før den sender svaret tilbake til klienten (response)
  4. Klienten mottar JSON dataene fra serveren, konverterer de til JavaScript objekter, og gjør dette om til HTML som vises på nettsiden.

Lagring

Dersom man skal lagre data til et API, f.eks. hvis man skal registrere en ordre i en nettbutikk, foregår dette omtrent på samme måte, men forskjellen vil være at man da bruker en annen HTTP metode (POST eller PUT). Både data, som front-end løsningen (klienten) har konvertert til JSON, og metode sendes sammen med nettadressen mot webserveren (API’et) slik at den vet hvordan den skal behandle forespørselen (requesten). I retur får man normalt et sett med standard statuskoder som forteller klienten om forespørselen gikk bra eller ikke. Hvis du åpner Chrome Developer Tools (F12) og ser under menypunktet Network vil du se alle forespørslene som startes når du går inn på en nettside, samt statusen på hver forespørsel.

Utviklingen av selve API’et

C#

Det er mange programmeringsspråk og rammeverk som kan brukes for å lage et API, men i denne artikkelen vil jeg fokusere på det vi normalt bruker back-end i Appex, nemlig ASP.Net Web API.

ASP.Net er et rammeverk for utvikling og drift av webløsninger, og Web API er en modul som gjør det enkelt å lage et REST basert API i dette rammeverket. Når du skal programmere en løsning i ASP.Net er det best å bruke verktøyet Visual Studio.

Last ned gratisversjonen Visual Studio Community for å komme i gang: https://www.visualstudio.com/downloads/

Programmeringsspråket som benyttes vil da normalt være C# (uttales C Sharp). Språket kan minne en del om JavaScript som vi så på i forrige artikkel, så hvis du allerede har jobbet med det vil du kjenne igjen en del derfra. C# er noe «strengere» enn JavaScript, og for å kjøre koden må den først kompileres – dette gjøres automatisk når du starter en løsning i Visual Studio. Når koden kompileres vil en del feil fanges opp, f.eks. som når jeg i koden under har satt opp at metoden GetCustomerCount skal returnere et heltall («int»), men faktisk returnerer en tekststreng.

Da går ting galt.

public class CustomerRepository : BaseRepository
{        
    public Customer GetCustomer(int id)
    {
        return db.Customers.FirstOrDefault(x => x.Id == id);
    }
    public int GetCustomerCount()
    {        
        return "mange"; <-- kompileringsfeil
    }        
}

public class Customer
{
    public int Id {get;set;}
    public string Name {get;set;}        
}

ASP.Net rammeverket er relativt omfattende, men det er ganske enkelt å komme i gang. Du bør imidlertid bruke litt tid på det for å forstå oppbygningen av en ASP.Net applikasjon – det er mange forskjellige måter å løse et problem på, og for å vite hvilket alternativ du skal velge må du også kjenne litt til hvilke muligheter rammeverket har.

Lær mer om C# og ASP.Net her:

Web API

Når du lager et API vil du sette opp en API-klasse som normalt har metoder som sammenfaller med HTTP metodene vi har snakket om tidligere: GET, POST, PUT og DELETE. Du angir hvilken HTTP metode som skal brukes, f.eks. [HttpGet], og i tillegg kan du angi hvilken sti (/route) som skal brukes for å starte API-funksjonen, altså hvilken web-adresse som skal benyttes for å få kjørt funksjonen. I eksempelet under har jeg satt opp et API for å hente ut/lagre kundeinformasjon. RoutePrefix brukes her for å angi sti’en som gjelder for hele API’et (/api/customers), som ved GET gir en liste med kunder. På hver funksjon kan vi også legge til parametre som gjør at vi kan ha en GET-funksjon som returnerer én kunde (/api/customers/id):

    [RoutePrefix("api/customers")]
    public class CustomerController : ApiController
    {
        [HttpGet]
        [Route("")]
        public IEnumerable<Customer> Get()
        {
            // hent en liste med kunder
        }
        
        [HttpGet]
        [Route("{id}")]
        public Customer Get(int id)
        {
            // hent kunden med angitt id
        }
        
        [HttpPost]
        [Route("")]
        public void Post([FromBody]Customer customer)
        {
            // lagre den nye kunden til databasen
        }

        [HttpPut]
        [Route("{id}")]
        public void Put(int id, [FromBody]Customer customer)
        {
            // hent kunden med angitt id fra databasen, og oppdater verdiene
        }

        [HttpDelete]
        [Route("{id}")]
        public void Delete(int id)
        {
            // slett kunden med angitt id
        }
    }

Utvikling av en database

I de fleste API’er vil en av oppgavene være å hente og/eller lagre informasjon i en database. Det finnes mange forskjellige databaseløsninger, SQL Server, MySQL, Oracle, PostgreSQL for å nevne noen. Når du jobber med ASP.Net er det enklest å komme i gang med SQL Server. Databaser inneholder tabeller med felter. Hver tabell inneholder så rader med verdier for hvert felt.

I en relasjonsdatabase (som SQL Server) vil du ha relasjoner mellom tabellene, slik at du enkelt kan koble sammen data når du skal hente de ut. Til dette brukes språket SQL. SQL (Structured Query Language) er et språk som brukes for å hente eller oppdatere data i en database. Her er metodene angitt litt annerledes enn i API’ene. Typisk vil du bruke SELECT for å hente data, INSERT for å sette inn, UPDATE for å oppdatere, eller DELETE for å slette data. Med SQL kan du også koble (JOIN) data i forskjellige tabeller, og på den måten samle data fra flere tabeller får de sendes ut.

Nedenfor ser du et eksempel på en SQL spørring som viser en del av mulighetene. Her henter jeg ut en ordre fra en database, kobler den sammen med kundeinformasjon, filtrerer ut ordre basert på en dato, summerer alle ordrelinjene som hører til hver ordre for å finne totalsummen, og til slutt sorterer listen slik at jeg får de største ordrene først:

select o.id as OrderId, a.Id as AccountId, a.Name as AccountName, sum(oi.Sum) as OrderSum
from orders o
join accounts a on o.accountid = a.id
left outer join OrderItems oi on o.id = oi.OrderId
where o.OrderDate >= '2017-01-01'
group by o.id, a.id, a.name
order by sum(oi.Sum) desc

Herlig! :-)

Her har du et grunnleggende kurs rundt databaser og SQL, men som med all programmering; det gjelder å prøve seg frem for å lære hvilke muligheter og begrensninger som finnes: https://www.pluralsight.com/courses/introduction-to-sql

Jeg anbefaler også å laste ned og installere SQL Server Express – dette er gratisutgaven av SQL Server. Når du installerer denne får du også med programmet Management Studio som du kan bruke til å se på tabeller, kjøre SQL spørringer og se på andre deler av databasen din (f.eks. sikkerhetsstyring og lignende).

Last ned SQL Server Express her: https://www.microsoft.com/en-us/sql-server/sql-server-editions-express

Mapping fra database til objekter med Entity Framework

C# er et objektorientert programmeringsspråk (OOP), og det er ikke nødvendigvis et en-til-en-forhold mellom tabellene i databasen din og objektene i API’et ditt. Når du henter data fra en database må du derfor “mappe” dem om til objekter, som igjen kan gjøres om til JSON og returneres fra API’et ditt til klienten. Til dette vil du normalt bruke et ORM verktøy (Object Relational Mapping).

I en ASP.Net applikasjon er det enkleste å bruke Entity Framework til dette – da kan du både opprette tabeller, hente ut data og oppdatere data uten å egentlig skrive noe SQL. Dette er veldig greit når du skal komme i gang – så er det én ting mindre å tenke på…

Med Entity Framework vil vi kunne hente ut de samme dataene som med SQL-spørringen over på denne måten:

var orderData = db.Orders
                .Where(o => o.OrderDate >= new DateTime(2017, 1, 1))
                .Select(o => new
                {
                    OrderId = o.Id,
                    AccountId = o.AccountId,
                    AccountName = o.Account.Name,
                    OrderSum = o.Items.Sum(oi => oi.Sum)
                })
                .OrderByDescending(o => o.OrderSum);

Som du ser har vi her ingen joining som vi hadde i SQL’en over, Entity Framework legger til den automatisk når uttrykket oversettes til vanlig SQL (som skjer i bakgrunnen). Dette kan Entity Framework gjøre fordi tabellene er relatert til hverandre i «modellen» som rammeverket bruker. I tillegg til å hente ut og lagre informasjon fra databaser kan Entity Framework også brukes til å opprette databasetabeller (dette kalles migrations). 

Her kan du lære mer om Entity Framework: https://www.pluralsight.com/courses/entity-framework-6-getting-started

.NET Core

Når du begynner å lære deg .NET vil du fort komme over navnet «.NET Core». Dette er en ny versjon av .NET rammeverket som er utviklet med tanke på å kunne kjøres på flere plattformer. Mens .NET tidligere har vært mest knyttet til Windows kan .NET Core kjøre på både Linux og Mac. Dette er imidlertid fortsatt ganske nytt, så det kan være enklere å komme i gang hvis du bruker det vanlige .NET rammeverket.

Til slutt

Utvikling av et API er relativt enkelt å få til med moderne verktøy, selv om det krever noe grunnkunnskap for å komme i gang. Uansett, som med front-end utvikling lærer du best ved å faktisk programmere noe – finn deg et prosjekt du brenner for og prøv deg frem! Når du behersker både front-end utvikling og back-end utvikling kan du kalle deg fullstack utvikler. Lykke til :-)