Swashbuckle.AspNetCore介绍

使用 ASP.NET Core 构建的 API 的 Swagger 工具。直接从您的路由、控制器和模型生成精美的 API 文档,包括用于探索和测试操作的 UI。

除了 Swagger 2.0 和 OpenAPI 3.0 生成器外,Swashbuckle 还提供了由生成的 Swagger JSON 提供支持的令人敬畏的 swagger-ui 的嵌入式版本。这意味着您可以使用始终与最新代码同步的实时文档来补充您的 API。最重要的是,它需要最少的编码和维护,让您可以专注于构建一个很棒的 API。

这还不是全部......

一旦你有一个可以在 Swagger 中描述自己的 API,你就打开了基于 Swagger 的工具的宝库,包括一个可以针对各种流行平台的客户端生成器。

开始

  1. 将标准 Nuget 包安装到 ASP.NET Core 应用程序中。

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>Package Manager : Install-Package Swashbuckle.AspNetCore -Version 6.5.0
    CLI : dotnet add package --version 6.5.0 Swashbuckle.AspNetCore
    </code></span></span></span>
  2. 在 的方法中,注册 Swagger 生成器,定义一个或多个 Swagger 文档。ConfigureServicesStartup.cs

    using Microsoft.OpenApi.Models;
    services.AddMvc();
    
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    });
  3. 确保您的 API 操作和参数使用显式“Http”和“From”绑定进行修饰。

    [HttpPost]
    public void CreateProduct([FromBody]Product product)
    ...
    [HttpGet]
    public IEnumerable<Product> SearchProducts([FromQuery]string keywords)
    ...

    注意:如果省略显式参数绑定,则默认情况下,生成器会将它们描述为“查询”参数。

  4. 在该方法中,应通过以下方法之一将生成的 Swagger 公开为 JSON 端点:Configure

    • 如果使用基于终结点的路由,请添加终结点。
    app.MapEndpoints(endpoints =>
    {
        // ...
        endpoints.MapSwagger();
    });
    • 插入中间件
    app.UseSwagger();

    此时,您可以启动应用程序并在“/swagger/v1/swagger.json”中查看生成的 Swagger JSON。

  5. (可选)如果要公开交互式文档,请插入 swagger-ui 中间件,并指定用于支持它的 Swagger JSON 端点。

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

    现在,您可以重新启动应用程序,并在“/swagger”中查看自动生成的交互式文档。

System.Text.Json (STJ) 与 Newtonsoft

在之前的版本中,Swashbuckle 将根据 Newtonsoft 序列化程序的行为生成 Schema(API 公开的数据类型的描述)。这是有道理的,因为这是当时 Core 附带 ASP.NET 序列化程序。但是,从版本开始,ASP.NET Core 引入了开箱即用的新序列化程序 System.Text.Json (STJ),如果您想继续使用 Newtonsoft,则需要安装单独的包并明确选择加入。从 Swashbuckle 及以后,使用了类似的模式。也就是说,开箱即用的 Swashbuckle 将假设您正在使用 STJ 序列化程序,并根据其行为生成 Schema。如果您使用的是 Newtonsoft,则需要安装单独的 Swashbuckle 软件包并明确选择加入。无论您使用的是哪个版本的 ASP.NET Core,这都是必需的步骤5.0.03.0.05.0.0

总而言之......

如果使用的是 System.Text.Json (STJ),则上述设置就足够了,Swagger 生成器将自动遵循 STJ 选项/属性。

如果您使用的是 Newtonsoft,则需要安装单独的软件包并明确选择加入,以确保 Swagger 生成器自动遵循 Newtonsoft 设置/属性:

<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>Package Manager : Install-Package Swashbuckle.AspNetCore.Newtonsoft -Version 6.5.0
CLI : dotnet add package --version 6.5.0 Swashbuckle.AspNetCore.Newtonsoft
</code></span></span></span></span>
services.AddMvc();

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
services.AddSwaggerGenNewtonsoftSupport(); 
// explicit opt-in - needs to be placed after AddSwaggerGen()

Swashbuckle、ApiExplorer 和路由

Swashbuckle 严重依赖 ASP.NET Core 附带的 API 元数据层。如果使用帮助程序引导 MVC 堆栈,则 ApiExplorer 将自动注册,并且 SB 将正常工作。但是,如果用于更配对的 MVC 堆栈,则需要显式添加 ApiExplorer 服务:ApiExplorerAddMvcAddMvcCore

services.AddMvcCore()
    .AddApiExplorer();

此外,如果您使用的是传统路由(而不是属性路由),则任何使用传统路由的控制器上的操作都不会在 ApiExplorer 中表示,这意味着 Swashbuckle 将无法找到这些控制器并从中生成 Swagger 操作。例如:

app.UseMvc(routes =>
{
   // SwaggerGen won't find controllers that are routed via this technique.
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

您必须对要在 Swagger 文档中表示的任何控制器使用属性路由:

[Route("example")]
public class ExampleController : Controller
{
    [HttpGet("")]
    public IActionResult DoStuff() { /**/ }
}

组件

Swashbuckle 由多个组件组成,可以根据您的需要一起使用或单独使用。其核心是一个 Swagger 生成器、将其公开为 JSON 端点的中间件,以及 swagger-ui 的打包版本。这 3 个包可以与“元包”一起安装,并且可以无缝地协同工作(请参阅入门),以提供从您的代码自动生成的精美 API 文档。Swashbuckle.AspNetCore

此外,还有附加组件包(CLI 工具、备用 UI 等),您可以根据需要选择安装和配置。

“核心”包(即通过 Swashbuckle.AspNetCore 安装)

描述
Swashbuckle.AspNetCore.Swagger公开 Swagger JSON 端点。它希望在 DI 容器中注册一个实现,它查询以检索该容器,然后将其公开为序列化 JSONISwaggerProviderOpenAPIDocument(s)
Swashbuckle.AspNetCore.SwaggerGen注入上述组件可以使用的实现。此特定实现从您的路由、控制器和模型生成ISwaggerProviderOpenApiDocument(s)
Swashbuckle.AspNetCore.SwaggerUI公开 swagger-ui 的嵌入式版本。您可以指定可以获取 Swagger JSON 的 API 端点,并使用它们为您的 API 提供交互式文档

附加套餐

描述
Swashbuckle.AspNetCore.Annotations包括一组自定义属性,可应用于控制器、操作和模型,以丰富生成的 Swagger
Swashbuckle.AspNetCore.Cli提供命令行界面,用于直接从启动程序集中检索 Swagger 并写入文件
Swashbuckle.AspNetCore.ReDoc公开 ReDoc UI 的嵌入式版本(swagger-ui 的替代方法)

社区套餐

这些软件包由开源社区提供。

描述
Swashbuckle.AspNetCore.Filters一些有用的 Swashbuckle 过滤器,可添加其他文档,例如请求和响应示例、授权信息等。有关详细信息,请参阅其自述文件
Unchase.Swashbuckle.AspNetCore.Extensions一些有用的扩展(筛选器),它们添加了额外的文档,例如隐藏未接受角色的 PathItems、修复客户端代码生成的枚举等。有关详细信息,请参阅其自述文件
MicroElements.Swashbuckle.FluentValidation使用 FluentValidation 规则而不是 ComponentModel 属性来扩充生成的 Swagger 架构
MMLib.SwaggerForOcelot直接在 Ocelot API Gateway 上通过微服务聚合文档

Swashbuckle.AspNetCore.Swagger

更改 Swagger JSON 终结点的路径

默认情况下,Swagger JSON 将在以下路由中公开 - “/swagger/{documentName}/swagger.json”。如有必要,您可以在启用 Swagger 中间件时更改此设置。自定义路由必须包含该参数。{documentName}

app.UseSwagger(c =>
{
    c.RouteTemplate = "api-docs/{documentName}/swagger.json";
})

注意:如果使用的是 SwaggerUI 中间件,则还需要更新其配置以反映新的终结点:

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/api-docs/v1/swagger.json", "My API V1");
})

注意:如果还需要更新 UI 本身可用的相对路径,则需要按照更改 UI 的相对路径中的说明进行操作。

使用请求上下文修改 Swagger

如果需要根据当前请求设置一些 Swagger 元数据,可以配置在序列化文档之前执行的筛选器。

app.UseSwagger(c =>
{
    c.PreSerializeFilters.Add((swagger, httpReq) =>
    {
        swagger.Servers = new List<OpenApiServer> { new OpenApiServer { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}" } };
    });
});

和电流都传递到滤波器。这提供了很大的灵活性。例如,您可以基于“Host”标头(如图所示)添加显式 API 服务器,也可以检查会话信息或 Authorization 标头,并根据用户权限从文档中删除操作。OpenApiDocumentHttpRequest

以 2.0 格式序列化 Swagger

默认情况下,Swashbuckle 将在规范的 3.0 版本(正式称为 OpenAPI 规范)中生成并公开 Swagger JSON。但是,若要支持向后兼容性,可以选择使用以下选项继续以 2.0 格式公开它:

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

使用虚拟目录和反向代理

虚拟目录和反向代理可能会导致生成链接和重定向的应用程序出现问题,尤其是在应用根据标头和当前请求中的其他信息返回绝对 URL 时。为了避免这些问题,Swashbuckle 尽可能使用相对 URL,并鼓励在配置 SwaggerUI 和 ReDoc 中间件时使用它们。Host

例如,要连接 SwaggerUI 中间件,您需要提供一个或多个 OpenAPI/Swagger 文档的 URL。这是客户端应用程序 swagger-ui 将调用的 URL,用于检索 API 元数据。为了确保这在虚拟目录和反向代理后面工作,你应该相对于 swagger-ui 本身来表达这一点:RoutePrefix

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

注意:在早期版本的文档中,您可能已经看到它表示为相对根链接(例如 /swagger/v1/swagger.json)。如果应用托管在 IIS 虚拟目录上或位于代理后面,该代理在转发之前修整请求路径,则此操作不起作用。如果切换到上面所示的页面相对语法,它应该在所有情况下都有效。

Swashbuckle.AspNetCore.SwaggerGen

分配显式 OperationIds

在 Swagger 中,可以为操作分配一个 .此 ID 在 API 中描述的所有操作中必须是唯一的。工具和库(例如客户端生成器)可以使用 operationId 来唯一标识操作,因此,建议遵循常见的编程命名约定。operationId

自动生成符合这些要求的 ID,同时提供在客户端库中有意义的名称是一项艰巨的任务,因此,Swashbuckle 默认省略了 。但是,如有必要,您可以通过装饰单个路线或提供自定义策略来分配。operationIdoperationIds

选项 1) 使用 Name 属性修饰路由

[HttpGet("{id}", Name = "GetProductById")]
public IActionResult Get(int id) // operationId = "GetProductById"

选项 2) 提供自定义策略

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...
    
    // Use method name as operationId
    c.CustomOperationIds(apiDesc =>
    {
        return apiDesc.TryGetMethodInfo(out MethodInfo methodInfo) ? methodInfo.Name : null;
    });
})

// ProductsController.cs
[HttpGet("{id}")]
public IActionResult GetProductById(int id) // operationId = "GetProductById"

注意:无论采用哪种方法,API 作者都有责任确保所有操作中 operationId 的唯一性

列出操作响应

默认情况下,Swashbuckle 将为每个操作生成“200”响应。如果操作返回响应 DTO,则这将用于生成响应正文的架构。例如。。。

[HttpPost("{id}")]
public Product GetById(int id)

将生成以下响应元数据:

<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>responses: {
  200: {
    description: "Success",
    content: {
      "application/json": {
        schema: {
          $ref: "#/components/schemas/Product"
        }
      }
    }
  }
}
</code></span></span></span></span>
显式响应

如果需要指定不同的状态代码和/或其他响应,或者您的操作返回而不是响应 DTO,则可以使用 ASP.NET Core 附带的 显式描述响应。例如。。。IActionResultProducesResponseTypeAttribute

[HttpPost("{id}")]
[ProducesResponseType(typeof(Product), 200)]
[ProducesResponseType(typeof(IDictionary<string, string>), 400)]
[ProducesResponseType(500)]
public IActionResult GetById(int id)

将生成以下响应元数据:

<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>responses: {
  200: {
    description: "Success",
    content: {
      "application/json": {
        schema: {
          $ref: "#/components/schemas/Product"
        }
      }
    }
  },
  400: {
    description: "Bad Request",
    content: {
      "application/json": {
        schema: {
          type: "object",
          additionalProperties: {
            type: "string"
          }
        }
      }
    }
  },
  500: {
    description: "Server Error",
    content: {}
  }
}
</code></span></span></span></span>

标记必需的参数和架构属性

在 Swagger 文档中,您可以标记请求所需的参数和架构属性。如果参数(顶级或基于属性)使用 or 修饰,则 Swashbuckle 会在生成的 Swagger 中自动将其标记为“必需”参数:BindRequiredAttributeRequiredAttribute

// ProductsController.cs
public IActionResult Search([FromQuery, BindRequired]string keywords, [FromQuery]PagingParams pagingParams)
{
    if (!ModelState.IsValid)
        return BadRequest(ModelState);
    ...
}

// SearchParams.cs
public class PagingParams
{
    [Required]
    public int PageNo { get; set; }

    public int PageSize { get; set; }
}

除了参数之外,Swashbuckle 还将遵循在绑定到请求正文的模型中使用时。在这种情况下,修饰后的属性将在正文描述中标记为“必需”属性:RequiredAttribute

// ProductsController.cs
public IActionResult Create([FromBody]Product product)
{
    if (!ModelState.IsValid)
        return BadRequest(ModelState);
    ...
}

// Product.cs
public class Product
{
    [Required]
    public string Name { get; set; }

    public string Description { get; set; }
}

处理表单和文件上传

此控制器将接受两个表单字段值和一个从同一表单上传的命名文件:

[HttpPost]
public void UploadFile([FromForm]string description, [FromForm]DateTime clientDate, IFormFile file)

重要说明:根据 ASP.NET Core 文档,您不应该使用该属性修饰参数,因为绑定源是从类型自动推断出来的。事实上,推断的值是,如果您应用它将设置为的属性,这将搞砸 ,ASP.NET Core 附带的元数据组件,并且 Swashbuckle 严重依赖。这里的一个特殊问题是,如果您错误地包含此属性,SwaggerUI 不会将参数视为文件,因此不会显示文件上传按钮。IFormFile[FromForm]BindingSource.FormFileBindingSource.FormApiExplorer

处理文件下载

ApiExplorer(构建 Swashbuckle 的 ASP.NET Core 元数据组件)默认情况下显示类型,因此您需要使用属性显式告诉它:FileResultProduces

[HttpGet("{fileName}")]
[Produces("application/octet-stream", Type = typeof(FileResult))]
public FileResult GetFile(string fileName)

如果您希望 swagger-ui 显示“下载文件”链接,则您的操作将需要返回“application/octet-stream”的 Content-Type 或“attachement”的 Content-Disposition

包括 XML 注释中的说明

要使用人性化的描述来增强生成的文档,您可以使用 Xml 注释注释控制器操作和模型,并配置 Swashbuckle 以将这些注释合并到输出的 Swagger JSON 中:

  1. 打开项目的“属性”对话框,单击“生成”选项卡,确保选中“XML 文档文件”,或将元素添加到 .csproj 项目文件的部分。这将在构建时生成一个包含所有 XML 注释的文件。<GenerateDocumentationFile>true</GenerateDocumentationFile><PropertyGroup>

    此时,任何未使用 XML 注释批注的类或方法都将触发生成警告。若要禁止显示此问题,请在属性对话框的“禁止显示警告”字段中输入警告代码“1591”,或将 <NoWarn>1591</NoWarn>添加到 .csproj 项目文件的 <PropertyGroup> 部分。

  2. 配置 Swashbuckle 以将文件上的 XML 注释合并到生成的 Swagger JSON 中:

    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1",
            new OpenApiInfo
            {
                Title = "My API - V1",
                Version = "v1"
            }
         );
    
         var filePath = Path.Combine(System.AppContext.BaseDirectory, "MyApi.xml");
         c.IncludeXmlComments(filePath);
    }
  3. 使用摘要、备注、参数和响应标签注释您的操作:

    /// <summary>
    /// Retrieves a specific product by unique id
    /// </summary>
    /// <remarks>Awesomeness!</remarks>
    /// <param name="id" example="123">The product id</param>
    /// <response code="200">Product retrieved</response>
    /// <response code="404">Product not found</response>
    /// <response code="500">Oops! Can't lookup your product right now</response>
    [HttpGet("{id}")]
    [ProducesResponseType(typeof(Product), 200)]
    [ProducesResponseType(404)]
    [ProducesResponseType(500)]
    public Product GetById(int id)
  4. 您还可以使用摘要和示例标签对类型进行批注:

    public class Product
    {
        /// <summary>
        /// The name of the product
        /// </summary>
        /// <example>Men's basketball shoes</example>
        public string Name { get; set; }
    
        /// <summary>
        /// Quantity left in stock
        /// </summary>
        /// <example>10</example>
        public int AvailableStock { get; set; }
    
    /// <summary>
        /// The sizes the product is available in
        /// </summary>
        /// <example>["Small", "Medium", "Large"]</example>
    public List<string> Sizes { get; set; }
    }
  5. 重新生成项目以更新 XML 注释文件并导航到 Swagger JSON 终结点。请注意描述是如何映射到相应的 Swagger 字段的。

注意:您还可以通过使用摘要标签注释 API 模型及其属性来提供 Swagger 架构描述。如果您有多个 XML 注释文件(例如,控制器和模型的单独库),则可以多次调用 IncludeXmlComments 方法,它们都将合并到输出的 Swagger JSON 中。

提供全局 API 元数据

除了 Swashbuckle 为您生成的“PathItems”、“Operations”和“Responses”之外,Swagger 还支持全局元数据(参见 OpenAPI Specification - Version 3.1.0 | Swagger)。例如,您可以提供 API 的完整描述、服务条款,甚至是联系方式和许可信息:

c.SwaggerDoc("v1",
    new OpenApiInfo
    {
        Title = "My API - V1",
        Version = "v1",
        Description = "A sample API to demo Swashbuckle",
        TermsOfService = new Uri("http://tempuri.org/terms"),
        Contact = new OpenApiContact
        {
            Name = "Joe Developer",
            Email = "joe.developer@tempuri.org"
        },
        License = new OpenApiLicense
        {
            Name = "Apache 2.0",
            Url = new Uri("http://www.apache.org/licenses/LICENSE-2.0.html")
        }
    }
);

提示:使用 IntelliSense 查看还有哪些其他字段可用。

生成多个 Swagger 文档

通过上述设置,生成器将包含所有 API 操作在一个 Swagger 文档中。但是,如有必要,您可以创建多个文档。例如,您可能希望为每个版本的 API 提供单独的文档。为此,首先在以下位置定义多个 Swagger 文档:Startup.cs

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API - V1", Version = "v1" });
    c.SwaggerDoc("v2", new OpenApiInfo { Title = "My API - V2", Version = "v2" });
})

请注意 SwaggerDoc 的第一个参数。它必须是唯一标识文档的 URI 友好名称。随后,它用于创建请求相应 Swagger JSON 的路径。例如,使用默认路由时,上述文档将在“/swagger/v1/swagger.json”和“/swagger/v2/swagger.json”中提供。

接下来,您需要通知 Swashbuckle 要在每个文档中包含哪些操作。尽管可以自定义(见下文),但默认情况下,生成器将使用 ASP.NET Core 附带的内置元数据层的一部分属性来进行此区分。您可以通过修饰单个操作或应用应用程序范围的约定来设置此设置。ApiDescription.GroupName

装饰个人动作

若要在特定 Swagger 文档中包含操作,请使用 和 设置为相应的文档名称(区分大小写)进行修饰:ApiExplorerSettingsAttributeGroupName

[HttpPost]
[ApiExplorerSettings(GroupName = "v2")]
public void Post([FromBody]Product product)
按约定将操作分配给文档

若要按约定分组而不是修饰每个操作,可以应用自定义控制器或操作约定。例如,您可以连接以下约定,以根据控制器命名空间将操作分配给文档。

// ApiExplorerGroupPerVersionConvention.cs
public class ApiExplorerGroupPerVersionConvention : IControllerModelConvention
{
    public void Apply(ControllerModel controller)
    {
        var controllerNamespace = controller.ControllerType.Namespace; // e.g. "Controllers.V1"
        var apiVersion = controllerNamespace.Split('.').Last().ToLower();

        controller.ApiExplorer.GroupName = apiVersion;
    }
}

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(c =>
        c.Conventions.Add(new ApiExplorerGroupPerVersionConvention())
    );

    ...
}
自定义操作选择过程

在为给定的 Swagger 文档选择操作时,生成器会针对框架显示的每个操作调用一个。如果值为 null 或等于请求的文档名称,则默认实现将检查并返回 true。但是,您也可以提供自定义包含谓词。例如,如果使用基于属性的方法实现 API 版本控制(例如 Microsoft.AspNetCore.Mvc.Versioning),则可以配置利用版本控制属性的自定义谓词:DocInclusionPredicateApiDescriptionApiDescription.GroupName

c.DocInclusionPredicate((docName, apiDesc) =>
{
    if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo)) return false;

    var versions = methodInfo.DeclaringType
        .GetCustomAttributes(true)
        .OfType<ApiVersionAttribute>()
        .SelectMany(attr => attr.Versions);

    return versions.Any(v => $"v{v.ToString()}" == docName);
});
通过 UI 公开多个文档

如果使用的是中间件,则需要指定要公开的任何其他 Swagger 终结点。有关详细信息,请参阅列出多个 Swagger 文档SwaggerUI

省略过时的操作和/或架构属性

Swagger 规范包含一个标志,用于指示操作已弃用且应避免使用。Swagger 生成器将自动设置此标志,如果相应的操作用 .但是,您可以将生成器配置为完全忽略过时的操作,而不是设置标志:deprecatedObsoleteAttribute

services.AddSwaggerGen(c =>
{
    ...
    c.IgnoreObsoleteActions();
};

类似的方法也可用于在 Swagger 输出中省略架构中的过时属性。也就是说,您可以使用 并配置 Swashbuckle 以在生成 JSON 架构时省略这些属性:ObsoleteAttribute

services.AddSwaggerGen(c =>
{
    ...
    c.IgnoreObsoleteProperties();
};

省略任意操作

您可以通过修饰单个操作或应用应用程序范围的约定来省略 Swagger 输出中的操作。

装饰个人动作

若要省略特定操作,请使用 并设置标志来修饰它:ApiExplorerSettingsAttributeIgnoreApi

[HttpGet("{id}")]
[ApiExplorerSettings(IgnoreApi = true)]
public Product GetById(int id)
按约定省略操作

若要按约定省略操作而不是单独修饰它们,可以应用自定义操作约定。例如,您可以将以下约定连接起来,以仅记录 GET 操作:

// ApiExplorerGetsOnlyConvention.cs
public class ApiExplorerGetsOnlyConvention : IActionModelConvention
{
    public void Apply(ActionModel action)
    {
        action.ApiExplorer.IsVisible = action.Attributes.OfType<HttpGetAttribute>().Any();
    }
}

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(c =>
        c.Conventions.Add(new ApiExplorerGetsOnlyConvention())
    );

    ...
}

自定义操作标签(例如用于 UI 分组)

Swagger 规范允许将一个或多个“标签”分配给操作。Swagger 生成器会将控制器名称指定为默认标记。如果您使用的是中间件,请务必注意这一点,因为它使用此值对操作进行分组。SwaggerUI

您可以通过提供按约定应用标签的函数来覆盖默认标签。例如,以下配置将通过 HTTP 方法标记 UI 中的操作,从而对操作进行分组:

services.AddSwaggerGen(c =>
{
    ...
    c.TagActionsBy(api => api.HttpMethod);
};

更改操作排序顺序(例如,用于 UI 排序)

默认情况下,操作在被分组到 Swagger 规范的以路径为中心的嵌套结构之前,按分配的标记(见上文)排序。但是,您可以使用自定义排序策略更改操作的默认顺序:

services.AddSwaggerGen(c =>
{
    ...
    c.OrderActionsBy((apiDesc) => $"{apiDesc.ActionDescriptor.RouteValues["controller"]}_{apiDesc.HttpMethod}");
};

注意:这决定了在对操作进行分组并转换为 Swagger 格式之前的排序顺序。因此,它会影响 Swagger 输出中组的排序(即 Swagger “PathItems”),以及组内操作的排序。

自定义架构 ID

如果生成器遇到复杂的参数或响应类型,会生成对应的 JSON Schema,添加到全局字典中,并通过唯一 ID 从操作描述中引用。例如,如果您有一个返回类型的操作,则将按如下方式引用生成的架构:components/schemasProduct

<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>responses: {
  200: {
    description: "Success",
    content: {
      "application/json": {
        schema: {
          $ref: "#/components/schemas/Product"
        }
      }
    }
  }
}
</code></span></span></span></span>

但是,如果它遇到多个具有相同名称但不同命名空间的类型(例如 & ),则 Swashbuckle 将引发由于“冲突的 schemaIds”而引发异常。在这种情况下,您需要提供自定义 Id 策略,以进一步限定名称:RequestModels.ProductResponseModels.Product

services.AddSwaggerGen(c =>
{
    ...
    c.CustomSchemaIds((type) => type.FullName);
};

覆盖特定类型的架构

开箱即用,Swashbuckle 在生成准确描述请求和响应有效负载的 JSON 模式方面做得不错。但是,如果要在 API 中自定义某些类型的序列化行为,则可能需要提供帮助。

例如,您可能有一个具有多个属性的类,您希望在 JSON 中将其表示为逗号分隔的字符串。为此,您可能会实现自定义 .在这种情况下,Swashbuckle 不知道转换器是如何实现的,因此您需要为其提供准确描述类型的架构:JsonConverter

// PhoneNumber.cs
public class PhoneNumber
{
    public string CountryCode { get; set; }

    public string AreaCode { get; set; }

    public string SubscriberId { get; set; }
}

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...
    c.MapType<PhoneNumber>(() => new OpenApiSchema { Type = "string" });
};

使用操作、模式和文档过滤器扩展生成器

Swashbuckle 公开了一个与生成过程挂钩的过滤器管道。生成后,单个元数据对象将传递到管道中,在那里可以进一步修改它们。您可以连接自定义过滤器以丰富生成的“操作”、“架构”和“文档”。

操作过滤器

Swashbuckle 为每个操作检索 ASP.NET Core 的一部分,并使用它来生成相应的 .生成后,它会通过配置的操作过滤器列表传递 和 。ApiDescriptionOpenApiOperationOpenApiOperationApiDescription

在典型的过滤器实现中,您将检查相关信息(例如路线信息、操作属性等),然后相应地更新。例如,以下筛选器列出了使用 :ApiDescriptionOpenApiOperationAuthorizeAttribute

// AuthResponsesOperationFilter.cs
public class AuthResponsesOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
            .Union(context.MethodInfo.GetCustomAttributes(true))
            .OfType<AuthorizeAttribute>();

        if (authAttributes.Any())
            operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
    }
}

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...
    c.OperationFilter<AuthResponsesOperationFilter>();
};

注意:过滤器管道具有 DI 感知功能。也就是说,您可以使用构造函数参数创建筛选器,如果参数类型已注册到 DI 框架,则在实例化筛选器时会自动注入它们

架构筛选器

Swashbuckle 为控制器操作公开的每个参数、响应和属性类型生成 Swagger 风格的 JSONSchema。生成后,它会通过配置的架构筛选器列表传递架构和类型。

下面的示例添加了一个 AutoRest 供应商扩展(请参阅 autorest/docs/extensions/readme.md at main · Azure/autorest · GitHub),以告知 AutoRest 工具在生成 API 客户端时应如何对枚举进行建模。

// AutoRestSchemaFilter.cs
public class AutoRestSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        var type = context.Type;
        if (type.IsEnum)
        {
            schema.Extensions.Add(
                "x-ms-enum",
                new OpenApiObject
                {
                    ["name"] = new OpenApiString(type.Name),
                    ["modelAsString"] = new OpenApiBoolean(true)
                }
            );
        };
    }
}

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...
    c.SchemaFilter<AutoRestSchemaFilter>();
};

The example below allows for automatic schema generation of generic objects. Note that this only generates the swagger; is not able to parse dictionary enums by default, so you will need a special JsonConverter, like in the .NET docsDictionary<Enum, TValue>System.Text.Json

// DictionaryTKeyEnumTValueSchemaFilter.cs
public class DictionaryTKeyEnumTValueSchemaFilter : ISchemaFilter
{
  public void Apply(OpenApiSchema schema, SchemaFilterContext context)
  {
    // Only run for fields that are a Dictionary<Enum, TValue>
    if (!context.Type.IsGenericType || !context.Type.GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<,>)))
    {
return;
    }

    var keyType = context.Type.GetGenericArguments()[0];
    var valueType = context.Type.GetGenericArguments()[1];

    if (!keyType.IsEnum)
    {
return;
    }

    schema.Type = "object";
    schema.Properties = keyType.GetEnumNames().ToDictionary(name => name,
name => context.SchemaGenerator.GenerateSchema(valueType,
  context.SchemaRepository));
  }
}

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...
    // These will be replaced by DictionaryTKeyEnumTValueSchemaFilter, but are needed to avoid an error.
    // You will need one for every kind of Dictionary<,> you have.
    c.MapType<Dictionary<MyEnum, List<string>>>(() => new OpenApiSchema());
    c.SchemaFilter<DictionaryTKeyEnumTValueSchemaFilter>();
};
	
文档过滤器

生成后,也可以通过一组预配置的文档过滤器传递它。这样可以完全控制以您认为合适的方式修改文档。为确保仍返回有效的 Swagger JSON,在使用此筛选器类型之前,应通读规范OpenApiDocument

下面的示例提供了分配给文档中操作的任何标记的说明:

public class TagDescriptionsDocumentFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        swaggerDoc.Tags = new List<OpenApiTag> {
            new OpenApiTag { Name = "Products", Description = "Browse/manage the product catalog" },
            new OpenApiTag { Name = "Orders", Description = "Submit orders" }
        };
    }
}

注意:如果使用的是 SwaggerUI 中间件,则上面演示的 TagDescriptionsDocumentFilter 可用于在每组操作旁边显示其他说明。

添加安全定义和要求

在 Swagger 中,您可以通过定义一个或多个安全方案(例如 basic、api key、oauth2 等)并声明哪些方案适用于全球或特定操作来描述您的 API 是如何保护的。有关更多详细信息,请查看 Swagger 规范中的安全要求对象。

在 Swashbuckle 中,可以通过调用方法定义方案,并提供 的名称和实例。例如,您可以定义 OAuth 2.0 - 隐式流,如下所示:AddSecurityDefinitionOpenApiSecurityScheme

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...

    // Define the OAuth2.0 scheme that's in use (i.e. Implicit Flow)
    c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.OAuth2,
        Flows = new OpenApiOAuthFlows
        {
            Implicit = new OpenApiOAuthFlow
            {
                AuthorizationUrl = new Uri("/auth-server/connect/authorize", UriKind.Relative),
                Scopes = new Dictionary<string, string>
                {
                    { "readAccess", "Access read operations" },
                    { "writeAccess", "Access write operations" }
                }
            }
        }
    });
};

注意:除了定义方案外,还需要指明该方案适用于哪些操作。您可以通过 AddSecurityRequirement 方法全局应用方案(即应用于所有操作)。下面的示例指示名为“oauth2”的方案应应用于所有操作,并且“readAccess”和“writeAccess”范围是必需的。应用“oauth2”以外的方案时,作用域数组必须为空。

c.AddSwaggerGen(c =>
{
    ...

    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
            },
            new[] { "readAccess", "writeAccess" }
        }
    });
})

如果您的方案仅适用于某些操作,则可以通过操作筛选器应用它们。例如,以下筛选器根据 OAuth2 的存在添加 OAuth<> 要求:AuthorizeAttribute

// SecurityRequirementsOperationFilter.cs
public class SecurityRequirementsOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        // Policy names map to scopes
        var requiredScopes = context.MethodInfo
            .GetCustomAttributes(true)
            .OfType<AuthorizeAttribute>()
            .Select(attr => attr.Policy)
            .Distinct();

        if (requiredScopes.Any())
        {
            operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
            operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });

            var oAuthScheme = new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
            };

            operation.Security = new List<OpenApiSecurityRequirement>
            {
                new OpenApiSecurityRequirement
                {
                    [ oAuthScheme ] = requiredScopes.ToList()
                }
            };
        }
    }
}

注意:如果您使用的是 SwaggerUI 中间件,则可以启用由发出的安全元数据提供支持的交互式 OAuth2.0 流。有关更多详细信息,请参阅启用 OAuth2.0 流

添加持有者身份验证的安全定义和要求

services.AddSwaggerGen(c =>
{
    c.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.Http,
        Scheme = "bearer",
        BearerFormat = "JWT",
        Description = "JWT Authorization header using the Bearer scheme."
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearerAuth" }
            },
            new string[] {}
        }
    });
});

遗传和多态性

Swagger / OpenAPI 定义了用于描述模式定义中的继承和多态关系的 and 关键字。例如,如果对共享公共属性的模型使用基类,则可以使用关键字来描述继承层次结构。或者,如果序列化程序支持多态序列化/反序列化,则可以使用关键字记录因子类型而异的请求/响应的所有“可能”架构。allOfoneOfallOfoneOf

启用继承

默认情况下,Swashbuckle 会展平继承层次结构。也就是说,对于派生模型,继承的属性将合并并与声明的属性一起列出。这可能会导致生成的 Swagger 出现大量重复,尤其是当有多个子类型时。如果您使用的是客户端生成器(例如 NSwag),并且希望在生成的客户端模型中维护继承层次结构,这也是有问题的。若要解决此问题,可以应用该设置,这将利用关键字在生成的 Swagger 中通过引用合并继承的属性:UseAllOfForInheritanceallOf

<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>Circle: {
  type: "object",
  allOf: [
    {
      $ref: "#/components/schemas/Shape"
    }
  ],
  properties: {
    radius: {
      type: "integer",
      format: "int32",
    }
  },
},
Shape: {
  type: "object",
  properties: {
    name: {
      type: "string",
      nullable: true,
    }
  },
}
</code></span></span></span></span>
启用多态性

如果序列化程序支持多态序列化/反序列化,并且想要列出接受/返回抽象基类型的操作的可能子类型,则可以应用该设置。因此,生成的请求/响应架构将引用“可能”架构的集合,而不仅仅是基类架构:UseOneOfForPolymorphism

<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>requestBody: {
  content: {
    application/json: {
      schema: {
      oneOf: [
        {
          $ref: "#/components/schemas/Rectangle"
        },
        {
          $ref: "#/components/schemas/Circle"
        },
      ],
    }
  }
}
</code></span></span></span></span>
检测亚型

As inheritance and polymorphism relationships can often become quite complex, not just in your own models but also within the .NET class library, Swashbuckle is selective about which hierarchies it does and doesn't expose in the generated Swagger. By default, it will pick up any subtypes that are defined in the same assembly as a given base type. If you'd like to override this behavior, you can provide a custom selector function:

services.AddSwaggerGen(c =>
{
    ...

    c.UseAllOfForInheritance();

    c.SelectSubTypesUsing(baseType =>
    {
        return typeof(Startup).Assembly.GetTypes().Where(type => type.IsSubclassOf(baseType));
    })
});

NOTE: If you're using the Swashbuckle Annotations library, it contains a custom selector that's based on the presence of SwaggerSubType attributes on base class definitions. This way, you can use simple attributes to explicitly list the inheritance and/or polymorphism relationships you want to expose. To enable this behavior, check out the Annotations docs.

Describing Discriminators

In conjunction with the and/or keywords, Swagger / OpenAPI supports a field on base schema definitions. This keyword points to the property that identifies the specific type being represented by a given payload. In addition to the property name, the discriminator description MAY also include a which maps discriminator values to specific schema definitions.oneOfallOfdiscriminatormapping

For example, the Newtonsoft serializer supports polymorphic serialization/deserialization by emitting/accepting a "$type" property on JSON instances. The value of this property will be the assembly qualified type name of the type represented by a given JSON instance. So, to explicitly describe this behavior in Swagger, the corresponding request/response schema could be defined as follows:

<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>components: {
  schemas: {
    Shape: {
      required: [
        "$type"
      ],
      type: "object",
      properties: {
        $type: {
          type": "string"
      },
      discriminator: {
        propertyName: "$type",
        mapping: {
          Rectangle: "#/components/schemas/Rectangle",
          Circle: "#/components/schemas/Circle"
        }
      }
    },
    Rectangle: {
      type: "object",
      allOf: [
        {
          "$ref": "#/components/schemas/Shape"
        }
      ],
      ...
    },
    Circle: {
      type: "object",
      allOf: [
        {
          "$ref": "#/components/schemas/Shape"
        }
      ],
      ...
    }
  }
}
</code></span></span></span></span>

If or is enabled, and your serializer supports (and has enabled) emitting/accepting a discriminator property, then Swashbuckle will automatically generate the corresponding metadata on base schema definitions.UseAllOfForInheritanceUseOneOfForPolymorphismdiscriminator

Alternatively, if you've customized your serializer to support polymorphic serialization/deserialization, you can provide some custom selector functions to determine the discriminator name and corresponding mapping:

services.AddSwaggerGen(c =>
{
    ...

    c.UseOneOfForInheritance();

    c.SelectDiscriminatorNameUsing((baseType) => "TypeName");
    c.SelectDiscriminatorValueUsing((subType) => subType.Name);
});

NOTE: If you're using the Swashbuckle Annotations library, it contains custom selector functions that are based on the presence of SwaggerDiscriminator and SwaggerSubType attributes on base class definitions. This way, you can use simple attributes to explicitly provide discriminator metadata. To enable this behavior, check out the Annotations docs.

Swashbuckle.AspNetCore.SwaggerUI

Change Relative Path to the UI

By default, the Swagger UI will be exposed at "/swagger". If necessary, you can alter this when enabling the SwaggerUI middleware:

app.UseSwaggerUI(c =>
{
    c.RoutePrefix = "api-docs"
    ...
}

Change Document Title

By default, the Swagger UI will have a generic document title. When you have multiple Swagger pages open, it can be difficult to tell them apart. You can alter this when enabling the SwaggerUI middleware:

app.UseSwaggerUI(c =>
{
    c.DocumentTitle = "My Swagger UI";
    ...
}

List Multiple Swagger Documents

When enabling the middleware, you're required to specify one or more Swagger endpoints (fully qualified or relative to the UI page) to power the UI. If you provide multiple endpoints, they'll be listed in the top right corner of the page, allowing users to toggle between the different documents. For example, the following configuration could be used to document different versions of an API.

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1 Docs");
    c.SwaggerEndpoint("/swagger/v2/swagger.json", "V2 Docs");
}

Apply swagger-ui Parameters

The swagger-ui ships with its own set of configuration parameters, all described here swagger-ui/docs/usage/configuration.md at v3.8.1 · swagger-api/swagger-ui · GitHub. In Swashbuckle, most of these are surfaced through the SwaggerUI middleware options:

app.UseSwaggerUI(c =>
{
    c.DefaultModelExpandDepth(2);
    c.DefaultModelRendering(ModelRendering.Model);
    c.DefaultModelsExpandDepth(-1);
    c.DisplayOperationId();
    c.DisplayRequestDuration();
    c.DocExpansion(DocExpansion.None);
    c.EnableDeepLinking();
    c.EnableFilter();
    c.MaxDisplayedTags(5);
    c.ShowExtensions();
    c.ShowCommonExtensions();
    c.EnableValidator();
    c.SupportedSubmitMethods(SubmitMethod.Get, SubmitMethod.Head);
    c.UseRequestInterceptor("(request) => { return request; }");
    c.UseResponseInterceptor("(response) => { return response; }");
});

NOTE: The InjectOnCompleteJavaScript and InjectOnFailureJavaScript options have been removed because the latest version of swagger-ui doesn't expose the necessary hooks. Instead, it provides a flexible customization system based on concepts and patterns from React and Redux. To leverage this, you'll need to provide a custom version of index.html as described below.

The custom index sample app demonstrates this approach, using the swagger-ui plugin system provide a custom topbar, and to hide the info component.

Inject Custom CSS

To tweak the look and feel, you can inject additional CSS stylesheets by adding them to your folder and specifying the relative paths in the middleware options:wwwroot

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

Customize index.html

To customize the UI beyond the basic options listed above, you can provide your own version of the swagger-ui index.html page:

app.UseSwaggerUI(c =>
{
    c.IndexStream = () => GetType().Assembly
        .GetManifestResourceStream("CustomUIIndex.Swagger.index.html"); // requires file to be added as an embedded resource
});

To get started, you should base your custom index.html on the default version

Enable OAuth2.0 Flows

The swagger-ui has built-in support to participate in OAuth2.0 authorization flows. It interacts with authorization and/or token endpoints, as specified in the Swagger JSON, to obtain access tokens for subsequent API calls. See Adding Security Definitions and Requirements for an example of adding OAuth2.0 metadata to the generated Swagger.

If your Swagger endpoint includes the appropriate security metadata, the UI interaction should be automatically enabled. However, you can further customize OAuth support in the UI with the following settings below. See swagger-ui/docs/usage/oauth2.md at v3.10.0 · swagger-api/swagger-ui · GitHub for more info:

app.UseSwaggerUI(c =>
{
    ...

    c.OAuthClientId("test-id");
    c.OAuthClientSecret("test-secret");
    c.OAuthRealm("test-realm");
    c.OAuthAppName("test-app");
    c.OAuthScopeSeparator(" ");
    c.OAuthAdditionalQueryStringParams(new Dictionary<string, string> { { "foo", "bar" }}); 
    c.OAuthUseBasicAuthenticationWithAccessCodeGrant();
});

Use client-side request and response interceptors

To use custom interceptors on requests and responses going through swagger-ui you can define them as javascript functions in the configuration:

app.UseSwaggerUI(c =>
{
    ...

    c.UseRequestInterceptor("(req) => { req.headers['x-my-custom-header'] = 'MyCustomValue'; return req; }");
    c.UseResponseInterceptor("(res) => { console.log('Custom interceptor intercepted response from:', res.url); return res; }");
});

This can be useful in a range of scenarios where you might want to append local xsrf tokens to all requests for example:

app.UseSwaggerUI(c =>
{
    ...

    c.UseRequestInterceptor("(req) => { req.headers['X-XSRF-Token'] = localStorage.getItem('xsrf-token'); return req; }");
});

Swashbuckle.AspNetCore.Annotations

Install and Enable Annotations

  1. Install the following Nuget package into your ASP.NET Core application.

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>Package Manager : Install-Package Swashbuckle.AspNetCore.Annotations
    CLI : dotnet add package Swashbuckle.AspNetCore.Annotations
    </code></span></span></span>
  2. In the method of , enable annotations within in the Swagger config block:ConfigureServicesStartup.cs

    services.AddSwaggerGen(c =>
    {
       ...
    
       c.EnableAnnotations();
    });

丰富操作元数据

启用注释后,可以通过使用 .SwaggerOperationAttribute

[HttpPost]

[SwaggerOperation(
    Summary = "Creates a new product",
    Description = "Requires admin privileges",
    OperationId = "CreateProduct",
    Tags = new[] { "Purchase", "Products" }
)]
public IActionResult Create([FromBody]Product product)

丰富响应元数据

ASP.NET Core 提供了用于列出操作可以返回的不同响应。如所述,这些属性可以与 XML 注释结合使用,以在生成的 Swagger 中为每个响应包含人性化的描述。如果您希望使用单个属性完成所有这些操作,并避免使用 XML 注释,则可以改用 s:ProducesResponseTypeAttributeSwaggerResponseAttribute

[HttpPost]
[SwaggerResponse(201, "The product was created", typeof(Product))]
[SwaggerResponse(400, "The product data is invalid")]
public IActionResult Create([FromBody]Product product)

丰富参数元数据

您可以用 a 注释 “path”、“query” 或 “header” 绑定参数或属性(即用 或 修饰),以丰富 Swashbuckle 生成的相应元数据:[FromRoute][FromQuery][FromHeader]SwaggerParameterAttributeParameter

[HttpGet]
public IActionResult GetProducts(
    [FromQuery, SwaggerParameter("Search keywords", Required = true)]string keywords)

扩充 RequestBody 元数据

您可以使用 a 注释“body”绑定参数或属性(即用 )来丰富 Swashbuckle 生成的相应元数据:[FromBody]SwaggerRequestBodyAttributeRequestBody

[HttpPost]
public IActionResult CreateProduct(
    [FromBody, SwaggerRequestBody("The product payload", Required = true)]Product product)

丰富架构元数据

您可以使用 a 注释类或属性,以丰富 Swashbuckle 生成的相应元数据:SwaggerSchemaAttributeSchema

[SwaggerSchema(Required = new[] { "Description" })]
public class Product
{
	[SwaggerSchema("The product identifier", ReadOnly = true)]
	public int Id { get; set; }

	[SwaggerSchema("The product description")]
	public string Description { get; set; }

	[SwaggerSchema("The date it was created", Format = "date")]
	public DateTime DateCreated { get; set; }
}

注意:在 Swagger / OpenAPI 中,序列化对象和包含的属性表示为架构实例,因此此注释可以应用于类和属性。另外值得注意的是,“必需”属性在顶级架构上被指定为属性名称数组,而不是每个单独属性上的标志。

将架构筛选器应用于特定类型

该包提供了多个扩展点,包括用于自定义所有生成的架构的架构筛选器(此处所述)。但是,在某些情况下,最好将筛选器应用于特定架构。例如,如果您想在 API 中包含特定类型的示例。这可以通过用 a 装饰类型来完成:SwaggerGenSwaggerSchemaFilterAttribute

// Product.cs
[SwaggerSchemaFilter(typeof(ProductSchemaFilter))]
public class Product
{
    ...
}

// ProductSchemaFilter.cs
public class ProductSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        schema.Example = new OpenApiObject
        {
            [ "Id" ] = new OpenApiInteger(1),
            [ "Description" ] = new OpenApiString("An awesome product")
        };
    }
}

Add Tag Metadata

By default, the Swagger generator will tag all operations with the controller name. This tag is then used to drive the operation groupings in the swagger-ui. If you'd like to provide a description for each of these groups, you can do so by adding metadata for each controller name tag via the :SwaggerTagAttribute

[SwaggerTag("Create, read, update and delete Products")]
public class ProductsController
{
    ...
}

NOTE: This will add the above description specifically to the tag named "Products". Therefore, you should avoid using this attribute if you're tagging Operations with something other than controller name - e.g. if you're customizing the tagging behavior with TagActionsBy.

List Known Subtypes for Inheritance and Polymorphism

If you want to use Swashbuckle's inheritance and/or polymorphism behavior, you can use annotations to explicitly indicate the "known" subtypes for a given base type. This will override the default selector function, which selects all subtypes in the same assembly as the base type, and therefore needs to be explicitly enabled when you enable Annotations:

// Startup.cs
services.AddSwaggerGen(c =>
{
    c.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);
});

// Shape.cs
[SwaggerSubType(typeof(Rectangle))]
[SwaggerSubType(typeof(Circle))]
public abstract class Shape
{
}

Enrich Polymorphic Base Classes with Discriminator Metadata

If you're using annotations to explicitly indicate the "known" subtypes for a polymorphic base type, you can combine the with the to provide additional metadata about the "discriminator" property, which will then be incorporated into the generated schema definition:SwaggerDiscriminatorAttributeSwaggerSubTypeAttribute

// Startup.cs
services.AddSwaggerGen(c =>
{
    c.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);
});

// Shape.cs
[SwaggerDiscriminator("shapeType")]
[SwaggerSubType(typeof(Rectangle), DiscriminatorValue = "rectangle")]
[SwaggerSubType(typeof(Circle), DiscriminatorValue = "circle")]
public abstract class Shape
{
    public ShapeType { get; set; }
}

This indicates that the corresponding payload will have a "shapeType" property to discriminate between subtypes, and that property will have a value of "rectangle" if the payload represents a type and a value of "circle" if it represents a type. This detail will be described in the generated schema definition as follows:RectangleCircle

<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>schema: {
  oneOf: [
    {
      $ref: "#/components/schemas/Rectangle"
    },
    {
      $ref: "#/components/schemas/Circle"
    },
  ],
  discriminator: {
    propertyName: shapeType,
    mapping: {
      rectangle: "#/components/schemas/Rectangle",
      circle: "#/components/schemas/Circle",
    }
  }
}
</code></span></span></span></span>

Swashbuckle.AspNetCore.Cli

Retrieve Swagger Directly from a Startup Assembly

Once your application has been setup with Swashbuckle (see Getting Started), you can use the Swashbuckle CLI tool to retrieve Swagger / OpenAPI JSON directly from your application's startup assembly, and write it to file. This can be useful if you want to incorporate Swagger generation into a CI/CD process, or if you want to serve it from static file at run-time.

It's packaged as a .NET Core Tool that can be installed and used via the dotnet SDK.

⚠️ The tool needs to load your Startup DLL and its dependencies at runtime. Therefore, you should use a version of the SDK that is compatible with your application. For example, if your app targets , then you should use version 2.1 of the SDK to run the CLI tool. If it targets , then you should use version 3.0 of the SDK and so on.dotnetnetcoreapp2.1netcoreapp3.0

Using the tool with the .NET Core 2.1 SDK
  1. Install as a global tool

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>dotnet tool install -g --version 6.5.0 Swashbuckle.AspNetCore.Cli
    </code></span></span></span>
  2. Verify that the tool was installed correctly

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>swagger tofile --help
    </code></span></span></span>
  3. Generate a Swagger/ OpenAPI document from your application's startup assembly

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>swagger tofile --output [output] [startupassembly] [swaggerdoc]
    </code></span></span></span>

    Where ...

    • [output] is the relative path where the Swagger JSON will be output to
    • [startupassembly] is the relative path to your application's startup assembly
    • [swaggerdoc] is the name of the swagger document you want to retrieve, as configured in your startup class
Using the tool with the .NET Core 3.0 SDK or later
  1. In your project root, create a tool manifest file:

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>dotnet new tool-manifest
    </code></span></span></span>
  2. Install as a local tool

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>dotnet tool install --version 6.5.0 Swashbuckle.AspNetCore.Cli
    </code></span></span></span>
  3. Verify that the tool was installed correctly

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>dotnet swagger tofile --help
    </code></span></span></span>
  4. Generate a Swagger / OpenAPI document from your application's startup assembly

    <span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>dotnet swagger tofile --output [output] [startupassembly] [swaggerdoc]
    </code></span></span></span>

    Where ...

    • [output] is the relative path where the Swagger JSON will be output to
    • [startupassembly] is the relative path to your application's startup assembly
    • [swaggerdoc] is the name of the swagger document you want to retrieve, as configured in your startup class

Use the CLI Tool with a Custom Host Configuration

Out-of-the-box, the tool will execute in the context of a "default" web host. However, in some cases you may want to bring your own host environment, for example if you've configured a custom DI container such as Autofac. For this scenario, the Swashbuckle CLI tool exposes a convention-based hook for your application.

That is, if your application contains a class that meets either of the following naming conventions, then that class will be used to provide a host for the CLI tool to run in.

  • public class SwaggerHostFactory, containing a public static method called with return type CreateHostIHost
  • public class SwaggerWebHostFactory, containing a public static method called with return type CreateWebHostIWebHost

For example, the following class could be used to leverage the same host configuration as your application:

public class SwaggerHostFactory
{
    public static IHost CreateHost()
    {
        return Program.CreateHostBuilder(new string[0]).Build();
    }
}

Swashbuckle.AspNetCore.ReDoc

Change Relative Path to the UI

By default, the ReDoc UI will be exposed at "/api-docs". If necessary, you can alter this when enabling the ReDoc middleware:

app.UseReDoc(c =>
{
    c.RoutePrefix = "docs"
    ...
}

Change Document Title

By default, the ReDoc UI will have a generic document title. You can alter this when enabling the ReDoc middleware:

app.UseReDoc(c =>
{
    c.DocumentTitle = "My API Docs";
    ...
}

Apply ReDoc Parameters

ReDoc ships with its own set of configuration parameters, all described here redoc/README.md at main · Redocly/redoc · GitHub. In Swashbuckle, most of these are surfaced through the ReDoc middleware options:

app.UseReDoc(c =>
{
    c.SpecUrl("/v1/swagger.json");
    c.EnableUntrustedSpec();
    c.ScrollYOffset(10);
    c.HideHostname();
    c.HideDownloadButton();
    c.ExpandResponses("200,201");
    c.RequiredPropsFirst();
    c.NoAutoAuth();
    c.PathInMiddlePanel();
    c.HideLoading();
    c.NativeScrollbars();
    c.DisableSearch();
    c.OnlyRequiredInSamples();
    c.SortPropsAlphabetically();
});

在同一个 UseReDoc(...) 中多次使用 c.SpecUrl(“/v1/swagger.json”) 不会添加多个 url。

注入自定义 CSS

要调整外观,您可以通过将其他 CSS 样式表添加到您的文件夹并在中间件选项中指定相对路径来注入它们:wwwroot

app.UseReDoc(c =>
{
    ...
    c.InjectStylesheet("/redoc/custom.css");
}

也可以使用属性修改主题,有关详细信息,请参阅 redoc/README.md at main · Redocly/redoc · GitHubAdditionalItems

app.UseReDoc(c =>
{
    ...
    c.ConfigObject.AdditionalItems = ...
}

自定义index.html

要自定义上面列出的基本选项之外的 UI,您可以提供自己的 ReDoc index.html 页面版本:

app.UseReDoc(c =>
{
    c.IndexStream = () => GetType().Assembly
        .GetManifestResourceStream("CustomIndex.ReDoc.index.html"); // requires file to be added as an embedded resource
});
码字不易,如果您觉的我的文章对您有帮助的话,建议您在经济能力之内慷慨打赏一元给我买瓶水, 这将是我下一步继续书写本题目的动力;如果您囊肿羞涩也没有关系,希望您点个关注,写点评论;您的支持将是我创作之路上的无线动力;青山依旧绿水长流,希望我们下期来能再见。 


 

  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Swashbuckle.AspNetCore.Newtonsoft是一个.NET Core中的扩展库,它提供了对Swagger UI和ReDoc的集成支持,并针对使用Newtonsoft.Json作为JSON序列化器的应用程序进行了优化。而Newtonsoft则是一个.NET中的开源JSON序列化器,它提供了丰富的功能和高性能的JSON序列化和反序列化能力。 在.NET Core应用程序中,通常使用Newtonsoft.Json作为默认的JSON序列化器,以实现对JSON格式数据的处理。而在使用Swagger UI和ReDoc等API文档生成工具时,通常需要将.NET Core应用程序暴露的API接口和数据模型转换为OpenAPI规范的文档格式。Swashbuckle.AspNetCore.Newtonsoft通过对Swagger UI和ReDoc的集成支持,以及对Newtonsoft.Json的优化,可以方便地实现这一转换过程。 Swashbuckle.AspNetCore.Newtonsoft通过对Newtonsoft.Json的优化,可以对应用程序中的JSON数据进行更加高效的序列化和反序列化处理。例如,它可以自动忽略循环引用、支持自定义序列化和反序列化规则等。同时,Swashbuckle.AspNetCore.Newtonsoft还提供了一些扩展功能,如支持XML注释、自定义UI等,可以方便地实现对API文档的定制化和优化。 综上所述,Swashbuckle.AspNetCore.Newtonsoft是一个专门针对使用Newtonsoft.Json作为JSON序列化器的.NET Core应用程序的Swagger UI和ReDoc集成扩展库,它通过对Newtonsoft.Json的优化,可以方便地实现对API文档生成和定制化。而Newtonsoft则是一个.NET中的开源JSON序列化器,它提供了丰富的功能和高性能的JSON序列化和反序列化能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A_nanda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值