A la hora de desarrollar nuestra API, hay algunos aspectos que debemos de tener claros antes de empezar a tirar lineas de código: autenticación, versionado, CORS, nomenclatura, escalado, etc… En este post vamos a a ver cómo versionar nuestra API en ASP.Net Core.
Antes de entrar en materia, vamos a poner un poco de contexto. Tenemos la tarea de desarrollar una API para una organización que va a dar cobertura a determinados requerimientos de negocio.
Esta API se utilizará desde varias aplicaciones, tanto móviles como de escritorio, y desde entornos Windows y No-Windows). Publicamos la primera versión de nuestra API con todos estos requerimientos, la ponemos en producción, y todas estas aplicaciones se ponen a funcionar y a consumirla sin ningún problema. Ahora bien, puede llegar un momento en que surja una nueva necesidad en la organización, o bien cambie alguno de los requisitos de negocio. En este caso, está claro que tenemos que hacer una modificación en nuestra API y quizás alguno de los métodos de las aplicaciones utilizadas hayan cambiado. De ser así, en el momento en que actualicemos las API, es posible que alguna de las aplicaciones que nos consumen dejen de funcionar. ¿Cómo podemos solucionar este problema y no dejar sin servicio a algunos de los clientes de nuestras API?: Versionando nuestra API
Cómo se hacía en versiones anteriores de ASP.NET
En versiones anteriores, el framework no tenía nada de serie para hacer versionados de la API, y para conseguirlo había que hacerlo de forma manual. Dependiendo de las necesidades que tuviera esa API, se implementaban unas rutas en cuya petición se incluía la versión requerida, siguiendo el resto de procesos de forma manual. Un buen ejemplo para saber cómo versionar de forma correcta en versiones anteriores, la escribió Sergio León en el siguiente artículo.
¿Cómo se hace en .NET Core?
Ahora, el equipo de .NET ha publicado un paquete Nuget para facilitarnos todas estas tareas con el versionado de la API. A la consola de ejecución le añadimos el paquete de Nuget donde disponemos un middleware para utilizar en nuestro proyecto:
Dotnet add package Microsoft.AspNetCore.Mvc.Versioning
Con el paquete de Nuget añadido, el siguiente paso es poner este middleware dentro del punto de arranque. Para ello, en el Startup.cs (método ConfigureServices), añadiremos las siguientes líneas:
services.AddApiVersioning(options => { options.ReportApiVersions=true; options.AssumeDefaultVersionWhenUnspecified = true; var multiVersionReader = new HeaderApiVersionReader("x-version"); options.ApiVersionReader= multiVersionReader; options.DefaultApiVersion = new ApiVersion(1, 0); });
Dentro de estas opciones:
– ReportApiVersion -> Indica que en la petición señalamos qué versión de la API soporta la petición que hemos realizado.
– AssumeDefaultVersiónWhenUnspecified ->En caso de que no se notifique la versión en la petición, cómo tratamos dicha petición (si se envía un error o bien si asume la versión por defecto).
– ApiVersiónReader -> Ubicación donde indicamos la versión, ya sea por QueryString o por HeaderAPIVersión
– DefaultApiVersión -> Versión por defecto la API
Ahora bien, al configurar estos parámetros tenemos que tener clara cuál es la estrategia que vamos a dar a los consumidores de nuestra API para consultarla: si será un parámetro de la petición REST, o si vamos a añadir una «header» en dicha petición para seleccionar la versión de la API.
Yo personalmente prefiero utilizar el header. El primer motivo, por seguridad (dar información extra a posibles usuarios no aporta valor). El segundo, es que si hacemos uso de una petición y ésta cambia, tengo que modificar las llamadas en la aplicación que lo consume (como se nota el uso de la API Graph, que cada vez que cambia de versión tengo que llevar a cabo modificaciones en diversas aplicaciones).
Otro de los aspectos que se configuran en el middleware es indicar si asumimos la versión por defecto, en caso de que no venga informada. En este caso, como creador de una API, me parece buena idea partir de dicha base. Ahora bien, como posible consumidor de dicha API, el hacer llamadas sin versionar puede ocasionar problemas en la llamada, ya que si la API modifica la devolución de la misma, esto ocasiona que mi aplicación deje de funcionar.
Una vez tenemos el middleware configurado, el siguiente paso sería añadir la versión que vamos a utilizar dentro de cada controlador de nuestra WebAPI.
[ApiVersion("2.0")] public class StarWarsController : Controller {
En caso de que queramos poner la versión en la llamada de la petición, lo haríamos bajo el Atributo Route, de la siguiente forma:
[ApiVersion( "1.0" )] [Route( "api/v{version:apiVersion}/[controller]" )] public class HelloWorldController : Controller { public string Get() => "Hello world!"; }
Otro de los aspectos que nos proporciona este paquete de Nuget es poder indicar que un método esta deprecated y que pase a utilizar otra versión. Para ello, bastaría con poner lo siguiente en la cabecera de dicho método:
[ApiVersion( "2.0" )] [ApiVersion( "1.0", Deprecated = true )]
Añadiendo esto en la devolución de la petición, se devolverá en los headers lo siguiente:
Conclusión
El versionado de la API es algo muy importante y que debemos de plantearnos desde el minuto cero de la creación de la API.
Está claro que el utilizar esta librería de Nuget nos ahorra muchos quebraderos de cabeza a la hora de mantener una comunicación con nuestros clientes. Pero independientemente de si utilizamos la librería o no, debemos tener clara la estrategia a seguir.
Esta librería nos facilita la comunicación entre la API y sus consumidores, sin embargo, debemos tener en cuenta cómo vamos a llevar el versionado del resto del backEnd. Por ejemplo, si añadimos un nuevo identificador sobre la base de datos y esto provoca que la versión anterior deje de funcionar. En este caso, debemos tener en cuenta si ésto lo vamos a soportar o no. Otros aspectos que también hay que prever, es a cuántas versiones anteriores se da soporte y cuál es la política de incremento de versión de la API (si voy a subir de versión cuando haya un nuevo requisito, o bien cuando haya una nueva Feature).
Y vosotros, ¿cómo versionáis vuestra API?
Happy Codding 🙂