You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 KiB

警告: 如果您要在主要版本之间迁移,请特别注意。
* 从 4.x 升级到 5.x需要注意几个重大更改查看发行说明
* 先从3.x 升级到4.x,也有很多乌龙,查看 发行说明

Swashbuckle.AspNetCore

构建状态

Nuget

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

Swagger 2.0 and OpenAPI 3.0 之外, Swashbuckle还提供了由Swagger JSON驱动的超棒的嵌入式swagger-ui。

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

一旦有了可以在Swagger中描述自己的API就可以使用基于Swagger的工具库其中包括可以针对各种流行平台的客户端生成器。详细情况参见 swagger-codegen

兼容性

Swashbuckle Version ASP.NET Core Swagger / OpenAPI Spec. swagger-ui ReDoc UI
master >= 2.0.0 2.0, 3.0 3.32.5 2.0.0-rc.40
5.6.2 >= 2.0.0 2.0, 3.0 3.32.5 2.0.0-rc.40
4.0.0 >= 2.0.0, < 3.0.0 2.0 3.19.5 1.22.2
3.0.0 >= 1.0.4, < 3.0.0 2.0 3.17.1 1.20.0
2.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文档。

    using Microsoft.OpenApi.Models;
    
    services.AddMvc();
    
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    });
    
  3. 确保使用显式的"Http"特性和"From"绑定装饰您的API方法和参数。

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

    注意:如果您省略显式参数绑定,则默认情况下,生成器会将其描述为"query"参数。_

  4. 在该Configure方法中插入中间件以将生成的Swagger公开为JSON端点

    app.UseSwagger();
    

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

  5. 可选的如果您想公开交互式文档请插入swagger-ui中间件并指定Swagger JSON端点作为提供器。

    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
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服务

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个软件包可以与Swashbuckle.AspNetCore“元软件包”一起安装并且可以无缝地协同工作请参阅入门以提供从代码自动生成的精美API文档。

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

“核心”软件包即通过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 一些有用的Swashbuckle过滤器可添加其他文档例如请求和响应示例文件上传按钮等。
Unchase.Swashbuckle.AspNetCore.Extensions 一些有用的扩展过滤器这些扩展添加了其他文档例如隐藏不可接受角色的PathItems修复用于生成客户端代码的枚举等。
MicroElements.Swashbuckle.FluentValidation 使用FluentValidation规则而不是ComponentModel属性来增强生成的Swagger模式

配置和定制

上述步骤将以最少的设置启动并运行。但是Swashbuckle提供了很多灵活性可以根据需要进行自定义。请查看下表以获取完整的选项列表

Swashbuckle.AspNetCore.Swagger

更改Swagger JSON端点的路径

默认情况下,Swagger JSON将在以下路径公开 -- "/swagger//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");
})

使用请求上下文修改 Swagger

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

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 格式使用以下选项公开它:

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

Swashbuckle.AspNetCore.SwaggerGen

显式指定操作标识OperationIds

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

自动生成一个与这些需求相匹配的ID同时提供一个在客户端库中有意义的名称是一项非常重要的任务因此swashbuck默认情况下会忽略operationId。但是如果需要可以通过装饰各个路由或提供自定义策略来分配operationid。

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

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

选项 2) 提供自定义策略

// 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则此操作将用于为响应正文生成架构。例如

[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 响应。例如

[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”参数:

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

包括来自XML注释的说明

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

  1. 打开项目的"属性"对话框,单击"生成"选项卡,并确保选中"XML 文档文件"。这将在生成时生成包含所有 XML 注释的文件。

    此时未使用“ML注释”注释的任何类或方法都将触发生成警告。若要禁止显示此状态请在属性对话框中的"Suppress warnings"字段中输入警告代码"1591"

    特别说明:上面项目属性对话框中的设置,会有些关于路径的小问题,可以直接编辑项目设置文件xxxx.csproj 如下(详见微软官网配置

    <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 中:

    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. 使用摘要、备注、参数和响应标记注释您的操作:

    /// <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. 还可以使用摘要和示例标记对类型进行注释:

    //产品类    
    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的完整描述、服务条款甚至联系人和许可信息:

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文档:

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”设置为相应的文档名称区分大小写

[HttpPost]
[ApiExplorerSettings(GroupName = "v2")]
public void Post([FromBody]Product product)

按公约为文档分组

要按约定分组而不是装饰每个Action方法可以应用自定义控制器或操作约定类。 例如,您可以将以下约定连接起来,根据控制器名称空间将操作分配给文档。

// 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则可以配置一个利用版本控制属性的自定义谓词

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文档

忽略过时的操作和(或)架构属性

Swagger spec 包含一个“deprecated”标志用于指示某个操作已弃用应避免使用。如果相应的操作用“ObsoleteAttribute”修饰则Swagger生成器将自动设置此标志。但是您可以将生成器配置为完全忽略过时的操作而不是设置标志

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

在Swagger输出中也可以使用类似的方法从Model中省略过时的属性。也就是说,您可以用ObsoleteAttribute修饰模型属性并配置swashbuck以在生成JSON模式时忽略这些属性:

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

忽略任意操作

您可以通过装饰单个操作或应用应用程序范围 convention来从 Swagger 输出中忽略操作。

单独装饰 Action

若要忽略某个特定的接口(控制器方法),请使用ApiExplorerSettingsAttribute 对其进行修饰,并设置IgnoreApi标志:

[HttpGet("{id}")]
[ApiExplorerSettings(IgnoreApi = true)]
public Product GetById(int id)

按约定器Convention忽略Action

要按约定省略操作而不是单独装饰它们可以应用自定义操作约定。例如可以将以下约定连接到仅document 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())
    );

    ...
}

自定义操作标签(如自定义用户界面)

Swagger 规范 允许将一个或多个tags分配给操作。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“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策略来进一步限定名称

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

覆盖特定类型的架构

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

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

// 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 SchemasDocuments.

Operation 筛选器

Swashbuckle为每个Operation检索一个 ApiDescriptionASP.NET Core的一部分并使用它生成相应的OpenApiOperation,一旦生成,它会将OpenApiOperationApiDescription传递给配置的操作筛选器列表。

在一个典型的过滤器实现中,您需要检查ApiDescription中的相关信息(例如路由信息、操作属性等),然后相应地更新OpenApiOperation。例如,下面的过滤器列出了用AuthorizeAttribute修饰的所有操作的附加"401"响应:

// 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。生成后,它将在已配置的架构过滤器列表中传递架构和类型。 下面的示例下面的示例添加了一个AutoRest供应商扩展(参阅)以通知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>();
};

Document 筛选器

一旦生成了OpenApiDocument它也可以通过一组预先配置的文档过滤器进行传递。这样您就可以完全控制自己修改文档的方式。为了确保仍然返回有效的Swagger JSON在使用此过滤器类型之前您应该通读specification。 下面的示例提供了分配给文档中操作的任何标记的说明:

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规范中的安全需求对象. 在swashbuck中可以通过调用AddSecurityDefinition方法来定义方案,提供OpenApiSecurityScheme的名称和实例。例如,您可以定义OAuth 2.0-隐式流具体如下:

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

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

// 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流 _

继承与多态

Swagger / OpenAPI定义了 allOfoneOf 关键字来描述继承和多态性模式定义中的关系。 例如,如果要为共享公共属性的模型使用基类,可以使用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中公开哪些层次结构是有选择的。默认情况下它将拾取与给定基类型在同一程序集中定义的任何子类型。如果要重写此行为可以提供自定义选择器函数

services.AddSwaggerGen(c =>
{
    ...

    c.UseAllOfForInheritance();

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

注意:如果您使用的是Swashbuckle Annotations library,它包含一个自定义选择器,该选择器基于基类定义上是否存在SwaggerSubType属性。 这样,就可以使用简单的属性来显式地列出要公开的继承和/或多态关系。要启用此行为,请查看Annotations docs

描述鉴别器

Swagger / OpenAPI与 oneOf关键字一起,还支持多态模式定义上的discriminator 字段。此关键字指向标识由给定负载表示的特定类型的属性。除了属性名,鉴别器描述还可以包括一个mapping,它将鉴别器值映射到特定的模式定义。

例如Newtonsoft 序列化程序通过在JSON实例上发出/接受 $type 属性来支持多态序列化/反序列化。此属性的值将为程序集限定类型名由给定的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 元数据。

或者,如果已自定义序列化程序以支持多态序列化/反序列化,则可以提供一些自定义选择器函数来确定鉴别器名称和相应的映射:

services.AddSwaggerGen(c =>
{
    ...

    c.UseOneOfForPolymorphism();

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

注意:如果您使用的是Swashbuckle Annotations library,它包含基于基类定义上 SwaggerDiscriminatorSwaggerSubType 属性的自定义选择器函数。这样,就可以使用简单的属性显式地提供鉴别器元数据。要启用此行为,请查看Annotations docs

Swashbuckle.AspNetCore.SwaggerUI

更改 UI 的相对路径

默认情况下,Swagger UI 将暴露在"/swagger"处。如有必要,可以在启用SwaggerUI中间件时更改此设置:

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

更改文档标题

默认情况下,Swagger UI将具有通用文档标题。当您打开多个Swagger页面时,可能很难区分它们。您可以在启用SwaggerUI中间件时更改此设置:

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

列出多个 Swagger 文档

在启用中间件时,您需要指定一个或多个 Swagger 端点(绝对或相对于UI页面)来支持 UI。如果您提供多个端点它们将被列在页面的右上角允许用户在不同的文档之间切换。 例如,下面的配置可用于记录 API 的不同版本:

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

应用 swagger-ui 参数

Swagger-ui 附带了它自己的一套配置参数,这些参数都在此处描述。 在 Swashbuckle中大多数的参数配置都是通过 Swagger-UI 中间件的特定选项暴露出来的:

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 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 wwwroot folder and specifying the relative paths in the middleware options:

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 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:

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:

    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.

[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, 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 SwaggerResponseAttributes instead:

[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:

[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:

[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:

[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) 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:

// 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 SwaggerDiscriminatorAttribute with the SwaggerSubTypeAttribute to provide additional metadata about the "discriminator" property, which will then be incorporated into the generated schema definition:

// 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), 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 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

    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

    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:

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 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:

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.

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:

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.

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

Customize index.html

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

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