Condividi tramite


Introduzione a NSwag e ad ASP.NET Core

Di Christoph Nienaber, Rico Suter e Dave Brock

Visualizzare o scaricare il codice di esempio (procedura per il download)

NSwag offre le funzionalità seguenti:

  • La possibilità di usare l'interfaccia utente di Swagger e un generatore Swagger.
  • Funzionalità di generazione del codice flessibili.

Con NSwag non è necessaria un'API esistente. È possibile usare API di terze parti che incorporano Swagger e generano un'implementazione client. NSwag consente di velocizzare il ciclo di sviluppo e adattarsi facilmente alle modifiche dell'API.

Installazione del pacchetto

Installare NSwag in:

  • Generare la specifica Swagger per l'API Web implementata.
  • Usare l'interfaccia utente di Swagger per esplorare e testare l'API Web.
  • Usare Redoc per aggiungere la documentazione dell'API per l'API Web.

Per usare il middleware ASP.NET Core di NSwag, installare il pacchetto NuGet NSwag.AspNetCore. Questo pacchetto contiene il middleware necessario per generare e usare la specifica Swagger, l'interfaccia utente di Swagger (v2 e v3) e l'interfaccia utente di ReDoc. NSwag 14 supporta solo v3 della specifica dell'interfaccia utente di Swagger.

Usare uno degli approcci seguenti per installare il pacchetto NuGet NSwag:

  • Dalla finestra Console di Gestione pacchetti:

    • Passare a Vista>Altre finestre>Console di Gestione pacchetti

    • Passare alla directory in cui esiste il NSwagSample.csproj file

    • Eseguire il comando seguente:

      Install-Package NSwag.AspNetCore
      
  • Dalla finestra di dialogo Gestisci pacchetti NuGet:

    • Fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni>Gestisci pacchetti NuGet
    • Impostare Origine pacchetto su "nuget.org"
    • Immettere "NSwag.AspNetCore" nella casella di ricerca
    • Selezionare il pacchetto "NSwag.AspNetCore" dalla scheda Sfoglia e fare clic su Installa

Aggiungere e configurare il middleware di Swagger

Aggiungere e configurare Swagger nell'app ASP.NET Core eseguendo i passaggi seguenti:

  • Aggiungere il generatore OpenApi alla raccolta di servizi in Program.cs:
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddOpenApiDocument();
  • Abilitare il middleware per gestire la specifica OpenApi generata, l'interfaccia utente di Swagger e l'interfaccia utente redoc, anche in Program.cs:
if (app.Environment.IsDevelopment())
{
    // Add OpenAPI 3.0 document serving middleware
    // Available at: http://localhost:<port>/swagger/v1/swagger.json
    app.UseOpenApi();

    // Add web UIs to interact with the document
    // Available at: http://localhost:<port>/swagger
    app.UseSwaggerUi(); // UseSwaggerUI Protected by if (env.IsDevelopment())
}
  • Avviare l'app. Passare a:
    • http://localhost:<port>/swagger per visualizzare l'interfaccia utente di Swagger.
    • http://localhost:<port>/swagger/v1/swagger.json per visualizzare la specifica di Swagger.

Generazione codice

È possibile sfruttare i vantaggi delle funzionalità di generazione del codice di NSwag scegliendo una delle opzioni seguenti:

Generare il codice con NSwagStudio

  • Installare NSwagStudio seguendo le istruzioni riportate nel repository di GitHub NSwagStudio. Nella pagina NSwag release (Versione NSwag) è possibile scaricare una versione xcopy che può essere avviata senza privilegi di installazione e amministratore.
  • Avviare NSwagStudio e immettere l'URL del swagger.json file nella casella di testo Swagger Specification URL (URL specifica Swagger). Ad esempio: http://localhost:5232/swagger/v1/swagger.json.
  • Fare clic sul pulsante Create local Copy (Crea copia locale) per generare una rappresentazione JSON della specifica di Swagger.

NSwag Studio importa la specifica ed esporta un client CSharp.

  • Nell'area Output fare clic sulla casella di controllo Client CSharp. A seconda del progetto, è anche possibile scegliere TypeScript Client (Client TypeScript) o CSharp Web API Controller (Controller API Web CSharp). Se si seleziona CSharp Web API Controller (Controller API Web CSharp), una specifica del servizio ricompila il servizio, fungendo da generazione inversa.
  • Fare clic su Generate Outputs (Genera output) per generare un'implementazione client completa C# del progetto TodoApi.NSwag. Per visualizzare il codice client generato, fare clic sulla scheda CSharp Client (Client CSharp):
namespace MyNamespace
{
    using System = global::System;

    [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
    public partial class TodoClient
    {
    #pragma warning disable 8618 // Set by constructor via BaseUrl property
        private string _baseUrl;
    #pragma warning restore 8618 // Set by constructor via BaseUrl property
        private System.Net.Http.HttpClient _httpClient;
        private static System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(CreateSerializerSettings, true);

        public TodoClient(System.Net.Http.HttpClient httpClient)
        {
            BaseUrl = "http://localhost:5232";
            _httpClient = httpClient;
        }

        private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
        {
            var settings = new Newtonsoft.Json.JsonSerializerSettings();
            UpdateJsonSerializerSettings(settings);
            return settings;
        }

        public string BaseUrl
        {
            get { return _baseUrl; }
            set
            {
                _baseUrl = value;
                if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/"))
                    _baseUrl += '/';
            }
        }
        // code omitted for brevity

Suggerimento

Il codice client C# viene generato in base alle selezioni nella scheda Impostazioni . Modificare le impostazioni per eseguire attività quali la ridenominazione dello spazio dei nomi predefinita e la generazione di metodi sincroni.

  • Copiare il codice C# generato in un file nel progetto client che utilizzerà l'API.
  • Iniziare a usare l'API Web:
var todoClient = new TodoClient(new HttpClient());

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

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

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

Personalizzare la documentazione dell'API

OpenApi offre opzioni per documentare il modello a oggetti per semplificare l'utilizzo dell'API Web.

Informazioni e descrizione API

In Program.csaggiornare AddOpenApiDocument per configurare le informazioni sul documento dell'API Web e includere altre informazioni, ad esempio l'autore, la licenza e la descrizione. Importare prima lo NSwag spazio dei nomi per usare le OpenApi classi .

using NSwag;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApiDocument(options => {
     options.PostProcess = document =>
     {
         document.Info = new OpenApiInfo
         {
             Version = "v1",
             Title = "ToDo API",
             Description = "An ASP.NET Core Web API for managing ToDo items",
             TermsOfService = "https://example.com/terms",
             Contact = new OpenApiContact
             {
                 Name = "Example Contact",
                 Url = "https://example.com/contact"
             },
             License = new OpenApiLicense
             {
                 Name = "Example License",
                 Url = "https://example.com/license"
             }
         };
     };
});

L'interfaccia utente di Swagger visualizza le informazioni sulla versione:

Interfaccia utente di Swagger con informazioni sulla versione.

Commenti in XML

Per abilitare i commenti XML, seguire questa procedura:

  • Fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Edit <project_name>.csproj.
  • Aggiungere manualmente le righe evidenziate al .csproj file:
<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

Abilitando i commenti XML, viene eseguito il debug delle informazioni per membri e tipi pubblici non documentati. I membri e tipi non documentati sono indicati nel messaggio di avviso. Ad esempio, il messaggio seguente indica una violazione del codice di avviso 1591:

warning CS1591: Missing XML comment for publicly visible type or member 'TodoContext'

Per eliminare gli avvisi per l'intero progetto, definire un elenco delimitato da punto e virgola di codici di avviso da ignorare nel file di progetto. L'aggiunta di codici di avviso a $(NoWarn); applica anche i valori predefiniti di C#.

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

Per eliminare gli avvisi solo per membri specifici, racchiudere il codice in direttive del preprocessore #pragma warning. Questo approccio è utile per il codice che non deve essere esposto tramite la documentazione dell'API. Nell'esempio seguente il codice di avviso CS1591 viene ignorato per l'intera TodoContext classe. L'imposizione del codice di avviso viene ripristinata alla chiusura della definizione della classe. Specificare più codici di avviso con un elenco delimitato da virgole.

namespace NSwagSample.Models;

#pragma warning disable CS1591
public class TodoContext : DbContext
{
    public TodoContext(DbContextOptions<TodoContext> options) : base(options) { }

    public DbSet<TodoItem> TodoItems => Set<TodoItem>();
}
#pragma warning restore CS1591

Annotazioni dei dati

Contrassegnare il modello con gli attributi, disponibili nello spazio dei nomi, per facilitare l'unità dei componenti dell'interfaccia System.ComponentModel.DataAnnotations utente di Swagger.

Aggiungere l'attributo [Required] alla proprietà Name della classe TodoItem:

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

namespace NSwagSample.Models;

public class TodoItem
{
    public long Id { get; set; }

    [Required]
    public string Name { get; set; } = null!;

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

La presenza di questo attributo modifica il comportamento dell'interfaccia utente e lo schema JSON sottostante:

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

Con l'aumento dell'uso delle annotazioni dei dati nell'API Web, le pagine della Guida dell'API e dell'interfaccia utente diventano più descrittive e utili.

Descrivere i tipi di risposta

Gli sviluppatori che usano un'API Web sono maggiormente interessati a ciò che viene restituito, in particolare ai tipi di risposta e ai codici di errore (se non standard). I tipi di risposta e i codici di errore vengono indicati nei commenti XML e nelle annotazioni dei dati.

L'azione Create restituisce un codice di stato HTTP 201 in caso di esito positivo. Quando il corpo della richiesta inviata è null, viene restituito un codice di stato HTTP 400 . Senza la documentazione appropriata nell'interfaccia utente di Swagger, il consumer non riconosce tali risultati previsti. Risolvere il problema aggiungendo le righe evidenziate nell'esempio seguente:

/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <remarks>
/// Sample request:
///
///     POST /Todo
///     {
///        "id": 1,
///        "name": "Item #1",
///        "isComplete": true
///     }
///
/// </remarks>
/// <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 async Task<IActionResult> Create(TodoItem item)
{
    _context.TodoItems.Add(item);
    await _context.SaveChangesAsync();

    return CreatedAtAction(nameof(Get), new { id = item.Id }, item);
}

L'interfaccia utente di Swagger ora documenta chiaramente i codici di risposta HTTP previsti (e vengono visualizzati anche i commenti XML):

Interfaccia utente di Swagger che mostra la descrizione della classe di risposta POST 'Restituisce l'elemento Todo appena creato' e '400 - Se l'elemento è null' per il codice di stato e il motivo in Messaggi di risposta.

Le convenzioni possono essere usate come alternativa per decorare in modo esplicito le singole azioni con [ProducesResponseType]. Per altre informazioni, vedere Usare le convenzioni dell'API Web.

Redoc

Redoc è un'alternativa all'interfaccia utente di Swagger. È simile perché fornisce anche una pagina della documentazione per l'API Web usando la specifica OpenAPI. La differenza è che l'interfaccia utente di Redoc è più incentrata sulla documentazione e non fornisce un'interfaccia utente interattiva per testare l'API.

Per abilitare Redoc, aggiungere il middleware a Program.cs:

if (app.Environment.IsDevelopment())
{
    // Add OpenAPI 3.0 document serving middleware
    // Available at: http://localhost:<port>/swagger/v1/swagger.json
    app.UseOpenApi();

    // Add web UIs to interact with the document
    // Available at: http://localhost:<port>/swagger
    app.UseSwaggerUi(); // UseSwaggerUI is called only in Development.
    
    // Add ReDoc UI to interact with the document
    // Available at: http://localhost:<port>/redoc
    app.UseReDoc(options =>
    {
        options.Path = "/redoc";
    });
}

Eseguire l'applicazione e passare a per http://localhost:<port>/redoc visualizzare l'interfaccia utente di Redoc:

Documentazione di Redoc per l'API di esempio.

Di Christoph Nienaber, Rico Suter e Dave Brock

Visualizzare o scaricare il codice di esempio (procedura per il download)

NSwag offre le funzionalità seguenti:

  • La possibilità di usare l'interfaccia utente di Swagger e un generatore Swagger.
  • Funzionalità di generazione del codice flessibili.

Con NSwag non è necessaria un'API esistente. È possibile usare API di terze parti che incorporano Swagger e generano un'implementazione client. NSwag consente di velocizzare il ciclo di sviluppo e adattarsi facilmente alle modifiche dell'API.

Registrare il middleware NSwag

Registrare il middleware NSwag per:

  • Generare la specifica Swagger per l'API Web implementata.
  • Usare l'interfaccia utente di Swagger per esplorare e testare l'API Web.

Per usare il middleware ASP.NET Core di NSwag, installare il pacchetto NuGet NSwag.AspNetCore. Questo pacchetto contiene il middleware necessario per generare e usare la specifica Swagger, l'interfaccia utente di Swagger (v2 e v3) e l'interfaccia utente di ReDoc.

Usare uno degli approcci seguenti per installare il pacchetto NuGet NSwag:

  • Dalla finestra Console di Gestione pacchetti:

    • Passare a Vista>Altre finestre>Console di Gestione pacchetti

    • Passare alla directory in cui esiste il TodoApi.csproj file

    • Eseguire il comando seguente:

      Install-Package NSwag.AspNetCore
      
  • Dalla finestra di dialogo Gestisci pacchetti NuGet:

    • Fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni>Gestisci pacchetti NuGet
    • Impostare Origine pacchetto su "nuget.org"
    • Immettere "NSwag.AspNetCore" nella casella di ricerca
    • Selezionare il pacchetto "NSwag.AspNetCore" dalla scheda Sfoglia e fare clic su Installa

Aggiungere e configurare il middleware di Swagger

Aggiungere e configurare Swagger nell'app ASP.NET Core eseguendo i passaggi seguenti:

  • Nel metodo Startup.ConfigureServices registrare i servizi Swagger necessari:
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TodoContext>(opt =>
        opt.UseInMemoryDatabase("TodoList"));
    services.AddMvc();

    // Register the Swagger services
    services.AddSwaggerDocument();
}
  • Nel metodo Startup.Configure abilitare il middleware per la gestione della specifica generata e dell'interfaccia utente di Swagger:
public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles();

    // Register the Swagger generator and the Swagger UI middlewares
    app.UseOpenApi();
    app.UseOpenApi();
    if (env.IsDevelopment())
    {
        app.UseSwaggerUi3();
    }
    app.UseMvc();
}
  • Avviare l'app. Passare a:
    • http://localhost:<port>/swagger per visualizzare l'interfaccia utente di Swagger.
    • http://localhost:<port>/swagger/v1/swagger.json per visualizzare la specifica di Swagger.

Generazione codice

È possibile sfruttare i vantaggi delle funzionalità di generazione del codice di NSwag scegliendo una delle opzioni seguenti:

Generare il codice con NSwagStudio

  • Installare NSwagStudio seguendo le istruzioni riportate nel repository di GitHub NSwagStudio. Nella pagina NSwag release (Versione NSwag) è possibile scaricare una versione xcopy che può essere avviata senza privilegi di installazione e amministratore.

  • Avviare NSwagStudio e immettere l'URL del swagger.json file nella casella di testo Swagger Specification URL (URL specifica Swagger). Ad esempio: http://localhost:44354/swagger/v1/swagger.json.

  • Fare clic sul pulsante Create local Copy (Crea copia locale) per generare una rappresentazione JSON della specifica di Swagger.

    Creare una copia locale della specifica di Swagger

  • Nell'area Output fare clic sulla casella di controllo Client CSharp. A seconda del progetto, è anche possibile scegliere TypeScript Client (Client TypeScript) o CSharp Web API Controller (Controller API Web CSharp). Se si seleziona CSharp Web API Controller (Controller API Web CSharp), una specifica del servizio ricompila il servizio, fungendo da generazione inversa.

  • Fare clic su Generate Outputs (Genera output) per generare un'implementazione client completa C# del progetto TodoApi.NSwag. Per visualizzare il codice client generato, fare clic sulla scheda CSharp Client (Client 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

Suggerimento

Il codice client C# viene generato in base alle selezioni nella scheda Impostazioni . Modificare le impostazioni per eseguire attività quali la ridenominazione dello spazio dei nomi predefinita e la generazione di metodi sincroni.

  • Copiare il codice C# generato in un file nel progetto client che utilizzerà l'API.
  • Iniziare a usare l'API Web:
 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);

Personalizzare la documentazione dell'API

Swagger offre opzioni per documentare il modello a oggetti e semplificare l'uso dell'API Web.

Informazioni e descrizione API

Nel metodo AddSwaggerDocument l'azione di configurazione passata al metodo Startup.ConfigureServices aggiunge informazioni come autore, licenza e descrizione:

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"
        };
    };
});

L'interfaccia utente di Swagger visualizza le informazioni sulla versione:

Interfaccia utente Swagger con informazioni sulla versione

Commenti in XML

Per abilitare i commenti XML, seguire questa procedura:

  • Fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Edit <project_name>.csproj.
  • Aggiungere manualmente le righe evidenziate al .csproj file:
<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
  <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

Annotazioni dei dati

Poiché NSwag usa Reflection e il tipo restituito consigliato per le azioni dell'API Web è ActionResult<T>, può dedurre solo il tipo restituito definito da T. Non è possibile dedurre automaticamente altri tipi restituiti possibili.

Si consideri l'esempio seguente:

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

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

L'azione precedente restituisce ActionResult<T>. All'interno dell'azione viene restituito CreatedAtRoute. Poiché il controller ha l'attributo [ApiController] , è possibile anche una BadRequest risposta. Per altre informazioni, vedere Risposte HTTP 400 automatiche. Usare le annotazioni dei dati per indicare ai client i codici di stato HTTP restituiti da questa azione. Contrassegnare l'azione con gli attributi seguenti:

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

In ASP.NET Core 2.2 o versioni successive, è possibile usare convenzioni in alternativa alla decorazione esplicita di azioni singole con [ProducesResponseType]. Per altre informazioni, vedere Usare le convenzioni dell'API Web.

Il generatore di Swagger ora può descrivere accuratamente questa azione e i client generati conoscono la risposta che riceveranno quando si chiamerà l'endpoint. Come raccomandazione, contrassegnare tutte le azioni con questi attributi.

Per linee guida sulle risposte HTTP che devono essere restituite, vedere RFC 9110: Semantica HTTP (sezione 9.3). Definizioni dei metodi).