Introducción a Swashbuckle y ASP.NET CoreGet started with Swashbuckle and ASP.NET Core

Vea o descargue el código de ejemplo (cómo descargarlo)View or download sample code (how to download)

Hay tres componentes principales de Swashbuckle:There are three main components to Swashbuckle:

  • Swashbuckle.AspNetCore.Swagger: modelo de objetos de Swagger y middleware para exponer objetos SwaggerDocument como puntos de conexión JSON.Swashbuckle.AspNetCore.Swagger: a Swagger object model and middleware to expose SwaggerDocument objects as JSON endpoints.

  • Swashbuckle.AspNetCore.SwaggerGen: generador de Swagger que genera objetos SwaggerDocument directamente desde las rutas, controladores y modelos.Swashbuckle.AspNetCore.SwaggerGen: a Swagger generator that builds SwaggerDocument objects directly from your routes, controllers, and models. Se suele combinar con el middleware de punto de conexión de Swagger para exponer automáticamente el JSON de Swagger.It's typically combined with the Swagger endpoint middleware to automatically expose Swagger JSON.

  • Swashbuckle.AspNetCore.SwaggerUI: versión insertada de la herramienta de interfaz de usuario de Swagger.Swashbuckle.AspNetCore.SwaggerUI: an embedded version of the Swagger UI tool. Interpreta el JSON de Swagger para crear una experiencia enriquecida y personalizable para describir la funcionalidad de la API web.It interprets Swagger JSON to build a rich, customizable experience for describing the web API functionality. Incluye herramientas de ejecución de pruebas integradas para los métodos públicos.It includes built-in test harnesses for the public methods.

Instalación del paquetePackage installation

Se puede agregar Swashbuckle con los métodos siguientes:Swashbuckle can be added with the following approaches:

  • En la ventana Consola del Administrador de paquetes:From the Package Manager Console window:

    • Vaya a Vista > Otras ventanas > Consola del Administrador de paquetes.Go to View > Other Windows > Package Manager Console

    • Vaya al directorio en el que está TodoApi.csproj.Navigate to the directory in which the TodoApi.csproj file exists

    • Ejecute el siguiente comando:Execute the following command:

      Install-Package Swashbuckle.AspNetCore -Version 5.6.3
      
  • En el cuadro de diálogo Administrar paquetes NuGet:From the Manage NuGet Packages dialog:

    • Haga clic con el botón derecho en el proyecto en el Explorador de soluciones > Administrar paquetes NuGet.Right-click the project in Solution Explorer > Manage NuGet Packages
    • Establezca el origen del paquete en "nuget.org".Set the Package source to "nuget.org"
    • Asegúrese de que la opción "Incluir versión preliminar" está habilitada.Ensure the "Include prerelease" option is enabled
    • Escriba "Swashbuckle.AspNetCore" en el cuadro de búsqueda.Enter "Swashbuckle.AspNetCore" in the search box
    • Seleccione el paquete "Swashbuckle.AspNetCore" más reciente en la pestaña Examinar y haga clic en Instalar.Select the latest "Swashbuckle.AspNetCore" package from the Browse tab and click Install

Agregar y configurar el middleware de SwaggerAdd and configure Swagger middleware

Agregue el generador de Swagger a la colección de servicios en el método Startup.ConfigureServices:Add the Swagger generator to the services collection in the Startup.ConfigureServices method:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TodoContext>(opt =>
        opt.UseInMemoryDatabase("TodoList"));
    services.AddMvc();

    // Register the Swagger generator, defining 1 or more Swagger documents
    services.AddSwaggerGen();
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TodoContext>(opt =>
        opt.UseInMemoryDatabase("TodoList"));
    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    // Register the Swagger generator, defining 1 or more Swagger documents
    services.AddSwaggerGen();
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TodoContext>(opt =>
        opt.UseInMemoryDatabase("TodoList"));
    services.AddControllers();

    // Register the Swagger generator, defining 1 or more Swagger documents
    services.AddSwaggerGen();
}

En el método Startup.Configure, habilite el middleware para servir el documento JSON generado y la interfaz de usuario de Swagger:In the Startup.Configure method, enable the middleware for serving the generated JSON document and the Swagger UI:

public void Configure(IApplicationBuilder app)
{
    // Enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger();

    // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
    // specifying the Swagger JSON endpoint.
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    });

    app.UseMvc();
}
public void Configure(IApplicationBuilder app)
{
    // Enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger();

    // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
    // specifying the Swagger JSON endpoint.
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    });

    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Nota

Swashbuckle se basa en Microsoft.AspNetCore.Mvc.ApiExplorer de MVC para detectar las rutas y los puntos de conexión.Swashbuckle relies on MVC's Microsoft.AspNetCore.Mvc.ApiExplorer to discover the routes and endpoints. Si el proyecto llama a AddMvc, las rutas y los puntos de conexión se detectan automáticamente.If the project calls AddMvc, routes and endpoints are discovered automatically. Al llamar a AddMvcCore, se debe llamar explícitamente al método AddApiExplorer.When calling AddMvcCore, the AddApiExplorer method must be explicitly called. Para más información, consulte Swashbuckle, ApiExplorer y enrutamiento.For more information, see Swashbuckle, ApiExplorer, and Routing.

La llamada de método UseSwaggerUI anterior habilita el middleware de archivos estáticos.The preceding UseSwaggerUI method call enables the Static File Middleware. Si el destino es .NET Framework o .NET Core 1.x, agregue el paquete NuGet Microsoft.AspNetCore.StaticFiles al proyecto.If targeting .NET Framework or .NET Core 1.x, add the Microsoft.AspNetCore.StaticFiles NuGet package to the project.

Inicie la aplicación y vaya a http://localhost:<port>/swagger/v1/swagger.json.Launch the app, and navigate to http://localhost:<port>/swagger/v1/swagger.json. El documento generado en el que se describen los puntos de conexión aparecerá según se muestra en la especificación de OpenAPI (openapi.json).The generated document describing the endpoints appears as shown in OpenAPI specification (openapi.json).

La interfaz de usuario de Swagger se encuentra en http://localhost:<port>/swagger.The Swagger UI can be found at http://localhost:<port>/swagger. Explore la API a través de la interfaz de usuario de Swagger e incorpórela a otros programas.Explore the API via Swagger UI and incorporate it in other programs.

Sugerencia

Para servir la interfaz de usuario de Swagger en la raíz de la aplicación (http://localhost:<port>/), establezca la propiedad RoutePrefix en una cadena vacía:To serve the Swagger UI at the app's root (http://localhost:<port>/), set the RoutePrefix property to an empty string:

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    c.RoutePrefix = string.Empty;
});

Si usa directorios con IIS o un proxy inverso, establezca el punto de conexión de Swagger en una ruta de acceso relativa mediante el prefijo ./.If using directories with IIS or a reverse proxy, set the Swagger endpoint to a relative path using the ./ prefix. Por ejemplo: ./swagger/v1/swagger.json.For example, ./swagger/v1/swagger.json. El uso de /swagger/v1/swagger.json indica a la aplicación que debe buscar el archivo JSON en la verdadera raíz de la dirección URL (junto con el prefijo de ruta, si se usa).Using /swagger/v1/swagger.json instructs the app to look for the JSON file at the true root of the URL (plus the route prefix, if used). Por ejemplo, use http://localhost:<port>/<route_prefix>/swagger/v1/swagger.json en lugar de http://localhost:<port>/<virtual_directory>/<route_prefix>/swagger/v1/swagger.json.For example, use http://localhost:<port>/<route_prefix>/swagger/v1/swagger.json instead of http://localhost:<port>/<virtual_directory>/<route_prefix>/swagger/v1/swagger.json.

Nota

De forma predeterminada, Swashbuckle genera y expone JSON de Swagger en la versión 3.0 de la especificación (denominada oficialmente la especificación OpenAPI).By default, Swashbuckle generates and exposes Swagger JSON in version 3.0 of the specification—officially called the OpenAPI Specification. Para admitir la compatibilidad con versiones anteriores, puede optar por exponer JSON en el formato 2.0 en su lugar.To support backwards compatibility, you can opt into exposing JSON in the 2.0 format instead. Este formato 2.0 es importante para integraciones como Microsoft Power Apps y Microsoft Flow, que actualmente admiten la versión 2.0 de OpenAPI.This 2.0 format is important for integrations such as Microsoft Power Apps and Microsoft Flow that currently support OpenAPI version 2.0. Para optar por el formato 2.0, establezca la propiedad SerializeAsV2 en Startup.Configure:To opt into the 2.0 format, set the SerializeAsV2 property in Startup.Configure:

public void Configure(IApplicationBuilder app)
{
    // Enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger(c =>
    {
        c.SerializeAsV2 = true;
    });

    // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
    // specifying the Swagger JSON endpoint.
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    });

    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Personalizar y ampliarCustomize and extend

Swagger proporciona opciones para documentar el modelo de objetos y personalizar la interfaz de usuario para que coincida con el tema.Swagger provides options for documenting the object model and customizing the UI to match your theme.

En la clase Startup, agregue los siguientes espacios de nombres:In the Startup class, add the following namespaces:

using System;
using System.Reflection;
using System.IO;

Información y descripción de la APIAPI info and description

La acción de configuración que se pasa al método AddSwaggerGen agrega información, como el autor, la licencia y la descripción:The configuration action passed to the AddSwaggerGen method adds information such as the author, license, and description:

En la clase Startup, importe el siguiente espacio de nombres para que use la clase OpenApiInfo:In the Startup class, import the following namespace to use the OpenApiInfo class:

using Microsoft.OpenApi.Models;

Con la clase OpenApiInfo, modifique la información que se muestra en la interfaz de usuario:Using the OpenApiInfo class, modify the information displayed in the UI:

// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "ToDo API",
        Description = "A simple example ASP.NET Core Web API",
        TermsOfService = new Uri("https://example.com/terms"),
        Contact = new OpenApiContact
        {
            Name = "Shayne Boyer",
            Email = string.Empty,
            Url = new Uri("https://twitter.com/spboyer"),
        },
        License = new OpenApiLicense
        {
            Name = "Use under LICX",
            Url = new Uri("https://example.com/license"),
        }
    });
});

La interfaz de usuario de Swagger muestra información de la versión:The Swagger UI displays the version's information:

Interfaz de usuario de Swagger con información de la versión: descripción, autor y el vínculo See more (Ver más)

comentarios XMLXML comments

Los comentarios XML se pueden habilitar con los métodos siguientes:XML comments can be enabled with the following approaches:

  • Haga clic con el botón derecho en el Explorador de soluciones y seleccione Editar <nombre_de_proyecto>.csproj.Right-click the project in Solution Explorer and select Edit <project_name>.csproj.
  • Agregue manualmente las líneas resaltadas al archivo .csproj:Manually add the highlighted lines to the .csproj file:
<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
  <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
  • Haga clic con el botón derecho en el proyecto en el Explorador de soluciones y seleccione Propiedades.Right-click the project in Solution Explorer and select Properties.
  • Active la casilla Archivo de documentación XML en la sección Salida de la pestaña Compilar.Check the XML documentation file box under the Output section of the Build tab.

Puede habilitar los comentarios XML para proporcionar información de depuración para miembros y tipos públicos sin documentación.Enabling XML comments provides debug information for undocumented public types and members. Los miembros y tipos que no estén documentados se indican por medio del mensaje de advertencia.Undocumented types and members are indicated by the warning message. Por ejemplo, el siguiente mensaje señala una infracción con el código de advertencia 1591:For example, the following message indicates a violation of warning code 1591:

warning CS1591: Missing XML comment for publicly visible type or member 'TodoController.GetAll()'

Para eliminar las advertencias a nivel de proyecto, defina una lista delimitada por punto y coma de códigos de advertencia que se deban omitir en el archivo de proyecto.To suppress warnings project-wide, define a semicolon-delimited list of warning codes to ignore in the project file. Al anexar los códigos de advertencia a $(NoWarn);, se aplican también los valores predeterminados de C#.Appending the warning codes to $(NoWarn); applies the C# default values too.

<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
  <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
<PropertyGroup>
  <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
  <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

Para suprimir las advertencias solo para miembros específicos, incluya el código en directivas de preprocesador de advertencias #pragma.To suppress warnings only for specific members, enclose the code in #pragma warning preprocessor directives. Este enfoque es útil para el código que no debe exponerse mediante los documentos de API. En el ejemplo siguiente, se omite el código de advertencia CS1591 para toda la clase Program.This approach is useful for code that shouldn't be exposed via the API docs. In the following example, warning code CS1591 is ignored for the entire Program class. La ejecución del código de advertencia se restaura al cerrar la definición de clase.Enforcement of the warning code is restored at the close of the class definition. Especifique varios códigos de advertencia con una lista delimitada por comas.Specify multiple warning codes with a comma-delimited list.

namespace TodoApi
{
#pragma warning disable CS1591
    public class Program
    {
        public static void Main(string[] args) =>
            BuildWebHost(args).Run();

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();
    }
#pragma warning restore CS1591
}

Configure Swagger para usar el archivo XML que se generó con las instrucciones anteriores.Configure Swagger to use the XML file that's generated with the preceding instructions. En Linux o sistemas operativos que no sean Windows, las rutas de acceso y los nombres de archivo pueden distinguir entre mayúsculas y minúsculas.For Linux or non-Windows operating systems, file names and paths can be case-sensitive. Por ejemplo, un archivo TodoApi.XML es válido en Windows, pero no en CentOS.For example, a TodoApi.XML file is valid on Windows but not CentOS.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TodoContext>(opt =>
        opt.UseInMemoryDatabase("TodoList"));
    services.AddControllers();

    // Register the Swagger generator, defining 1 or more Swagger documents
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo
        {
            Version = "v1",
            Title = "ToDo API",
            Description = "A simple example ASP.NET Core Web API",
            TermsOfService = new Uri("https://example.com/terms"),
            Contact = new OpenApiContact
            {
                Name = "Shayne Boyer",
                Email = string.Empty,
                Url = new Uri("https://twitter.com/spboyer"),
            },
            License = new OpenApiLicense
            {
                Name = "Use under LICX",
                Url = new Uri("https://example.com/license"),
            }
        });

        // Set the comments path for the Swagger JSON and UI.
        var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        c.IncludeXmlComments(xmlPath);
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TodoContext>(opt =>
        opt.UseInMemoryDatabase("TodoList"));
    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    // Register the Swagger generator, defining 1 or more Swagger documents
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo
        {
            Version = "v1",
            Title = "ToDo API",
            Description = "A simple example ASP.NET Core Web API",
            TermsOfService = new Uri("https://example.com/terms"),
            Contact = new OpenApiContact
            {
                Name = "Shayne Boyer",
                Email = string.Empty,
                Url = new Uri("https://twitter.com/spboyer"),
            },
            License = new OpenApiLicense
            {
                Name = "Use under LICX",
                Url = new Uri("https://example.com/license"),
            }
        });

        // Set the comments path for the Swagger JSON and UI.
        var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        c.IncludeXmlComments(xmlPath);
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TodoContext>(opt =>
        opt.UseInMemoryDatabase("TodoList"));
    services.AddMvc();

    // Register the Swagger generator, defining 1 or more Swagger documents
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo
        {
            Version = "v1",
            Title = "ToDo API",
            Description = "A simple example ASP.NET Core Web API",
            TermsOfService = new Uri("https://example.com/terms"),
            Contact = new OpenApiContact
            {
                Name = "Shayne Boyer",
                Email = string.Empty,
                Url = new Uri("https://twitter.com/spboyer"),
            },
            License = new OpenApiLicense
            {
                Name = "Use under LICX",
                Url = new Uri("https://example.com/license"),
            }
        });

        // Set the comments path for the Swagger JSON and UI.
        var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        c.IncludeXmlComments(xmlPath);
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TodoContext>(opt =>
        opt.UseInMemoryDatabase("TodoList"));
    services.AddMvc();

    // Register the Swagger generator, defining 1 or more Swagger documents
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo
        {
            Version = "v1",
            Title = "ToDo API",
            Description = "A simple example ASP.NET Core Web API",
            TermsOfService = new Uri("https://example.com/terms"),
            Contact = new OpenApiContact
            {
                Name = "Shayne Boyer",
                Email = string.Empty,
                Url = new Uri("https://twitter.com/spboyer"),
            },
            License = new OpenApiLicense
            {
                Name = "Use under LICX",
                Url = new Uri("https://example.com/license"),
            }
        });

        // Set the comments path for the Swagger JSON and UI.
        var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        c.IncludeXmlComments(xmlPath);
    });
}

En el código anterior, Reflection se usa para crear un nombre de archivo XML que coincida con el proyecto de API web.In the preceding code, Reflection is used to build an XML file name matching that of the web API project. La propiedad AppContext.BaseDirectory sirve para crear una ruta de acceso al archivo XML.The AppContext.BaseDirectory property is used to construct a path to the XML file. Algunas características de Swagger (por ejemplo, esquemas de parámetros de entrada o métodos HTTP y códigos de respuesta de los atributos respectivos) funcionan sin el uso de un archivo de documentación XML.Some Swagger features (for example, schemata of input parameters or HTTP methods and response codes from the respective attributes) work without the use of an XML documentation file. Para la mayoría de las características, es decir, los resúmenes de los métodos y las descripciones de los parámetros y los códigos de respuesta, el uso de un archivo XML es obligatorio.For most features, namely method summaries and the descriptions of parameters and response codes, the use of an XML file is mandatory.

Agregar comentarios con la triple barra diagonal a una acción mejora la interfaz de usuario de Swagger en tanto agrega una descripción de la acción al encabezado de la sección.Adding triple-slash comments to an action enhances the Swagger UI by adding the description to the section header. Agregue un elemento <summary> antes de la acción Delete:Add a <summary> element above the Delete action:

/// <summary>
/// Deletes a specific TodoItem.
/// </summary>
/// <param name="id"></param>        
[HttpDelete("{id}")]
public IActionResult Delete(long id)
{
    var todo = _context.TodoItems.Find(id);

    if (todo == null)
    {
        return NotFound();
    }

    _context.TodoItems.Remove(todo);
    _context.SaveChanges();

    return NoContent();
}

La interfaz de usuario de Swagger muestra el texto interno del elemento <summary> del código anterior:The Swagger UI displays the inner text of the preceding code's <summary> element:

Interfaz de usuario de Swagger en la que se muestra el comentario XML "Deletes a specific TodoItem" (Elimina una tarea pendiente específica)

La interfaz de usuario se controla por medio del esquema JSON generado:The UI is driven by the generated JSON schema:

"delete": {
    "tags": [
        "Todo"
    ],
    "summary": "Deletes a specific TodoItem.",
    "operationId": "ApiTodoByIdDelete",
    "consumes": [],
    "produces": [],
    "parameters": [
        {
            "name": "id",
            "in": "path",
            "description": "",
            "required": true,
            "type": "integer",
            "format": "int64"
        }
    ],
    "responses": {
        "200": {
            "description": "Success"
        }
    }
}

Agregue un elemento <remarks> a la documentación del método de acción Create.Add a <remarks> element to the Create action method documentation. Este elemento complementa la información especificada en el elemento <summary> y proporciona una interfaz de usuario de Swagger más sólida.It supplements information specified in the <summary> element and provides a more robust Swagger UI. El contenido del elemento <remarks> puede estar formado por texto, JSON o XML.The <remarks> element content can consist of text, JSON, or XML.

/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
///     POST /Todo
///     {
///        "id": 1,
///        "name": "Item1",
///        "isComplete": true
///     }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>            
[HttpPost]
[ProducesResponseType(typeof(TodoItem), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
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);
}
/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
///     POST /Todo
///     {
///        "id": 1,
///        "name": "Item1",
///        "isComplete": true
///     }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>            
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<TodoItem> Create(TodoItem item)
{
    _context.TodoItems.Add(item);
    _context.SaveChanges();

    return CreatedAtRoute("GetTodo", new { id = item.Id }, item);
}
/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
///     POST /Todo
///     {
///        "id": 1,
///        "name": "Item1",
///        "isComplete": true
///     }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>            
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<TodoItem> Create(TodoItem item)
{
    _context.TodoItems.Add(item);
    _context.SaveChanges();

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

Fíjese en las mejoras de la interfaz de usuario con estos comentarios extra:Notice the UI enhancements with these additional comments:

Interfaz de usuario de Swagger con comentarios adicionales

Anotaciones de datosData annotations

Marque el modelo con atributos que se encuentren en el espacio de nombres System.ComponentModel.DataAnnotations para controlar los componentes de la interfaz de usuario de Swagger.Mark the model with attributes, found in the System.ComponentModel.DataAnnotations namespace, to help drive the Swagger UI components.

Agregue el atributo [Required] a la propiedad Name de la clase TodoItem:Add the [Required] attribute to the Name property of the TodoItem class:

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace TodoApi.Models
{
    public class TodoItem
    {
        public long Id { get; set; }

        [Required]
        public string Name { get; set; }

        [DefaultValue(false)]
        public bool IsComplete { get; set; }
    }
}

La presencia de este atributo cambia el comportamiento de la interfaz de usuario y modifica el esquema JSON subyacente:The presence of this attribute changes the UI behavior and alters the underlying JSON schema:

"definitions": {
    "TodoItem": {
        "required": [
            "name"
        ],
        "type": "object",
        "properties": {
            "id": {
                "format": "int64",
                "type": "integer"
            },
            "name": {
                "type": "string"
            },
            "isComplete": {
                "default": false,
                "type": "boolean"
            }
        }
    }
},

Agregue el atributo [Produces("application/json")] al controlador de API.Add the [Produces("application/json")] attribute to the API controller. Su propósito consiste en declarar que las acciones del controlador admiten un contenido de respuesta de tipo application/json:Its purpose is to declare that the controller's actions support a response content type of application/json:

[Produces("application/json")]
[Route("api/[controller]")]
public class TodoController : ControllerBase
{
    private readonly TodoContext _context;
[Produces("application/json")]
[Route("api/[controller]")]
[ApiController]
public class TodoController : ControllerBase
{
    private readonly TodoContext _context;
[Produces("application/json")]
[Route("api/[controller]")]
[ApiController]
public class TodoController : ControllerBase
{
    private readonly TodoContext _context;

En el menú desplegable Response Content Type (Tipo de contenido de respuesta) se selecciona este tipo de contenido como el valor predeterminado para las acciones GET del controlador:The Response Content Type drop-down selects this content type as the default for the controller's GET actions:

Interfaz de usuario de Swagger con el tipo de contenido de respuesta predeterminado

A medida que aumenta el uso de anotaciones de datos en la API web, la interfaz de usuario y las páginas de ayuda de la API pasan a ser más descriptivas y útiles.As the usage of data annotations in the web API increases, the UI and API help pages become more descriptive and useful.

Describir los tipos de respuestaDescribe response types

Lo que más preocupa a los desarrolladores que consumen una API web es lo que se devuelve; sobre todo, los tipos de respuesta y los códigos de error (si no son los habituales).Developers consuming a web API are most concerned with what's returned—specifically response types and error codes (if not standard). Los tipos de respuesta y los códigos de error se indican en las anotaciones de datos y los comentarios XML.The response types and error codes are denoted in the XML comments and data annotations.

La acción Create devuelve un código de estado HTTP 201 cuando se ha ejecutado correctamente.The Create action returns an HTTP 201 status code on success. Cuando el cuerpo de solicitud enviado es null, se devuelve un código de estado HTTP 400.An HTTP 400 status code is returned when the posted request body is null. Sin la documentación correcta en la interfaz de usuario de Swagger, el consumidor no dispone de la información necesaria de estos resultados esperados.Without proper documentation in the Swagger UI, the consumer lacks knowledge of these expected outcomes. Corrija este problema agregando las líneas resaltadas en el siguiente ejemplo:Fix that problem by adding the highlighted lines in the following example:

/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
///     POST /Todo
///     {
///        "id": 1,
///        "name": "Item1",
///        "isComplete": true
///     }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>            
[HttpPost]
[ProducesResponseType(typeof(TodoItem), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
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);
}
/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
///     POST /Todo
///     {
///        "id": 1,
///        "name": "Item1",
///        "isComplete": true
///     }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>            
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<TodoItem> Create(TodoItem item)
{
    _context.TodoItems.Add(item);
    _context.SaveChanges();

    return CreatedAtRoute("GetTodo", new { id = item.Id }, item);
}
/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <remarks>
/// Sample request:
///
///     POST /Todo
///     {
///        "id": 1,
///        "name": "Item1",
///        "isComplete": true
///     }
///
/// </remarks>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>            
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<TodoItem> Create(TodoItem item)
{
    _context.TodoItems.Add(item);
    _context.SaveChanges();

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

Ahora, la interfaz de usuario de Swagger documenta de forma clara los códigos de respuesta HTTP esperados:The Swagger UI now clearly documents the expected HTTP response codes:

Interfaz de usuario de Swagger, donde se muestra la descripción de la clase de respuesta POST "Returns the newly created item" (Devuelve el elemento recién creado) y "400 - If the item is null" (400 - Si el elemento es nulo) para el código de estado y el motivo en Response Messages (Mensajes de respuesta)

En ASP.NET Core 2.2 o versiones posteriores, las convenciones se pueden usar como alternativa a la representación explícita de acciones individuales con [ProducesResponseType].In ASP.NET Core 2.2 or later, conventions can be used as an alternative to explicitly decorating individual actions with [ProducesResponseType]. Para obtener más información, vea Uso de convenciones de API web.For more information, see Uso de convenciones de API web.

Para admitir la decoración [ProducesResponseType], el paquete Swashbuckle.AspNetCore.Annotations ofrece extensiones para habilitar y enriquecer los metadatos de respuesta, esquema y parámetro.To support the [ProducesResponseType] decoration, the Swashbuckle.AspNetCore.Annotations package offers extensions to enable and enrich the response, schema, and parameter metadata.

Personalizar la interfaz de usuarioCustomize the UI

La interfaz de usuario predeterminada es funcional y tiene un aspecto adecuado.The default UI is both functional and presentable. Pero las páginas de documentación de la API deben ostentar su marca o tema.However, API documentation pages should represent your brand or theme. Para incluir la personalización de marca en los componentes de Swashbuckle, se deben agregar los recursos para servir archivos estáticos y generar la estructura de carpetas que hospedará estos archivos.Branding the Swashbuckle components requires adding the resources to serve static files and building the folder structure to host those files.

Si el destino es .NET Framework o .NET Core 1.x, agregue el paquete NuGet Microsoft.AspNetCore.StaticFiles al proyecto:If targeting .NET Framework or .NET Core 1.x, add the Microsoft.AspNetCore.StaticFiles NuGet package to the project:

<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />

El paquete NuGet anterior ya estará instalado si el destino es .NET Core 2.x y se usa el metapaquete.The preceding NuGet package is already installed if targeting .NET Core 2.x and using the metapackage.

Habilitar middleware de archivos estáticos:Enable Static File Middleware:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles();

    // Enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger();

    // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
    // specifying the Swagger JSON endpoint.
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    });

    app.UseMvc();
}
public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles();

    // Enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger();

    // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
    // specifying the Swagger JSON endpoint.
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    });

    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Para insertar hojas de estilos CSS adicionales, agréguelas a la carpeta wwwroot del proyecto y especifique la ruta de acceso relativa en las opciones de middleware:To inject additional CSS stylesheets, add them to the project's wwwroot folder and specify the relative path in the middleware options:

app.UseSwaggerUI(c =>
{
     c.InjectStylesheet("/swagger-ui/custom.css");
}

Recursos adicionalesAdditional resources