Introducción a NSwag y ASP.NET Core

Por Christoph Nienaber, Rico Suter y Dave Brock

NSwag ofrece las siguientes capacidades:

  • Capacidad de usar la interfaz de usuario y el generador de Swagger.
  • Capacidad de generar código con flexibilidad.

Con NSwag, no es necesario que exista una API; se pueden usar API de terceros que incluyan Swagger y que generen una implementación de cliente. NSwag permite acelerar el ciclo de desarrollo y adaptarse fácilmente a los cambios de API.

Registro del middleware de NSwag

Registre el middleware de NSwag para:

  • Generar la especificación de Swagger para la API web implementada.
  • Proporcionar la interfaz de usuario de Swagger para examinar y probar la API web.

Para usar NSwag con middleware de ASP.NET Core, instale el paquete NuGet NSwag.AspNetCore. Este paquete contiene el middleware para generar y proporcionar la especificación de Swagger, la interfaz de usuario de Swagger (v2 y v3) y la interfaz de usuario de ReDoc.

Use uno de los siguientes métodos para instalar el paquete NuGet de NSwag:

  • En la ventana Consola del Administrador de paquetes:

    • Vaya a Vista > Otras ventanas > Consola del Administrador de paquetes.

    • Vaya al directorio en el que está TodoApi.csproj.

    • Ejecute el siguiente comando:

      Install-Package NSwag.AspNetCore
      
  • En el cuadro de diálogo Administrar paquetes NuGet:

    • Haga clic con el botón derecho en el proyecto en el Explorador de soluciones > Administrar paquetes NuGet.
    • Establezca el origen del paquete en "nuget.org".
    • Escriba "NSwag.AspNetCore" en el cuadro de búsqueda.
    • Seleccione el paquete "NSwag.AspNetCore" en la pestaña Examinar y haga clic en Instalar.

Agregar y configurar el middleware de Swagger

Para agregar y configurar Swagger en su aplicación de ASP.NET Core, realice los siguientes pasos:

  • En el método Startup.ConfigureServices, registre los servicios necesarios de Swagger:
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TodoContext>(opt =>
        opt.UseInMemoryDatabase("TodoList"));
    services.AddMvc();

    // Register the Swagger services
    services.AddSwaggerDocument();
}
  • En el método Startup.Configure, habilite el middleware para servir la especificación y la interfaz de usuario de Swagger:
public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles();

    // Register the Swagger generator and the Swagger UI middlewares
    app.UseOpenApi();
    app.UseSwaggerUi3();

    app.UseMvc();
}
  • Inicie la aplicación. Vaya a:
    • http://localhost:<port>/swagger para ver la interfaz de usuario de Swagger.
    • http://localhost:<port>/swagger/v1/swagger.json para ver la especificación de Swagger.

Generación de código

Para aprovechar las capacidades de generación de código de NSwag, elija una de las siguientes opciones:

Generación de código con NSwagStudio

  • Instale NSwagStudio siguiendo las instrucciones del repositorio de GitHub de NSwagStudio. En la página de la versión NSwag, puede descargar una versión de XCOPY que se puede iniciar sin privilegios de administrador y de instalación.

  • Inicie NSwagStudio y escriba la URL del archivo swagger.json en el cuadro de texto Swagger Specification URL (URL de especificación de Swagger). Por ejemplo, http://localhost:44354/swagger/v1/swagger.json .

  • Haga clic en el botón Create local Copy (Crear copia local) para generar una representación JSON de la especificación de Swagger.

    Creación de una copia local de la especificación de Swagger

  • En el área Salidas, haga clic en la casilla CSharp Client (Cliente de CSharp). En función del proyecto, también puede elegir TypeScript Client (Cliente de TypeScript) o CSharp Web API Controller (Controlador de API web de CSharp). Si selecciona CSharp Web API Controller (Controlador de API web de CSharp), una especificación de servicio volverá a generar el servicio a modo de generación inversa.

  • Haga clic en Generate Outputs (Generar salidas) para producir una implementación completa del cliente de C# del proyecto TodoApi.NSwag. Para ver el código de cliente generado, haga clic en la pestaña CSharp Client (Cliente de CSharp):

//----------------------
// <auto-generated>
//     Generated using the NSwag toolchain v12.0.9.0 (NJsonSchema v9.13.10.0 (Newtonsoft.Json v11.0.0.0)) (http://NSwag.org)
// </auto-generated>
//----------------------

namespace MyNamespace
{
    #pragma warning disable

    [System.CodeDom.Compiler.GeneratedCode("NSwag", "12.0.9.0 (NJsonSchema v9.13.10.0 (Newtonsoft.Json v11.0.0.0))")]
    public partial class TodoClient
    {
        private string _baseUrl = "https://localhost:44354";
        private System.Net.Http.HttpClient _httpClient;
        private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;

        public TodoClient(System.Net.Http.HttpClient httpClient)
        {
            _httpClient = httpClient;
            _settings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(() =>
            {
                var settings = new Newtonsoft.Json.JsonSerializerSettings();
                UpdateJsonSerializerSettings(settings);
                return settings;
            });
        }

        public string BaseUrl
        {
            get { return _baseUrl; }
            set { _baseUrl = value; }
        }

        // code omitted for brevity

Sugerencia

El código de cliente de C# se genera en función de las selecciones en la pestaña Settings (Configuración). Modifique esta configuración para realizar tareas como cambiar el nombre del espacio de nombres predeterminado y generar un método sincrónico.

  • Copie el código de C# generado en un archivo del proyecto de cliente que usará la API.
  • Empiece a consumir la Web API:
 var todoClient = new TodoClient();

// Gets all to-dos from the API
 var allTodos = await todoClient.GetAllAsync();

 // Create a new TodoItem, and save it via the API.
var createdTodo = await todoClient.CreateAsync(new TodoItem());

// Get a single to-do by ID
var foundTodo = await todoClient.GetByIdAsync(1);

Personalización de la documentación de API

Swagger proporciona opciones para documentar el modelo de objetos de cara a facilitar el consumo de Web API.

Información y descripción de la API

En el método Startup.ConfigureServices, la acción de configuración que se pasa al método AddSwaggerDocument agrega información, como el autor, la licencia y la descripción:

services.AddSwaggerDocument(config =>
{
    config.PostProcess = document =>
    {
        document.Info.Version = "v1";
        document.Info.Title = "ToDo API";
        document.Info.Description = "A simple ASP.NET Core web API";
        document.Info.TermsOfService = "None";
        document.Info.Contact = new NSwag.OpenApiContact
        {
            Name = "Shayne Boyer",
            Email = string.Empty,
            Url = "https://twitter.com/spboyer"
        };
        document.Info.License = new NSwag.OpenApiLicense
        {
            Name = "Use under LICX",
            Url = "https://example.com/license"
        };
    };
});

La interfaz de usuario de Swagger muestra información de la versión:

Interfaz de usuario de Swagger con información de la versión

comentarios XML

Para habilitar los comentarios XML, realice los siguientes pasos:

  • Haga clic con el botón derecho en el Explorador de soluciones y seleccione Editar <nombre_de_proyecto>.csproj.
  • Agregue manualmente las líneas resaltadas al archivo .csproj:
<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
  <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
  • En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Propiedades.
  • Active la casilla Archivo de documentación XML en la sección Salida de la pestaña Compilar.

Anotaciones de datos

Dado que NSwag usa Reflection y el tipo de valor devuelto recomendado para acciones de API web es IActionResult, no puede inferir su acción ni el valor que devuelve.

Considere el ejemplo siguiente:

[HttpPost]
public IActionResult Create([FromBody] TodoItem item)
{
    if (item == null)
    {
        return BadRequest();
    }

    _context.TodoItems.Add(item);
    _context.SaveChanges();

    return CreatedAtRoute("GetTodo", new { id = item.Id }, item);
}

La acción anterior devuelve IActionResult pero, dentro de la acción, devuelve CreatedAtRoute o BadRequest. Use las anotaciones de datos para indicar a los clientes qué códigos de estado HTTP se sabe que esta acción devuelve. Marque la acción con los siguientes atributos:

[ProducesResponseType(typeof(TodoItem), StatusCodes.Status201Created)]  // Created
[ProducesResponseType(StatusCodes.Status400BadRequest)]                 // BadRequest

Dado que NSwag usa Reflection y el tipo de valor devuelto recomendado para acciones de API web es ActionResult<T>, solo puede inferir el tipo de valor devuelto definido por T. No puede inferir automáticamente ningún otro tipo de valor devuelto.

Considere el ejemplo siguiente:

[HttpPost]
public ActionResult<TodoItem> Create(TodoItem item)
{
    _context.TodoItems.Add(item);
    _context.SaveChanges();

    return CreatedAtRoute("GetTodo", new { id = item.Id }, item);
}

La acción anterior devuelve ActionResult<T>. Dentro de la acción, se devuelve CreatedAtRoute. Dado que el controlador tiene el atributo [ApiController], también es posible una respuesta BadRequest. Para obtener más información, consulte Respuestas HTTP 400 automáticas. Use las anotaciones de datos para indicar a los clientes qué códigos de estado HTTP se sabe que esta acción devuelve. Marque la acción con los siguientes atributos:

[ProducesResponseType(StatusCodes.Status201Created)]     // Created
[ProducesResponseType(StatusCodes.Status400BadRequest)]  // BadRequest

En ASP.NET Core 2.2 o versiones posteriores, puede usar las convenciones en lugar de decorar explícitamente acciones individuales con [ProducesResponseType]. Para obtener más información, vea Uso de convenciones de API web.

Ahora, el generador de Swagger puede describir con precisión esta acción y los clientes generados sabrán lo que reciben cuando llamen al punto de conexión. Le recomendamos que marque todas las acciones con estos atributos.

Para obtener instrucciones sobre qué respuestas HTTP deben devolver las acciones de API, vea la especificación RFC 7231.