Autor en Google+
Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET, ASP.NET Core, MVC, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

13 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET, ASP.NET Core, MVC, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 28 de enero de 2020
Open API La OpenAPI Specification (OAS) es un estándar abierto para la descripción de APIS REST promovido por la Iniciativa OpenAPI, un consorcio de compañías de primer nivel como Microsoft, Google, IBM, Paypal y otros.

El objetivo de OpenAPI es conseguir una fórmula normalizada para describir las capacidades de un servicio REST, independientemente de los lenguajes o tecnologías con las que sea implementado. Esta descripción, normalmente especificada en formato JSON o YAML, permite a clientes (sean humanos o máquinas) descubrir servicios, comprender sus capacidades y conocer sus detalles de funcionamiento sin necesidad de tener acceso a su código fuente o documentación textual.

Esta especificación formal abre interesantes posibilidades, pues a partir de la definición estandarizada de servicios es posible, entre otros,
  • disponer de herramientas de diseño y modelado de servicios,
  • generar automáticamente páginas de documentación,
  • generar automáticamente código cliente y servidor para dichos servicios para distintos, frameworks y lenguajes de programación,
  • generar automáticamente código de testing y validaciones,
  • o generar automáticamente mocks de servicios.

¿Y qué tiene que ver Swagger en todo esto? Pues bastante, porque Swagger fue la semilla de OpenAPI. De hecho, Swagger era un proyecto liderado por la compañía Smartbear, que definió las dos primeras versiones de la especificación, y luego la donó a la nueva iniciativa abierta OpenAPI, quedando renombrada a partir de ese momento a "OpenAPI Specification". Por tanto, a efectos prácticos, cuando hablamos de la especificación Swagger y de OpenAPI, en muchas ocasiones nos estamos refiriendo a lo mismo.

A partir de la puesta en marcha de la iniciativa OpenAPI, el término Swagger pasó a utilizarse principalmente para denominar el framework o conjunto de herramientas que implementan la especificación, tanto de forma comercial como open source: diseñadores, generadores de código, parsers, generadores de documentación, etc.

La web Swagger.io es el sitio de referencia para las herramientas básicas y open source de Swagger.

Herramientas en Swagger.io

¿Qué pinta tiene la descripción OpenAPI de un servicio?

Imaginemos una API tan simple como la siguiente, creada con ASP.NET Core MVC:
[Route("[controller]")]
public class CalculatorController : ControllerBase
{
    /// <summary>
    /// Divides two numbers
    /// </summary>
    /// <param name="a">The dividend</param>
    /// <param name="b">The divisor</param>
    /// <response code="200">Result of dividing "a" by "b"</response>
    /// <response code="400">It's not possible to divide by zero</response>
    [HttpGet("[action]/{a}/{b}")]
    [Produces("application/json")]
    [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public ActionResult<int> Divide(int a, int b)
    {
        if (b == 0)
        {
            return BadRequest();
        }
        return a / b;
    }
}
La descripción o esquema OpenAPI de este servicio en formato JSON podría ser la siguiente (he añadido algunos comentarios para explicar los principales puntos):
{
  "openapi": "3.0.1",
  "info": {
    "title": "Calculator",
    "version": "v1"
  },
  "paths": {
    "/Calculator/Divide/{a}/{b}": {        // <-- Ruta del endpoint
      "get": {                             // <-- Verbo HTTP
        "tags": [
          "Calculator"
        ],
        "summary": "Divides two numbers",
        "parameters": [
          {
            "name": "a",                   // <-- Parámetro "a"
            "in": "path",
            "description": "The dividend",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "b",                   // <-- Parámetro "b"
            "in": "path",
            "description": "The divisor",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {                         // <-- Retorno 200 OK
            "description": "The result of dividing \"a\" by \"b\"",
            "content": {
              "application/json": {
                "schema": {
                  "type": "integer",
                  "format": "int32"
                }
              }
            }
          },
          "400": {                         // <-- Retorno 400 Bad request
            "description": "It's not possible to divide by zero"
          }
        }
      }
    }
  }
}
Sin duda algo verboso, pero no tenemos que preocuparnos por ello porque vamos a ver algo más adelante que un componente llamado Swashbuckle puede generar esta descripción por nosotros :)

Lo importante es que el contenido es bastante claro y que el servicio queda especificado por completo, al más mínimo detalle.

Describiendo nuestras APIs HTTP

El paquete NuGet Swashbuckle.AspNetCore proporciona componentes para generar de forma automática la descripción OpenAPI de servicios creados con ASP.NET Core. Obviamente tendremos que ayudarlo un poco, como habéis visto en el servicio anterior, por ejemplo introduciendo comentarios o indicando expresamente los tipos de resultado, porque de otra forma este componente no podría aportar tanta información a los clientes.

Pero la ventaja es que esto lo haremos a nivel de código, e incluso disponemos de analizadores estáticos de Open API que nos ayudarán a completar la información que necesitemos para lograr una documentación de calidad.

Para generar automáticamente la documentación de nuestros API, lo primero que debemos hacer es instalar el paquete Swashbuckle.AspNetCore y, tras ello, registrar sus servicios en el inyector de dependencias de ASP.NET Core:
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("api", new OpenApiInfo { Title = "Awesomic calculator", Version = "v1" });
        var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        c.IncludeXmlComments(xmlPath);
    });
    ...
}
En la llamada a SwaggerDoc() establecemos los parámetros esenciales: el nombre que vamos a dar al documento generado, y luego alguna metainformación básica sobre el API, como su nombre descriptivo o versión (ambos aparecerán en la descripción OpenAPI).

A continuación, indicamos al componente dónde puede encontrar el archivo XML con la documentación de clases y métodos, obteniendo primero la ruta correcta y pasándosela al método IncludeXmlComments().

Podemos activar la generación de documentación XML desde las propiedades del proyecto, o bien introduciendo el siguiente bloque en el archivo .csproj (fijaos que el <NoWarn> es sólo para que el sistema no nos avise en otras clases que tengamos sin documentar):
<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
  <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
Tras el registro de servicios, ya sólo tenemos que añadir al pipeline el middleware que se encargará de retornar la descripción del API:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...
    app.UseSwagger();
    ...
}
¡Y esto es todo! Usando la configuración por defecto, una petición a la ruta /swagger/api/swagger.json retornará el esquema de la API según la especificación OpenAPI. Fijaos que ese "api" de la ruta debe corresponder con el nombre que dimos al documento cuando registramos el servicio anteriormente:

Especificación OpenAPI de nuestro servicio

A partir de este momento,ya podremos comenzar a utilizar herramientas que se alimenten de esta definición como Swagger UI o generadores de código, pero, para no extendernos más, lo dejaremos para otro post más adelante :)

Publicado en Variable not found.

Estos contenidos se publican bajo una licencia de Creative Commons Licencia Reconocimiento-No comercial-Compartir bajo la misma licencia 3.0 España de Creative Commons

Aún no hay comentarios, ¡sé el primero!

Artículos relacionados: