Versionando tu API en .NET Core
Tags: csharp, aspnetcore, dotnet, programming
Published: 2020-12-03 08:29:53

Muchas veces nos hemos topado con la necesidad de tener que cambiar el comportamiento o payload de un endpoint de nuestra API. Para estos casos, lo recomendable es tener un versionado de nuestras APIs.

## ¿Por qué versionar tu API?

Si tu API es usada por una web sobre la cual tienes control, no hay problema ya que tenemos poder para cambiar esta web acorde a los requerimientos de nuestra api. 

Por otro lado, si esta API es consumida por una APP Mobile donde es necesario una actualización de la APP por parte del usuario, o la API es consumida por aplicaciones de terceros sobre la cual no tenemos control, es importante tener un versionado.

## ¿Cómo versionamos?

Para versionar tu API en .NET Core hacemos lo siguiente:

- En el proyecto de la API, instalar el siguiente nuget:

```powershell
Install-Package Microsoft.AspNetCore.Mvc.Versioning
```

- En el método `ConfigureServices()` del archivo `startup.cs` del proyecto de la API, poner el siguiente código:

```csharp
 services.AddApiVersioning(x =>
            {
                x.DefaultApiVersion = new ApiVersion(1, 0);
                x.AssumeDefaultVersionWhenUnspecified = true;
                x.ReportApiVersions = true;
                x.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
            });
```
Donde:
&nbsp;&nbsp;`x.DefaultApiVersion` -> indica la versión por defecto de la API. 
&nbsp;&nbsp;`x.AssumeDefaultVersionWhenUnspecified` -> indica si se usará la versión por defecto de la API cuando en el header del request no indiquemos la versión de la API que queremos usar.
&nbsp;&nbsp;`x.ReportApiVersions` -> indica si queremos mostrar a los consumers las versiones disponibles de la API.
&nbsp;&nbsp;`x.ApiVersionReader` -> indica la forma de como vamos a enviar la versión de API en el request. 

En nuestro caso, enviaremos la versión de nuestra API por el Header, de esta manera evitamos que las aplicaciones que usen la API no tengan que modificar sus llamadas, además le añadimos un punto más de seguridad al enviarlo de esta manera en vez de por querystring por ejemplo.

## Añadiendo el versionado a tus controllers

Para añadir el versionado a tus controllers, lo único que tiene que hacer es añadirle el decorado `[ApiVersion("X.0")]`, donde `X.0` será el número de versión que quieres dar a tu controller. En caso de que tu controller no tenga este decorado, la API asumirá que será la versión por defecto (en nuestro caso la "1.0").

**Controller sin versionado**
```csharp
    [Route("api/[controller]")]
    [ApiController]
    public class DemoController : ControllerBase
    {
        [HttpGet]
        public IActionResult GetDemo()
        {
            return Content("Hola desde la versión por defecto");
        }
    }
```

**Controller con versionado**
```csharp
    [Route("api/[controller]")]
    [ApiController]
    [ApiVersion("2.0")]
    public class DemoController : ControllerBase
    {
        [HttpGet]
        public IActionResult GetDemo()
        {
            return Content("Hola desde la versión 2");
        }
    }
```

## Testeando el versionado con Postman

#### Llamando a tu API sin especificar la versión de la API en el Header

Por defecto cogerá el endpoint del controller que no se ha especificado la versión.

 ![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/nu19i8q79fi02nw9hcvr.JPG)


#### Llamando a tu API especificando la versión 1.0 de la API en el Header

Volverá a coger el endpoint del controller que no se ha especificado la versión ya que la versión 1.0 es igual al valor por defecto que hemos puesto en la configuración del versionado.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/crwvl3pwtea7x1j4rogw.JPG)

#### Llamando a tu API especificando la versión 2.0 de la API en el Header

En este caso devuelva una respuesta diferente ya que va al controller que tiene esta versión como decorado.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/a279apqohl8p10hc2gms.JPG)

#### Llamando a tu API con una versión que no existe

Si se llama la API con una versión que no existe, esta devolverá "por defecto" un BadRequest(400) indicando que no soporta este número de versión

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/k507zlmpu23by21kyhds.JPG)

Además que en el header del response, la API te informará las versiones disponibles que puedes usar, siempre y cuando hallas establecido el valor de `ReportApiVersions` a true en la configuración

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/w4r1skptoms2g1zo8va1.JPG)

Y con esto ya tenemos nuestra api versionada. Dejo por aqui el repo de Github por si quieres testearlo.

https://github.com/jhonmarmolejo/NetCoreApiVersionDemo/tree/feature/ApiWithSwagger

Hasta la próxima!!