在ASP.NET Core web API中使用Swagger/OpenAPI(Swashbuckle)


實戰

首先介紹三個重要組件:

  • Swashbuckle.AspNetCore.Swagger:一個把SwaggerDocument對象暴露成JSON端點(openapi.json對應的URI)的Swagger對象模型和中間件。
  • Swashbuckle.AspNetCore.SwaggerGen:一個根據Routes(路由),Controllers(控制器),Models(模型對象)生成SwaggerDocument的生成器,它通常與Swagger端點中間件相結合,自動公開Swagger JSON(openapi.json)。
  • Swashbuckle.AspNetCore.SwaggerUI:根據openapi.json生成的對應的UI界面

一、安裝包

方式一:在與項目文件夾相同的目錄下執行如下代碼:

Install-Package Swashbuckle.AspNetCore -Version 6.2.3

方式二:使用Nuget包管理工具:

添加並配置Swagger中間件

Program.cs文件中把Swagger生成器添加到服務集合

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        // Register the Swagger services
        services.AddSwaggerDocument();
    }

也在Program.cs啟用生成JSON文檔和SwaggerUI的中間件

    if (env.IsDevelopment())
    {
        // 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();
    }

上面添加的兩行代碼只有在開發環境時才會生效,如果想在生產環境也使用Swagger,就別放在上面的if判斷內

運行程序並訪問https://localhost:<port>/swagger/v1/swagger.json就能看到openapi.json文檔了。port為自己電腦對應的端口比如(默認5000或5001)

通過https://localhost:<port>/swagger路徑訪問SwaggerUI
如果想把SwaggerUI的路徑設置成根路徑(https://localhost:<port>/),把對應的RoutePrefix屬性設為空字符串就行了

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

如果使用了IIS或者反向代理,用過添加./前綴來Swagger端點使用相對地址,例如 ./swagger/v1/swagger.json,/swagger/v1/swagger.json表示程序在URL的真實跟目錄下尋找JSON文件,比如使用https://localhost:<port>/<route_prefix>/swagger/v1/swagger.json而不是https://localhost:<port>/<virtual_directory>/<route_prefix>/swagger/v1/swagger.json

注意:默認Swagger JSON是3.0版本的,若要啟用2.0版本,則添加如下代碼:

app.UseSwagger(options =>
{
    options.SerializeAsV2 = true;
});

API信息和描述

如果您想在Swagger UI中添加一些對API的描述信息,比如作者、許可證、服務條款等信息:
Program.cs類中引入OpenApiInfo類的命名空間

using Microsoft.OpenApi.Models;

然后在Program.cs文件中的ConfigureServices方法中通過services.AddSwaggerGen方法的配置對象進行就改,模板如下:

services.AddControllers();
services.AddSwaggerGen(o=> 
{
    o.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "WeatherForecastApi",
        Description = "try to use the swagger in asp.net core",
        TermsOfService = new Uri("https://www.baidu.com"),
        Contact = new OpenApiContact
        {
            Email = "spy@outlook.com",
            Name = "Michael Shen",
            Url = new Uri("https://www.github.com/shenpingyuan"),
        },
        License=new OpenApiLicense
        {
            Name="app license",
            Url = new Uri("https://example.com/license")
        }
    });
});

然后你的SwaggerUI將會顯示對應的配置信息

XML注釋

如果您想啟用XML注釋以及生成對應的XML注釋文檔,右擊的的項目文件,然后點擊編輯項目文件

添加<GenerateDocumentationFile>true</GenerateDocumentationFile>即可啟用XML注釋

<PropertyGroup>
  <!--生成XML注釋文檔-->
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

開啟這個功能后,如果您的程序中有沒有經過XML注釋的類型或者成員,您將會看到如下警告信息:

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

您覺得煩,可以在編輯項目文件中添加<NoWarn>$(NoWarn);1591</NoWarn>來取消這種警告

<PropertyGroup>
  <!--取消1591警告信息-->
  <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

您也可以通過如下宏定義的方式對整段代碼取消1591警告信息

namespace SwashbuckleSample.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
}

很多地方會用到這個XML注釋文件,如果您想配置你的Swagger使用XML注釋生成的XML注釋文檔,添加如下最后兩行代碼,通過反射方式獲取目標服務器上對應的XML文件的路徑。

注意:Linux或者非Windows系統上,文件名可能是區分大小寫的,比如一個TodoApi.XML文件在Windows上有效,在CentOS上無效

services.AddSwaggerGen(o=> 
{
    o.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "WeatherForecastApi",
        Description = "try to use the swagger in asp.net core",
        TermsOfService = new Uri("https://www.baidu.com"),
        Contact = new OpenApiContact
        {
            Email = "spy@outlook.com",
            Name = "Michael Shen",
            Url = new Uri("https://www.github.com/shenpingyuan"),
        },
        License=new OpenApiLicense
        {
            Name="app license",
            Url = new Uri("https://example.com/license")
        }
    });
    // using System.Reflection;
    var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    o.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
});

通過在在Controller上的Action上添加三重“/”(///),添加XML注釋,比如在 “Delete” Action上添加XML注釋:

/// <summary>
/// Deletes a specific TodoItem.
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(long id)
{
    var item = await _context.TodoItems.FindAsync(id);

    if (item is null)
    {
        return NotFound();
    }

    _context.TodoItems.Remove(item);
    await _context.SaveChangesAsync();

    return NoContent();
}

在SwaggerUI中將會顯示<summary>元素內的文本

對應的openapi.json文檔會添加一行"summary": "Deletes a specific TodoItem.",

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

添加<remark>元素:

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

對應SwaggerUI

屬性注釋

在模型對象上添加屬性注釋[Required]

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

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

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

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

對應openapi.json文檔

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

APIController添加[Produces("application/json")]屬性注釋,目的是聲明,這個Controller的Action支持返回的數據類型為application/json

[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoController : ControllerBase
{

SwaggerUI

您還可以通過如下方式添加返回的狀態碼的描述信息

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

SwaggerUI

定制UI界面

默認的SwaggerUI界面既好看又實用,但如果您需要API文檔頁代表你的品牌和主題。

通過app.UseStaticFiles();啟用靜態文件中間件

app.UseHttpsRedirection();
app.UseStaticFiles();
app.MapControllers();

把您的額外的CSS代碼放到項目的wwwroot文件夾下,然后在中間件的配置選項中指定對應的相對路徑

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

您也可以完全寫一套UI,在你的JS代碼中請求https://localhost:<port>/swagger/v1/swagger.json,得到XML注釋規范文檔,然后將openapi.json文檔中的內容解析到你的頁面


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM