Creando un API en Net Core - OpenAPI & Swagger
Tags: csharp, api, dotnet, rest
Published: 2021-02-26 03:24:44

Hi there! 👋

Llegó una nueva parte de esta guía de creación de **APIs** en **_NetCore_**. 

En este artículo veremos cómo incluir _OpenAPI_ en nuestro proyecto.

Si quieren ver el resultado final ejecutándose, pueden bajarlo del [github](https://github.com/andreslozadamosto/MyFirstNetCoreAPI-Tutorial)

Vamos? 

***

# ¿Qué es OpenAPI?
_OpenAPI_ (que ya fue mencionada en nuestro [segundo](https://dev.to/andreslozadamosto/creando-un-api-en-net-core-5-rest-api-3e2l) artículo) es un estándar que predefine como describir o documentar nuestro **API**.

Dejando detalles de lado, _OpenAPI_ define debe existir un archivo en formato _JSON_ o _YAML_ en donde se definan todos lo recursos del API, acciones que se le pueden realizar, información que se debe enviar a cada endpoint y que se puede recibir, etc.

En definitiva, regula todo el aspecto de como escribir ese archivo y por consiguiente, define la forma de documentar nuestro **API** para que otro equipo/persona sepa cómo utilizarlo.

# ¿Qué es Swagger?
_Swagger_ es un proyecto open source que implementa el estándar. El proyecto fue cedido a la Open API Initiative y desde ese momento se transforman en sinónimos.

Hay que diferenciar que uno es el estándar y el otro (Swagger) es una implementación y creación del UI en base al archivo _JSON_/_YAML_ generado.

# Alternativas
En cuanto a especificaciones, tenemos a _[RAML](https://raml.org/)_.

Para reemplazar el UI, tenemos alternativas en donde se destaca _[Redoc](https://redoc.ly/)_.

En este [link](https://nordicapis.com/ultimate-guide-to-30-api-documentation-solutions) podemos ver un listado de opciones al UI de Swagger.

***

# Agregar OpenAPI y Swagger UI a nuestro API

En mundo de .Net Core hay 2 librerías principales, [Swashbuckle](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) y [NSwag](https://github.com/RicoSuter/NSwag). En este caso vamos a utilizar _Swashbuckle_ que es la que desde _.Net 5_ viene incluida por defecto en el template de _APIs_

## Librerías
Agregamos el siguiente paquete de Nuget

```bash
$> dotnet add package Swashbuckle.AspNetCore
```

## Configurando el Startup.cs
Debemos agregar unas líneas en las funciones `ConfigurationServices`

```csharp
services.AddSwaggerGen();
```

Y en `Configure`

```csharp
app.UseSwagger();
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
```

## Customizaciones
_SwaggerUIPodemos agregar información a la documentación, agregar nuestros propios archivos _css_ y _javascript_ para personalizar la pantalla.

### Documentación de XMLDocs

Podemos utilizar nuestra documentación de código por medio de XML Docs para mostrar información en el UI.

Primero debemos indicarle al proyecto que genere el archivo XML con los comentarios de las funciones

```xml
<PropertyGroup>
	<GenerateDocumentationFile>true</GenerateDocumentationFile>
	<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
```

Luego le decimos a _Swagger_ que cargue el archivo

```csharp
services.AddSwaggerGen(c =>
{
	c.SwaggerDoc("v1", new OpenApiInfo { 
		Title = "My First Net Core REST API",
		Version = "v1"
	});

	var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
	var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
	c.IncludeXmlComments(xmlPath);
});
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/393jerntvjfeuzu56uyn.jpg)

### Logo customizado
Podemos agregar customizaciones a la UI para que se adapte a la gráfica de nuestra empresa. Para eso podemos agregar archivos _CSS_, _Javascript_ o bien utilizar un _HTML_ completo personalizado.

Para los cambios básicos (cambio de logo y color del header) solo necesitaremos agregar un _CSS_ nuevo de la siguiente manera

```cshap
app.UseStaticFiles();
app.UseSwaggerUI(c =>
{
	c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyFirstNetCoreWebAPI.WebAPI v1");
	c.InjectStylesheet("/swagger-ui/swagger-custom.css");
});
```

y el archivo css dentro de una nueva carpeta que llamaremos `wwwroot`

```css
.swagger-ui .topbar {
    background-color: #1abc9c;
}

.topbar-wrapper a img[alt="Swagger UI"] {
    display: none;
}

.topbar-wrapper a {
    display: block;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    background: url(apilogo.png) no-repeat;
    width: 300px; /* Width of new image */
    height: 86px; /* Height of new image */
    padding-left: 180px; /* Equal to width of new image */
}


.topbar-wrapper .select-label span {
    color: #212121;
}
```

El previo _css_ nos provee este bonito resultado.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ixxelk8s8iaa2wjsql6p.jpg)

### Información de licencia y autoría
Otra cosa que podemos agregar e importante cuando la **API** es pública es la información de Autoría y Licencia.

```csharp
services.AddSwaggerGen(c =>
{
	c.SwaggerDoc("v1", new OpenApiInfo { 
		Title = "My First Net Core REST API",
		Version = "v1",
		Description = "A simple example ASP.NET Core Web API by Andrés Lozada Mosto, You can find this tutorial here: https://dev.to/andreslozadamosto/creando-un-api-en-net-core-5-intro-2nc2",
		TermsOfService = new Uri("https://example.com/terms"),
		Contact = new OpenApiContact
		{
			Name = "Andres Lozada Mosto",
			Email = string.Empty,
			Url = new Uri("https://github.com/andreslozadamosto"),
		},
		License = new OpenApiLicense
		{
			Name = "Use under MIT licence",
			Url = new Uri("https://choosealicense.com/licenses/mit/"),
		}
	});
});
```

### Definiendo datos requeridos
Podemos utilizar los atributos como _[required]_ para indicar cuáles datos son requeridos por el objeto recibido como parámetro

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/74iegwpbwo1bl127unl0.JPG)

### Tipo de salida 
Algo muy importante es indicar al público target que utilizará nuestro **API** el formato en que recibirá las respuestas. Esto se realiza indicando el _MIME TYPE_ devuelto por el _Action_ del _Controller_.

```csharp
[Produces("application/json")]
```

Este atributo lo podemos utilizar a nivel de Clase como de Action Method.

Como veremos en artículos posteriores, cuando se llama a un **API** desde un frontend en javascript éste le puede indicar que formato de tipo de respuesta le gustaría recibirf_JSON_, _XML_, otro). **_Net Core_** provee soporte a esta funcionalidad y se pueden registrar cualquier tipo de formarteadores de salida. Pero este tema lo veremos en mayor profundidad en próximos artículos.

### Códigos de HTTP de respuesta [ProducesResponseType]
Otra información muy relevante por los usuarios de nuestra **API** es conocer cuales son los códigos HTTP de respuesta que podemos obtener al realizar un request.

Para documentar esto utilizamos el siguiente atributo a nivel de Action Method

```csharp
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
[ProducesResponseType(StatusCodes.Status201Created)]
```

El enum _StatusCodes_ tiene enumerados para todos los diferentes códigos de respuesta HTTP.

En el UI queda desglosado las diferentes posibles respuestas
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vr38qt2l4idmm73pb734.JPG)


***
# Extra
Hay un mundo de librerías que podemos utilizar junto con _Open API_ tales como generadores de librerías cliente (para consumir nuestro **API** desde cualquier lenguaje), generadores de server stubs, chequeo de seguridad entre otros.

Esta web [https://openapi.tools](https://openapi.tools/) nos provee un gran listado de herramientas organizadas por tema.

***