SwaggerStudy/SwaggerStudy/Documents/README_zh.md

1590 lines
62 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

| **警告:** 如果您要在主要版本之间迁移,请特别注意。
|--------------|
|* 从 4.x 升级到 5.x需要注意几个重大更改查看[发行说明](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases/tag/v5.0.0) <br />* 先从3.x 升级到4.x,也有很多乌龙,查看 [发行说明](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases/tag/v4.0.0)|
Swashbuckle.AspNetCore
========
[![构建状态](Images/Master.svg)](https://ci.appveyor.com/project/domaindrivendev/ahoy/branch/master)
[![Nuget](Images/aspnetcore.svg)](https://www.nuget.org/packages/swashbuckle.aspnetcore/)
[Swagger](http://swagger.io) 为使用ASP.NET Coer构建API的工具。直接从您的路由、控制器和模型生成漂亮的API文档包括用于探索和测试操作的UI。
除[Swagger 2.0 and OpenAPI 3.0](http://swagger.io/specification/) 之外, Swashbuckle还提供了由Swagger JSON驱动的超棒的嵌入式swagger-ui。
这还不是全部 ......
一旦有了可以在Swagger中描述自己的API就可以使用基于Swagger的工具库其中包括可以针对各种流行平台的客户端生成器。详细情况参见 [swagger-codegen](https://github.com/swagger-api/swagger-codegen)
# 兼容性 #
|Swashbuckle Version|ASP.NET Core|Swagger / OpenAPI Spec.|swagger-ui|ReDoc UI|
|----------|----------|----------|----------|----------|
|[master](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/tree/master/README.md)|>= 2.0.0|2.0, 3.0|3.32.5|2.0.0-rc.40|
|[5.6.2](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/tree/v5.6.2)|>= 2.0.0|2.0, 3.0|3.32.5|2.0.0-rc.40|
|[4.0.0](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/tree/v4.0.0)|>= 2.0.0, < 3.0.0|2.0|3.19.5|1.22.2|
|[3.0.0](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/tree/v3.0.0)|>= 1.0.4, < 3.0.0|2.0|3.17.1|1.20.0|
|[2.5.0](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/tree/v2.5.0)|>= 1.0.4, < 3.0.0|2.0|3.16.0|1.20.0|
# 入门 #
1. 安装 Nuget包到您的**ASP.NET Core**应用程序中。
```
Nuget包管理器命令: Install-Package Swashbuckle.AspNetCore -Version 5.6.2
.Net Core CLI: dotnet add package --version 5.6.2 Swashbuckle.AspNetCore
```
2. `Startup.cs`类的`ConfigureServices`方法内,注册Swagger生成器,定义一个或多个Swagger文档。
```csharp
using Microsoft.OpenApi.Models;
```
```csharp
services.AddMvc();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
```
3. 确保使用显式的"Http"特性和"From"绑定装饰您的API方法和参数。
```csharp
[HttpPost]
public void CreateProduct([FromBody]Product product)
...
```
```csharp
[HttpGet]
public IEnumerable<Product> SearchProducts([FromQuery]string keywords)
...
```
_注意如果您省略显式参数绑定则默认情况下生成器会将其描述为"query"参数。__
4. 在该Configure方法中插入中间件以将生成的Swagger公开为JSON端点
```csharp
app.UseSwagger();
```
_此时您可以启动应用程序并在“ /swagger/v1/swagger.json”中查看生成的Swagger JSON。_
5. 可选的如果您想公开交互式文档请插入swagger-ui中间件并指定Swagger JSON端点作为提供器。
```csharp
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
```
_现在您可以重新启动应用程序并在“ / swagger”处签出自动生成的交互式文档。_
# System.Text.Json (STJ) vs Newtonsoft #
5.0.0以前的版Swashbuckle基于Newtonsoft序列化器来生成Schema(由API公开的数据类型的描述),那是因为当时的ASP.NET程序以Newtonsoft为默认的序列化器。但是从开始ASP.NET Core 3.0.0版本开始ASP.NET Core开箱即用地引入了新的默认的序列化程序System.Text.JsonSTJ并且如果您想继续使用Newtonsoft则需要安装一个单独的程序包并明确选择加入。 从Swashbuckle `5.0.0` 开始使用与asp.net core相同的策略. 也就是说开箱即用的Swashbuckle会假设您正在使用STJ序列化器并根据其行为生成Schema。如果您使用的是Newtonsoft那么您需要安装一个单独的Swashbuckle软件包并明确选择加入。 **无论您使用的是哪个版本的ASP.NET Core这都是必需的步骤**.
综上所述
如果您使用的是System.Text.JsonSTJ那么上述设置就足够了并且Swagger生成器将自动接受STJ选项/属性。
如果您使用的是Newtonsoft那么您需要安装一个单独的软件包并明确选择加入以确保Swagger生成器自动遵守Newtonsoft的**设置/属性**:
```
Package Manager : Install-Package Swashbuckle.AspNetCore.Newtonsoft -Version 5.6.2
CLI : dotnet add package --version 5.6.2 Swashbuckle.AspNetCore.Newtonsoft
```
```csharp
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和Routing #
Swashbuckle高度依赖ApiExplorerASP.NET Core附带的API元数据层。如果您使用AddMvc帮助程序来引导MVC堆栈则ApiExplorer将自动注册并且SB可以正常工作。但是如果AddMvcCore用于更配对的MVC堆栈则需要显式添加ApiExplorer服务
```csharp
services.AddMvcCore()
.AddApiExplorer();
```
此外,如果您使用 _[常规路由](https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing#conventional-routing)_ 而不是属性路由则任何控制器以及使用常规路由的那些控制器上的操作都不会在ApiExplorer中表示这意味着Swashbuckle将无法找到那些控制器并生成Swagger他们的操作。例如
```csharp
app.UseMvc(routes =>
{
// SwaggerGen won't find controllers that are routed via this technique.
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
```
**必须** 对要在Swagger文档中表示的任何控制器使用属性路由:
```csharp
[Route("example")]
public class ExampleController : Controller
{
[HttpGet("")]
public IActionResult DoStuff() { /**/ }
}
```
有关更多信息,请参考 [路由文档](https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing) .
# 组件 #
Swashbuckle由多个组件组成可根据您的需要一起使用或单独使用。它的核心是Swagger生成器将其作为JSON端点公开的中间件以及 [swagger-ui](https://github.com/swagger-api/swagger-ui)的打包版本。这3个软件包可以与Swashbuckle.AspNetCore“元软件包”一起安装并且可以无缝地协同工作请参阅[入门](#getting-started)以提供从代码自动生成的精美API文档。
此外,还有附加软件包 ( CLI tools, [备用UI](https://github.com/Rebilly/ReDoc)),您可以根据需要选择安装和配置。
## “核心”软件包即通过Swashbuckle.AspNetCore安装
|Package|Description|
|---------|-----------|
|Swashbuckle.AspNetCore.Swagger|公开Swagger JSON端点。它期望将实现的`ISwaggerProvider`实现注册到DI容器中并对其进行查询以进行检索`OpenAPIDocument(s)`然后将其公开为序列化JSON。|
|Swashbuckle.AspNetCore.SwaggerGen|注入`ISwaggerProvider`上述组件可以使用的实现。此特定的实现OpenApiDocument(s)从您的路由,控制器和模型生成。|
|Swashbuckle.AspNetCore.SwaggerUI|公开`swagger-ui`的嵌入式版本。您指定可以获取Swagger JSON的API端点并使用它们来为您的API提供交互式文档|
## 附加包 ##
|Package|Description|
|---------|-----------|
|Swashbuckle.AspNetCore.Annotations|包括一组可应用于控制器动作和模型的自定义属性以丰富所生成的Swagger|
|Swashbuckle.AspNetCore.Cli|提供一个命令行界面用于直接从启动程序集检索Swagger并将其写入文件|
|Swashbuckle.AspNetCore.ReDoc|公开ReDoc UI的嵌入式版本swagger-ui的替代方案|
## 社区包 ##
These packages are provided by the open-source community.
|Package|Description|
|---------|-----------|
|[Swashbuckle.AspNetCore.Filters](https://github.com/mattfrear/Swashbuckle.AspNetCore.Filters)| 一些有用的Swashbuckle过滤器可添加其他文档例如请求和响应示例文件上传按钮等。|
|[Unchase.Swashbuckle.AspNetCore.Extensions](https://github.com/unchase/Unchase.Swashbuckle.AspNetCore.Extensions)| 一些有用的扩展过滤器这些扩展添加了其他文档例如隐藏不可接受角色的PathItems修复用于生成客户端代码的枚举等。|
|[MicroElements.Swashbuckle.FluentValidation](https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation)|使用FluentValidation规则而不是ComponentModel属性来增强生成的Swagger模式|
# 配置和定制 #
上述步骤将以最少的设置启动并运行。但是Swashbuckle提供了很多灵活性可以根据需要进行自定义。请查看下表以获取完整的选项列表
* [Swashbuckle.AspNetCore.Swagger](#swashbuckleaspnetcoreswagger)
* [更改Swagger JSON端点的路径](#change-the-path-for-swagger-json-endpoints)
* [使用请求上下文修改Swagger](#modify-swagger-with-request-context)
* [以2.0格式序列化Swagger JSON](#serialize-swagger-in-the-20-format)
* [Swashbuckle.AspNetCore.SwaggerGen](#swashbuckleaspnetcoreswaggergen)
* [分配明确的操作ID](#assign-explicit-operationids)
* [列出操作响应](#list-operation-responses)
* [标记必需的参数和架构属性](#flag-required-parameters-and-schema-properties)
* [包括XML注释中的描述](#include-descriptions-from-xml-comments)
* [提供全局API元数据](#provide-global-api-metadata)
* [生成多个Swagger文档](#generate-multiple-swagger-documents)
* [省略过时的操作和/或架构属性](#omit-obsolete-operations-andor-schema-properties)
* [省略任意操作](#omit-arbitrary-operations)
* [自定义操作标签例如用于UI分组](#customize-operation-tags-eg-for-ui-grouping)
* [更改操作排序顺序例如用于UI排序](#change-operation-sort-order-eg-for-ui-sorting)
* [自定义架构ID](#customize-schema-ids)
* [特定类型的替代架构](#override-schema-for-specific-types)
* [使用操作,模式和文档过滤器扩展生成器](#extend-generator-with-operation-schema--document-filters)
* [添加安全定义和要求](#add-security-definitions-and-requirements)
* [继承与多态](#inheritance-and-polymorphism)
* [Swashbuckle.AspNetCore.SwaggerUI](#swashbuckleaspnetcoreswaggerui)
* [更改用户界面的相对路径](#change-relative-path-to-the-ui)
* [变更文件标题](#change-document-title)
* [列出多个Swagger文档](#list-multiple-swagger-documents)
* [应用swagger-ui参数](#apply-swagger-ui-parameters)
* [注入自定义CSS](#inject-custom-css)
* [自定义index.html](#customize-indexhtml)
* [启用OAuth2.0流程](#enable-oauth20-flows)
* [Swashbuckle.AspNetCore.Annotations](#swashbuckleaspnetcoreannotations)
* [安装并启用注释](#install-and-enable-annotations)
* [丰富操作元数据](#enrich-operation-metadata)
* [丰富响应元数据](#enrich-response-metadata)
* [丰富参数元数据](#enrich-parameter-metadata)
* [丰富RequestBody元数据](#enrich-requestbody-metadata)
* [丰富架构元数据](#enrich-schema-metadata)
* [将架构过滤器应用于特定类型](#apply-schema-filters-to-specific-types)
* [添加标签元数据](#add-tag-metadata)
* [Swashbuckle.AspNetCore.Cli](#swashbuckleaspnetcorecli)
* [直接从启动程序集检索Swagger](#retrieve-swagger-directly-from-a-startup-assembly)
* [将CLI工具与自定义主机配置一起使用](#use-the-cli-tool-with-a-custom-host-configuration)
* [Swashbuckle.AspNetCore.ReDoc](#swashbuckleaspnetcoreredoc)
* [更改用户界面的相对路径](#redoc-change-relative-path-to-the-ui)
* [变更文件标题](#redoc-change-document-title)
* [应用ReDoc参数](#apply-redoc-parameters)
* [注入自定义CSS](#redoc-inject-custom-css)
* [自定义index.html](#redoc-customize-indexhtml)
## Swashbuckle.AspNetCore.Swagger ##
### 更改Swagger JSON端点的路径 ###
默认情况下,Swagger JSON将在以下路径公开 -- "/swagger//swagger.json"。
如有必要,您可以在启用 Swagger 中间件时更改此路径;自定义路由必须包含参数`{documentName}`
```csharp
app.UseSwagger(c =>
{
c.RouteTemplate = "api-docs/{documentName}/swagger.json";
})
```
_注意如果您使用 SwaggerUI 中间件则还需要更新其配置以反映新的终结点_
```csharp
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/api-docs/v1/swagger.json", "My API V1");
})
```
### 使用请求上下文修改 Swagger ###
如果你需要根据当前请求设置某些Swagger元数据, 可以设置在序列化文档之前执行的筛选器.
```csharp
app.UseSwagger(c =>
{
//配置筛选器
c.PreSerializeFilters.Add((swagger, httpReq) =>
{
swagger.Servers = new List<OpenApiServer> { new OpenApiServer { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}" } };
});
});
```
`OpenApiDocument` 和 当前的`HttpRequest` 都会传递给筛选器. 这提供了很大的灵活性,比如:您可以基于"Host"标头(如下所示)添加显式 API 服务器也可以检查Session信息或Authorization标头并基于用户权限从文档中删除操作。
### 以2.0格式序列化Swagger ###
默认情况下Swashbuckle 将在规范的 3.0 版本(正式称为 OpenAPI 规范)中生成和公开 Swagger JSON。但是为了支持向后兼容性您可以选择继续使用 2.0 格式使用以下选项公开它:
```csharp
app.UseSwagger(c =>
{
c.SerializeAsV2 = true;
});
```
## Swashbuckle.AspNetCore.SwaggerGen ##
### 显式指定操作标识OperationIds ###
在Swagger中, 可以分配 `operationId`。 此ID在所有的操作API中保持唯一. 工具和库(例如客户端生成器)可以使用 operationId 来唯一标识操作,因此,建议遵循常见的编程命名约定。
自动生成一个与这些需求相匹配的ID同时提供一个在客户端库中有意义的名称是一项非常重要的任务因此swashbuck默认情况下会忽略operationId。但是如果需要可以通过装饰各个路由或提供自定义策略来分配operationid。
__选项 1) 使用Name属性装饰路由__
```csharp
[HttpGet("{id}", Name = "GetProductById")]
public IActionResult Get(int id) // operationId = "GetProductById"
```
__选项 2) 提供自定义策略__
```csharp
// Startup.cs
services.AddSwaggerGen(c =>
{
...
// 使用方法名作为 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则此操作将用于为响应正文生成架构。例如
```csharp
[HttpPost("{id}")]
public Product GetById(int id)
```
将生成以下响应元数据:
```
responses: {
200: {
description: "Success",
content: {
"application/json": {
schema: {
$ref: "#/components/schemas/Product"
}
}
}
}
}
```
#### 显式响应 ####
如果需要指定不同的状态代码和(或)其他响应,或者您的操作返回 IActionResult 而不是响应DTO则可以使用附带的ProducesResponseTypeAttribute显式描述ASP.NET Core 响应。例如
```csharp
[HttpPost("{id}")]
[ProducesResponseType(typeof(Product), 200)]
[ProducesResponseType(typeof(IDictionary<string, string>), 400)]
[ProducesResponseType(500)]
public IActionResult GetById(int id)
```
将生成以下响应元数据:
```
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: {}
}
}
```
### 标记所需的参数和架构属性 ###
在Swagger文档中可以标记请求所需的参数和架构属性。如果一个参数顶层或基于属性被BindRequiredAttribute或RequiredAttribute修饰那么Swashbuckle将在生成的Swagger中自动将其标记为“required”参数:
```csharp
// 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。在这种情况下修饰的属性将被标记为主体描述中的必需属性:
```csharp
// 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; }
}
```
### 包括来自XML注释的说明 ###
为了用人性化的描述增强生成的文档,您可以用[Xml Comments](http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx)来注释控制器操作和模型并配置swashbuck以将这些注释合并到输出的Swagger JSON中:
1. 打开项目的"属性"对话框,单击"生成"选项卡,并确保选中"XML 文档文件"。这将在生成时生成包含所有 XML 注释的文件。
_此时未使用“ML注释”注释的任何类或方法都将触发生成警告。若要禁止显示此状态请在属性对话框中的"Suppress warnings"字段中输入警告代码"1591"_
**特别说明**:上面项目属性对话框中的设置,会有些关于路径的小问题,可以直接编辑项目设置文件`xxxx.csproj` 如下(详见[微软官网配置](https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-5.0&tabs=visual-studio#add-and-configure-swagger-middleware)
``` xml
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<!--XML注释配置 开始-->
<GenerateDocumentationFile>true</GenerateDocumentationFile><!--生成xml注释文件-->
<NoWarn>$(NoWarn);1591</NoWarn><!--忽略1591警告-->
<!--XML注释配置 结束-->
</PropertyGroup>
//其它配置
</Project>
```
2. 配置 Swashbuckle 以将文件上的 XML 注释合并到生成的 Swagger JSON 中:
```csharp
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);
}
```
可以综合使用其它方法,比如
```
public void ConfigureServices(IServiceCollection services)
{
//其它代码
// 配置SwaggerGen
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo{Version = "v1",Title = "ToDo API"});
//设置Swagger JSON和UI的注释路径
//写法1
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
//写法2
var basePath = PlatformServices.Default.Application.ApplicationBasePath;
var xmlFiles = Directory.GetFiles(basePath, "*.xml").ToList();
foreach (var item in xmlFiles)
{
//增加第二个参数True:包括控制器的注释不传或为false则只显示Action上的注释
c.IncludeXmlComments(item, true);
}
});
}
```
**特别注意**IncludeXmlComments(x)方法有重载IncludeXmlComments(x,y) 当第二个参数为true时刚包含控制器的注释否则只包括Action方法注释
3. 使用摘要、备注、参数和响应标记注释您的操作:
```csharp
/// <summary>
/// 按唯一id检索特定产品
/// </summary>
/// <remarks>太棒了!</remarks>
/// <param name="id" example="123">产品Id</param>
/// <response code="200">产品已创建</response>
/// <response code="400">产品缺少值或者值无效!</response>
/// <response code="500">哎呀!现在无法创建产品!</response>
[HttpGet("{id}")]
[ProducesResponseType(typeof(Product), 200)]
[ProducesResponseType(typeof(IDictionary<string, string>), 400)]
[ProducesResponseType(500)]
public Product GetById(int id)
```
4. 还可以使用摘要和示例标记对类型进行注释:
```csharp
//产品类
public class Product
{
/// <summary>
/// 产品名称
/// </summary>
/// <example>男子篮球鞋</example>
public string Name { get; set; }
/// <summary>
/// 剩余库存量
/// </summary>
/// <example>10</example>
public int AvailableStock { get; set; }
}
```
5. 重新编译、构建项目以更新XML注释文件并导航到 Swagger JSON 终结点。请注意如何将描述映射到相应的 Swagger 字段。
_说明您还可以通过用摘要标记注释API模型及其属性来提供Swagger模式描述。如果您有多个XML注释文件例如用于控制器和模型的单独库则可以多次调用IncludeXmlComments方法它们将全部合并到输出的Swagger JSON中._
### 提供全局API元数据 ###
除了Swashbuck为您生成的“PathItems”、“Operations”和“Responses”之外Swagger还支持全局元数据请参见https://swagger.io/specification/#oasObject). 例如您可以提供API的完整描述、服务条款甚至联系人和许可信息:
```csharp
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")
}
}
);
```
_提示: 使用智能感知查看哪些其他字段可用._
### 生成多Swagger文档 ###
通过上述设置生成器将在一个单独的Swagger文档中包含所有API操作。但是如果需要可以创建多个文档。
例如您可能希望API的每个版本都有一个单独的文档。为此首先在`Startup.cs`中定义多个Swagger文档:
```csharp
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"._
下一步您需要通知swashbuck要在每个文档中包含哪些操作。尽管可以自定义见下文但默认情况下生成器将使用`ApiDescription.GroupName`属性它是随附的ASP.NET Core内置元数据层的一部分来区分这一点。您可以通过装饰单个操作或应用应用程序范围的约定来设置此设置。
#### 装饰 Actions ####
若要在特定的Swagger文档中包含操作请使用“ApiExplorerSettingsAttribute”对其进行修饰并将“GroupName”设置为相应的文档名称区分大小写
```csharp
[HttpPost]
[ApiExplorerSettings(GroupName = "v2")]
public void Post([FromBody]Product product)
```
#### 按公约为文档分组 ####
要按约定分组而不是装饰每个Action方法可以应用自定义控制器或操作约定类。
例如,您可以将以下约定连接起来,根据控制器名称空间将操作分配给文档。
```csharp
// 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())
);
...
}
```
#### 自定义Action选择过程 ####
在为给定的Swagger文档选择操作时生成器将针对框架显示的每个“ApiDescription”调用一个“DocInclusionPredicate”。默认实现检查`ApiDescription.GroupName`如果值为null或等于请求的文档名则返回true。但是您也可以提供一个自定义的包含谓词。例如如果您使用基于属性的方法来实现API版本控制例如。Microsoft.AspNetCore.Mvc.Versioning则可以配置一个利用版本控制属性的自定义谓词
```csharp
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公开多个文档 ####
如果使用的是“SwaggerUI”中间件则需要指定要公开的任何其他Swagger端点。有关详细信息请参见[列出多个Swagger文档](#list-multiple-swagger-documents)。
### 忽略过时的操作和(或)架构属性 ###
[Swagger spec](http://swagger.io/specification/) 包含一个“deprecated”标志用于指示某个操作已弃用应避免使用。如果相应的操作用“ObsoleteAttribute”修饰则Swagger生成器将自动设置此标志。但是您可以将生成器配置为完全忽略过时的操作而不是设置标志
```csharp
services.AddSwaggerGen(c =>
{
...
c.IgnoreObsoleteActions();
};
```
在Swagger输出中也可以使用类似的方法从`Model`中省略过时的属性。也就是说,您可以用`ObsoleteAttribute`修饰模型属性并配置swashbuck以在生成JSON模式时忽略这些属性:
```csharp
services.AddSwaggerGen(c =>
{
...
c.IgnoreObsoleteProperties();
};
```
### 忽略任意操作 ###
您可以通过装饰单个操作或应用应用程序范围 `convention`来从 Swagger 输出中忽略操作。
#### 单独装饰 Action ####
若要忽略某个特定的接口(控制器方法),请使用`ApiExplorerSettingsAttribute` 对其进行修饰,并设置`IgnoreApi`标志:
```csharp
[HttpGet("{id}")]
[ApiExplorerSettings(IgnoreApi = true)]
public Product GetById(int id)
```
#### 按约定器`Convention`忽略Action ####
要按约定省略操作而不是单独装饰它们可以应用自定义操作约定。例如可以将以下约定连接到仅document GET操作
```csharp
// 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())
);
...
}
```
### 自定义操作标签(如自定义用户界面) ###
[Swagger 规范](http://swagger.io/specification/) 允许将一个或多个`tags`分配给操作。Swagger生成器将指定控制器名称作为默认标记。如果使用的是`SwaggerUI`中间件,这一点很重要,因为它使用这个值来分组操作。
您可以通过提供按约定应用标记的函数来重写默认标记。例如以下配置将通过HTTP方法标记UI中的操作从而对操作进行分组
```csharp
services.AddSwaggerGen(c =>
{
...
c.TagActionsBy(api => api.HttpMethod);
};
```
### 更改操作排序顺序(例如 UI 排序) ###
默认情况下,动作在被分组到[Swagger 规范](http://swagger.io/specification)的以路径为中心的嵌套结构之前按指定的标记(见上文)排序. 但是,您可以使用自定义排序策略更改操作的默认顺序
```csharp
services.AddSwaggerGen(c =>
{
...
c.OrderActionsBy((apiDesc) => $"{apiDesc.ActionDescriptor.RouteValues["controller"]}_{apiDesc.HttpMethod}");
};
```
_注意: 这规定了在将操作分组并转换为Swagger格式之前的排序顺序。因此它会影响组的顺序Swagger“PathItems”以及组内操作的顺序在Swagger输出中。_
### 自定义 Schema Id's ###
如果生成器遇到复杂的参数或响应类型它将生成相应的JSON架构并将其添加到全局“组件/架构”字典中并通过唯一Id从操作描述中引用它。例如如果您有一个返回`Product`类型的操作,则生成的架构将被引用如下:
```
responses: {
200: {
description: "Success",
content: {
"application/json": {
schema: {
$ref: "#/components/schemas/Product"
}
}
}
}
}
```
但是,如果它遇到多个名称空间(例如`RequestModels.Product` & `ResponseModels.Product`)那么swashbuck将由于“冲突的schemaIds”而引发异常。在这种情况下您需要提供一个定制的Id策略来进一步限定名称
```csharp
services.AddSwaggerGen(c =>
{
...
c.CustomSchemaIds((type) => type.FullName);
};
```
### 覆盖特定类型的架构 ###
开箱即用Swashbulk在生成准确描述请求和响应负载的JSON模式方面做得很好。但是如果要为API中的某些类型自定义序列化行为则可能需要帮助。
例如您可能有一个具有多个属性的类您希望在JSON中将这些属性表示为逗号分隔的字符串。为此您可能需要实现一个自定义的`JsonConverter`。在这种情况下Swashbuck不知道转换器是如何实现的因此您需要为它提供一个能够准确描述类型的模式
例如您可能有一个具有多个属性的类您希望在JSON中将这些属性表示为逗号分隔的字符串。为此您可能需要实现一个自定义的`JsonConverter`。在这种情况下Swashbuck不知道转换器是如何实现的因此您需要为它提供一个能够准确描述类型的模式
```csharp
// 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" });
};
```
### 使用Operation、Schema和Document筛选器扩展生成器 ###
Swashbuckle 公开一个筛选器管道,该管道连接到生成过程。生成后,单个元数据对象将传递到管道中,并可进一步修改它们。您可以连接自定义筛选器以丰富生成的`Operations` `Schemas``Documents`.
#### Operation 筛选器 ####
Swashbuckle为每个`Operation`检索一个 `ApiDescription`ASP.NET Core的一部分并使用它生成相应的`OpenApiOperation`,一旦生成,它会将`OpenApiOperation`和`ApiDescription`传递给配置的操作筛选器列表。
在一个典型的过滤器实现中,您需要检查`ApiDescription`中的相关信息(例如路由信息、操作属性等),然后相应地更新`OpenApiOperation`。例如,下面的过滤器列出了用`AuthorizeAttribute`修饰的所有操作的附加"401"响应:
```csharp
// 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框架中那么当过滤器被实例化时它们将被自动注入_
#### Schema 筛选器 ####
Swashbuckle会为`controller` `actions`公开的每个`parameter` `response` `property` `Type` 生成Swagger风格的[JSONSchema](http://swagger.io/specification/#schemaObject)。生成后,它将在已配置的架构过滤器列表中传递架构和类型。
下面的示例下面的示例添加了一个AutoRest供应商扩展([参阅](https://github.com/Azure/autorest/blob/master/docs/extensions/readme.md#x-ms-enum))以通知AutoRest工具在生成API客户端时应该如何对枚举进行建模。
```csharp
// 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>();
};
```
#### Document 筛选器 ####
一旦生成了`OpenApiDocument`它也可以通过一组预先配置的文档过滤器进行传递。这样您就可以完全控制自己修改文档的方式。为了确保仍然返回有效的Swagger JSON在使用此过滤器类型之前您应该通读[specification](http://swagger.io/specification/)。
下面的示例提供了分配给文档中操作的任何标记的说明:
```csharp
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规范中的安全需求对象](https://swagger.io/specification/#securityRequirementObject).
在swashbuck中可以通过调用`AddSecurityDefinition`方法来定义方案,提供`OpenApiSecurityScheme`的名称和实例。例如,您可以定义[OAuth 2.0-隐式流](https://oauth.net/2/)具体如下:
```csharp
// 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"以外类型的方案时作用域数组必须为空。_
```csharp
c.AddSwaggerGen(c =>
{
...
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
},
new[] { "readAccess", "writeAccess" }
}
});
})
```
如果您有仅适用于某些操作的方案,则可以通过操作筛选器应用这些方案。例如,以下筛选器根据`AuthorizeAttribute`的存在添加OAuth2要求
```csharp
// 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流](#enable-oauth20-flows) _
### 继承与多态 ###
Swagger / OpenAPI定义了 `allOf` 和`oneOf` 关键字来描述[继承和多态性](https://swagger.io/docs/specification/data-models/inheritation-and-polymorphic/)模式定义中的关系。
例如,如果要为共享公共属性的模型使用基类,可以使用`allOf`关键字来描述继承层次结构。或者,如果序列化程序支持多态序列化/反序列化,则可以使用`oneOf`关键字为不同子类型的请求/响应记录所有"可能"的架构。
#### 启用继承 ####
默认情况下Swashbulk会展平继承层次结构。也就是说对于派生模型继承的属性将与声明的属性一起组合并列出。这会在生成的 Swagger 中造成大量重复,特别是当有多个子类型时。
如果您使用的是客户机生成器例如NSwag并且希望在生成的客户机模型中维护继承层次结构那么也会有问题。
要解决此问题,可以应用`UseAllOfForInheritance`设置,这将利用`allOf`关键字将继承的属性通过引用合并到生成的Swagger中
```
Circle: {
type: "object",
allOf: [
{
$ref: "#/components/schemas/Shape"
}
],
properties: {
radius: {
type: "integer",
format: "int32",
}
},
},
Shape: {
type: "object",
properties: {
name: {
type: "string",
nullable: true,
}
},
}
```
#### 启用多态性 ####
如果序列化程序支持多态序列化/反序列化,并且希望列出接受/返回抽象基类型的操作的可能子类型,则可以应用 `UseOneOfForPolymorphism`设置。因此,生成的请求/响应模式将引用`可能`模式的集合,而不仅仅是基类模式:
```
requestBody: {
content: {
application/json: {
schema: {
oneOf: [
{
$ref: "#/components/schemas/Rectangle"
},
{
$ref: "#/components/schemas/Circle"
},
],
}
}
}
```
#### 检测子类型 ####
由于继承和多态关系通常会变得非常复杂,不仅在您自己的模型中,而且在.NET类库中Swashbuck对它在生成的swagrager中公开哪些层次结构是有选择的。默认情况下它将拾取与给定基类型在同一程序集中定义的任何子类型。如果要重写此行为可以提供自定义选择器函数
```csharp
services.AddSwaggerGen(c =>
{
...
c.UseAllOfForInheritance();
c.SelectSubTypesUsing(baseType =>
{
return typeof(Startup).Assembly.GetTypes().Where(type => type.IsSubclassOf(baseType));
})
});
```
_注意如果您使用的是[Swashbuckle Annotations library](#swashbuckleaspnetcoreannotations),它包含一个自定义选择器,该选择器基于基类定义上是否存在`SwaggerSubType`属性。
这样,就可以使用简单的属性来显式地列出要公开的继承和/或多态关系。要启用此行为,请查看[Annotations docs](#list-known-subtypes-for-inheritance-and-polymorphism)。_
#### 描述鉴别器 ####
Swagger / OpenAPI与 `oneOf`关键字一起,还支持多态模式定义上的`discriminator` 字段。此关键字指向标识由给定负载表示的特定类型的属性。除了属性名,鉴别器描述还可以包括一个`mapping`,它将鉴别器值映射到特定的模式定义。
例如Newtonsoft 序列化程序通过在JSON实例上发出/接受 `$type` 属性来支持多态序列化/反序列化。此属性的值将为[程序集限定类型名](https://docs.microsoft.com/en-us/dotnet/api/system.type.assemblyqualifiednameview=netcore-3.1)由给定的JSON实例表示的类型。因此为了在Swagger中显式地描述这种行为相应的请求/响应模式可以定义如下:
```
schema: {
oneOf: [
{
$ref: "#/components/schemas/Rectangle"
},
{
$ref: "#/components/schemas/Circle"
},
],
discriminator: {
propertyName: "$type",
mapping: {
"MyApp.Models.Rectangle, MyApp": "#/components/schemas/Rectangle",
"MyApp.Models.Circle, MyApp": "#/components/schemas/Circle",
}
}
}
```
如果启用了`UseOneOfForPolymorphism`,并且序列化程序支持(并且已经启用)发出/接受鉴别器属性那么swashbuck将自动在多态架构定义上生成相应的`discriminator` 元数据。
或者,如果已自定义序列化程序以支持多态序列化/反序列化,则可以提供一些自定义选择器函数来确定鉴别器名称和相应的映射:
```csharp
services.AddSwaggerGen(c =>
{
...
c.UseOneOfForPolymorphism();
c.SelectDiscriminatorNameUsing((baseType) => "TypeName");
c.SelectDiscriminatorValueUsing((subType) => subType.Name);
});
```
_注意如果您使用的是[Swashbuckle Annotations library](#swashbuckleaspnetcoreannotations),它包含基于基类定义上 `SwaggerDiscriminator` 和 `SwaggerSubType` 属性的自定义选择器函数。这样,就可以使用简单的属性显式地提供鉴别器元数据。要启用此行为,请查看[Annotations docs](#enrich-polymorphic-base-classes-with-discriminator-metadata)_
## Swashbuckle.AspNetCore.SwaggerUI ##
### 更改 UI 的相对路径 ###
默认情况下,Swagger UI 将暴露在"/swagger"处。如有必要,可以在启用`SwaggerUI`中间件时更改此设置:
```csharp
app.UseSwaggerUI(c =>
{
c.RoutePrefix = "api-docs"
...
}
```
### 更改文档标题 ###
默认情况下,`Swagger UI`将具有通用文档标题。当您打开多个Swagger页面时,可能很难区分它们。您可以在启用`SwaggerUI`中间件时更改此设置:
```csharp
app.UseSwaggerUI(c =>
{
c.DocumentTitle = "My Swagger UI";
...
}
```
### 列出多个 Swagger 文档 ###
在启用中间件时,您需要指定一个或多个 Swagger 端点(绝对或相对于UI页面)来支持 UI。如果您提供多个端点它们将被列在页面的右上角允许用户在不同的文档之间切换。
例如,下面的配置可用于记录 API 的不同版本:
```csharp
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1 Docs");
c.SwaggerEndpoint("/swagger/v2/swagger.json", "V2 Docs");
}
```
### 应用 swagger-ui 参数 ###
`Swagger-ui` 附带了它自己的一套配置参数,这些参数都在[此处](https://github.com/swagger-api/swagger-ui/blob/v3.8.1/docs/usage/configuration.md#display)描述。
在 Swashbuckle中大多数的参数配置都是通过 `Swagger-UI` 中间件的特定选项暴露出来的:
```csharp
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);
});
```
_NOTE: The `InjectOnCompleteJavaScript` and `InjectOnFailureJavaScript` options have been removed because the latest version of swagger-ui doesn't expose the neccessary hooks. Instead, it provides a [flexible customization system](https://github.com/swagger-api/swagger-ui/blob/master/docs/customization/overview.md) 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](#customize-indexhtml)._
The [custom index sample app](test/WebSites/CustomUIIndex/Swagger/index.html) 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 `wwwroot` folder and specifying the relative paths in the middleware options:
```csharp
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:
```csharp
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](src/Swashbuckle.AspNetCore.SwaggerUI/index.html)_
### 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](#add-security-definitions-and-requirements) for an example of adding OAuth2.0 metadata to the generated Swagger.
If you're 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 https://github.com/swagger-api/swagger-ui/blob/v3.10.0/docs/usage/oauth2.md for more info:
```csharp
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();
});
```
## Swashbuckle.AspNetCore.Annotations ##
### Install and Enable Annotations ###
1. Install the following Nuget package into your ASP.NET Core application.
```
Package Manager : Install-Package Swashbuckle.AspNetCore.Annotations
CLI : dotnet add package Swashbuckle.AspNetCore.Annotations
```
2. In the `ConfigureServices` method of `Startup.cs`, enable annotations within in the Swagger config block:
```csharp
services.AddSwaggerGen(c =>
{
...
c.EnableAnnotations();
});
```
### Enrich Operation Metadata ###
Once annotations have been enabled, you can enrich the generated Operation metadata by decorating actions with a `SwaggerOperationAttribute`.
```csharp
[HttpPost]
[SwaggerOperation(
Summary = "Creates a new product",
Description = "Requires admin privileges",
OperationId = "CreateProduct",
Tags = new[] { "Purchase", "Products" }
)]
public IActionResult Create([FromBody]Product product)
```
### Enrich Response Metadata ###
ASP.NET Core provides the `ProducesResponseTypeAttribute` for listing the different responses that can be returned by an action. These attributes can be combined with XML comments, as described [above](#include-descriptions-from-xml-comments), to include human friendly descriptions with each response in the generated Swagger. If you'd prefer to do all of this with a single attribute, and avoid the use of XML comments, you can use `SwaggerResponseAttribute`s instead:
```csharp
[HttpPost]
[SwaggerResponse(201, "The product was created", typeof(Product))]
[SwaggerResponse(400, "The product data is invalid")]
public IActionResult Create([FromBody]Product product)
```
### Enrich Parameter Metadata ###
You can annotate "path", "query" or "header" bound parameters or properties (i.e. decorated with `[FromRoute]`, `[FromQuery]` or `[FromHeader]`) with a `SwaggerParameterAttribute` to enrich the corresponding `Parameter` metadata that's generated by Swashbuckle:
```csharp
[HttpGet]
public IActionResult GetProducts(
[FromQuery, SwaggerParameter("Search keywords", Required = true)]string keywords)
```
### Enrich RequestBody Metadata ###
You can annotate "body" bound parameters or properties (i.e. decorated with `[FromBody]`) with a `SwaggerRequestBodyAttribute` to enrich the corresponding `RequestBody` metadata that's generated by Swashbuckle:
```csharp
[HttpPost]
public IActionResult CreateProduct(
[FromBody, SwaggerRequestBody("The product payload", Required = true)]Product product)
```
### Enrich Schema Metadata ###
You can annotate classes or properties with a `SwaggerSchemaAttribute` to enrich the corresponding `Schema` metadata that's generated by Swashbuckle:
```csharp
[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; }
}
```
_NOTE: In Swagger / OpenAPI, serialized objects AND contained properties are represented as `Schema` instances, hence why this annotation can be applied to both classes and properties. Also worth noting, "required" properties are specified as an array of property names on the top-level schema as opposed to a flag on each individual property._
### Apply Schema Filters to Specific Types ###
The `SwaggerGen` package provides several extension points, including Schema Filters ([described here](#extend-generator-with-operation-schema--document-filter)) for customizing ALL generated Schemas. However, there may be cases where it's preferable to apply a filter to a specific Schema. For example, if you'd like to include an example for a specific type in your API. This can be done by decorating the type with a `SwaggerSchemaFilterAttribute`:
```csharp
// 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`:
```csharp
[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](#inheritance-and-polymorphism), 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:
```csharp
// 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 `SwaggerDiscriminatorAttribute` with the `SwaggerSubTypeAttribute` to provide additional metadata about the "discriminator" property, which will then be incorporated into the generated schema definition:
```csharp
// 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 `Rectangle` type and a value of "circle" if it represents a `Circle` type. This detail will be described in the generated schema definition as follows:
```
schema: {
oneOf: [
{
$ref: "#/components/schemas/Rectangle"
},
{
$ref: "#/components/schemas/Circle"
},
],
discriminator: {
propertyName: shapeType,
mapping: {
rectangle: "#/components/schemas/Rectangle",
circle: "#/components/schemas/Circle",
}
}
}
```
## Swashbuckle.AspNetCore.Cli ##
### Retrieve Swagger Directly from a Startup Assembly ###
Once your application has been setup with Swashbuckle (see [Getting Started](#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](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools) that can be installed and used via the dotnet SDK.
> :warning: The tool needs to load your Startup DLL and it's dependencies at runtime. Therefore, you should use a version of the `dotnet` SDK that is compatible with your application. For example, if your app targets `netcoreapp2.1`, then you should use version 2.1 of the SDK to run the CLI tool. If it targetes `netcoreapp3.0`, then you should use version 3.0 of the SDK and so on.
#### Using the tool with the .NET Core 2.1 SDK
1. Install as a [global tool](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools#install-a-global-tool)
```
dotnet tool install -g --version 5.6.2 Swashbuckle.AspNetCore.Cli
```
2. Verify that the tool was installed correctly
```
swagger tofile --help
```
3. Generate a Swagger/ OpenAPI document from your application's startup assembly
```
swagger tofile --output [output] [startupassembly] [swaggerdoc]
```
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:
```
dotnet new tool-manifest
```
2. Install as a [local tool](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools#install-a-local-tool)
```
dotnet tool install --version 5.6.2 Swashbuckle.AspNetCore.Cli
```
3. Verify that the tool was installed correctly
```
dotnet swagger tofile --help
```
4. Generate a Swagger / OpenAPI document from your application's startup assembly
```
dotnet swagger tofile --output [output] [startupassembly] [swaggerdoc]
```
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 `CreateHost` with return type `IHost`
- `public class SwaggerWebHostFactory`, containing a public static method called `CreateWebHost` with return type `IWebHost`
For example, the following class could be used to leverage the same host configuration as your application:
```csharp
public class SwaggerHostFactory
{
public static IHost CreateHost()
{
return Program.CreateHostBuilder(new string[0]).Build();
}
}
```
## Swashbuckle.AspNetCore.ReDoc ##
<h3 id="redoc-change-relative-path-to-the-ui">Change Relative Path to the UI</h3>
By default, the ReDoc UI will be exposed at "/api-docs". If necessary, you can alter this when enabling the ReDoc middleware:
```csharp
app.UseReDoc(c =>
{
c.RoutePrefix = "docs"
...
}
```
<h3 id="redoc-change-document-title">Change Document Title</h3>
By default, the ReDoc UI will have a generic document title. You can alter this when enabling the ReDoc middleware:
```csharp
app.UseReDoc(c =>
{
c.DocumentTitle = "My API Docs";
...
}
```
### Apply ReDoc Parameters ###
ReDoc ships with it's own set of configuration parameters, all described here https://github.com/Rebilly/ReDoc/blob/master/README.md#redoc-options-object. In Swashbuckle, most of these are surfaced through the ReDoc middleware options:
```csharp
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();
});
```
_Using `c.SpecUrl("/v1/swagger.json")` multiple times within the same `UseReDoc(...)` will not add multiple urls._
<h3 id="redoc-inject-custom-css">Inject Custom CSS</h3>
To tweak the look and feel, you can inject additional CSS stylesheets by adding them to your `wwwroot` folder and specifying the relative paths in the middleware options:
```csharp
app.UseReDoc(c =>
{
...
c.InjectStylesheet("/redoc/custom.css");
}
```
It is also possible to modify the theme by using the `AdditionalItems` property, see https://github.com/Rebilly/ReDoc/blob/master/README.md#redoc-options-object for more information.
```csharp
app.UseReDoc(c =>
{
...
c.ConfigObject.AdditionalItems = ...
}
```
<h3 id="redoc-customize-indexhtml">Customize index.html</h3>
To customize the UI beyond the basic options listed above, you can provide your own version of the ReDoc index.html page:
```csharp
app.UseReDoc(c =>
{
c.IndexStream = () => GetType().Assembly
.GetManifestResourceStream("CustomIndex.ReDoc.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](src/Swashbuckle.AspNetCore.ReDoc/index.html)_