REST/routes och request-objekt (ASP.NET WebApi serie 1/4)

I den här posten, den första i serien om tre delar, behandlar vi två saker som berör hur ett API ser ut för konsumenten:

  • REST och routes - hur kommer man åt resurserna och vilka operationer kan man göra?
  • Request-objekt - hur föder man API:et med data i sina anrop?

REST och routes

När man bygger sina API:er så kan det vara bra att fundera på vad man vill kunna göra med det. Är det ett funktionellt API? Ska man tillgängliggöra olika resurser med CRUD-operationer? Kommer API:et konsumeras av ett hårt kopplat system, egenutvecklat eller är det ett API öppet för andra att konsumera? Alla dessa frågor är relevanta att fundera igenom ordentligt innan man sätter igång med sina controllers.

I dom flesta fallen bygger man ett API för att exponera någon slags resurs. Ett väldigt bra exempel på detta kan vara ett API för en webbshop som exponerar varor, ordrar, kundinformation etc. När det gäller resursexponerande API:er så hävdar jag bestämt att REST är en designfilosofi att följa, utan egentliga alternativ. Man behöver inte vara 100% strikt i sin REST-lika design, men att hålla sig i anslutning till REST kommer att löna sig i längden.

I dom fallen ett API används i ett funktionellt syfte, dvs. göra beräkningar på givet indata eller morsvarande, så bör man fundera på om det alls ska vara ett API? Man kanske då ska se över möjligheten att bygga ett bibliotek med önskad funktion och inkorporera det i applikationen eller systemet som skulle ha konsumerat det funktionella API:et. Detta beror såklart på miljö, teknik, komplexitet i funktionen etc.

Det finns otroligt mycket läsvärt om REST och routes här på Internet. En enkel googling senare och man har att göra i många dagar framöver.

Request-objekt

Efter man har funderat igenom REST och routes enligt ovan så är det läge att börja koda.

Om man ser till mängden kod ett system består av så bör så lite del av den koden som möjligt ligga i actions i controllers. Ett enkelt sätt att realisera det är genom att skapa bra request-objekt/klasser. Det gäller såklart ett API:s POST- och PUT-routes. Se kod nedan för exempel på detta:

[RoutePrefix("api/vehicles")]
public class VehiclesController : ApiController  
{     
    [HttpPost]
    [Route("")]
    public IHttpActionResult Create(CreateVehicleRequest vehicle)
    {
        // A few lines of code
    }

    [HttpPut]
    [Route("{id}")]
    public IHttpActionResult Update(int id, [FromBody] UpdateVehicleRequest vehicle)
    {
        // A few lines of code
    }
}

I dom två actions ovan skulle man eventuellt kunna återanvända inkommande typ på request-objekten, men underhållet blir i just det här fallet enklare om typerna är skillda åt. Såklart kan man använda arv, men det gäller att vara noga vid ändringar så man inte ställer till med oväntade kontraktsbrott. För att göra koden tydligare så har [FromBody]-attributet lagts till på Update-metoden. Detta är dock inte tvunget, iallafall inte om man använder det fulla .NET-ramverket, t.ex. .NET 4.7.

Förutom att det blir tydligt med request-objekt så fungerar det välidgt bra om man ska dokumentera sitt API. Det gäller både manuell dokumentation och automatisk dito mha. t.ex. Swagger/Swashbuckle (nuget-paket Swashbuckle):

Swagger/Swashbuckle för ASP.NET WebApi

Det här är alltså ett alldeles utmärkt sätt att dokumentera sitt API, men bör såklart användas med försiktighet eftersom man skulle kunna blotta sig fullständigt vid felaktig konfiguration. Det speciellt viktigt att autentisering och auktoriseringen inte äventyras. Läs på ordentligt här https://github.com/domaindrivendev/Swashbuckle.

Tillbaka till introduktionen.