关于 Swashbuckle.AspNetCore3.0

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

项目主页:https://github.com/domaindrivendev/Swashbuckle.AspNetCore

项目官方示例:https://github.com/domaindrivendev/Swashbuckle.AspNetCore/tree/master/test/WebSites

之前写过一篇Swashbuckle.AspNetCore-v1.10 的使用,现在 Swashbuckle.AspNetCore 已经升级到 3.0 了,正好开新坑(博客重构)重新封装了下,将所有相关的一些东西抽取到单独的类库中,尽可能的避免和项目耦合,使其能够在其他项目也能够快速使用。

运行示例

封装代码

待博客重构完成再将完整代码开源,参考下面步骤可自行封装

1. 新建类库并添加引用

我引用的版本如下

    <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />

2. 构建参数模型 CustsomSwaggerOptions.cs

    public class CustsomSwaggerOptions
{
/// <summary>
/// 项目名称
/// </summary>
public string ProjectName { get; set; } = "My API";
/// <summary>
/// 接口文档显示版本
/// </summary>
public string[] ApiVersions { get; set; }
/// <summary>
/// 接口文档访问路由前缀
/// </summary>
public string RoutePrefix { get; set; } = "swagger";
/// <summary>
/// 使用自定义首页
/// </summary>
public bool UseCustomIndex { get; set; }
/// <summary>
/// UseSwagger Hook
/// </summary>
public Action<SwaggerOptions> UseSwaggerAction { get; set; }
/// <summary>
/// UseSwaggerUI Hook
/// </summary>
public Action<SwaggerUIOptions> UseSwaggerUIAction { get; set; }
/// <summary>
/// AddSwaggerGen Hook
/// </summary>
public Action<SwaggerGenOptions> AddSwaggerGenAction { get; set; }
}

3. 版本控制默认参数接口实现 SwaggerDefaultValueFilter.cs

    public class SwaggerDefaultValueFilter : IOperationFilter
{
public void Apply(Swashbuckle.AspNetCore.Swagger.Operation operation, OperationFilterContext context)
{
// REF: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/412
// REF: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/413
foreach (var parameter in operation.Parameters.OfType<NonBodyParameter>())
{
var description = context.ApiDescription.ParameterDescriptions.FirstOrDefault(p => p.Name == parameter.Name);
if (description == null)
return;
if (parameter.Description == null)
{
parameter.Description = description.ModelMetadata.Description;
} if (description.RouteInfo != null)
{
parameter.Required |= !description.RouteInfo.IsOptional;
if (parameter.Default == null)
parameter.Default = description.RouteInfo.DefaultValue;
}
}
}

4. CustomSwaggerServiceCollectionExtensions.cs

    public static class CustomSwaggerServiceCollectionExtensions
{
public static IServiceCollection AddCustomSwagger(this IServiceCollection services)
{
return AddCustomSwagger(services, new CustsomSwaggerOptions());
} public static IServiceCollection AddCustomSwagger(this IServiceCollection services, CustsomSwaggerOptions options)
{
services.AddSwaggerGen(c =>
{
if (options.ApiVersions == null) return;
foreach (var version in options.ApiVersions)
{
c.SwaggerDoc(version, new Info { Title = options.ProjectName, Version = version });
}
c.OperationFilter<SwaggerDefaultValueFilter>();
options.AddSwaggerGenAction?.Invoke(c); });
return services;
}
}

5. SwaggerBuilderExtensions.cs

    public static class SwaggerBuilderExtensions
{
public static IApplicationBuilder UseCustomSwagger(this IApplicationBuilder app)
{
return UseCustomSwagger(app, new CustsomSwaggerOptions());
}
public static IApplicationBuilder UseCustomSwagger(this IApplicationBuilder app, CustsomSwaggerOptions options)
{
app.UseSwagger(opt =>
{
if (options.UseSwaggerAction == null) return;
options.UseSwaggerAction(opt);
});
app.UseSwaggerUI(c =>
{
if (options.ApiVersions == null) return;
c.RoutePrefix = options.RoutePrefix;
c.DocumentTitle = options.ProjectName;
if (options.UseCustomIndex)
{
c.UseCustomSwaggerIndex();
}
foreach (var item in options.ApiVersions)
{
c.SwaggerEndpoint($"/swagger/{item}/swagger.json", $"{item}");
}
options.UseSwaggerUIAction?.Invoke(c);
}); return app;
}
/// <summary>
/// 使用自定义首页
/// </summary>
/// <returns></returns>
public static void UseCustomSwaggerIndex(this SwaggerUIOptions c)
{
var currentAssembly = typeof(CustsomSwaggerOptions).GetTypeInfo().Assembly;
c.IndexStream = () => currentAssembly.GetManifestResourceStream($"{currentAssembly.GetName().Name}.index.html");
}
}

6. 模型初始化

    private CustsomSwaggerOptions CURRENT_SWAGGER_OPTIONS = new CustsomSwaggerOptions()
{
ProjectName = "墨玄涯博客接口",
ApiVersions = new string[] { "v1", "v2" },//要显示的版本
UseCustomIndex = true,
RoutePrefix = "swagger",
AddSwaggerGenAction = c =>
{
var filePath = System.IO.Path.Combine(System.AppContext.BaseDirectory, typeof(Program).GetTypeInfo().Assembly.GetName().Name + ".xml");
c.IncludeXmlComments(filePath, true);
},
UseSwaggerAction = c =>
{ },
UseSwaggerUIAction = c =>
{ }
};

7. 在 api 项目中使用

添加对新建类库的引用,并在 webapi 项目中启用版本管理需要为输出项目添加 Nuget 包:Microsoft.AspNetCore.Mvc.VersioningMicrosoft.AspNetCore.Mvc.Versioning.ApiExplorer (如果需要版本管理则添加)

我引用的版本如下

    <PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="2.2.0" />

Startup.cs 代码

    public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//版本控制
services.AddMvcCore().AddVersionedApiExplorer(o => o.GroupNameFormat = "'v'VVV");
services.AddApiVersioning(option =>
{
// allow a client to call you without specifying an api version
// since we haven't configured it otherwise, the assumed api version will be 1.0
option.AssumeDefaultVersionWhenUnspecified = true;
option.ReportApiVersions = false;
});
//custom swagger
services.AddCustomSwagger(CURRENT_SWAGGER_OPTIONS);
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApiVersionDescriptionProvider provider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//custom swagger
//自动检测存在的版本
// CURRENT_SWAGGER_OPTIONS.ApiVersions = provider.ApiVersionDescriptions.Select(s => s.GroupName).ToArray();
app.UseCustomSwagger(CURRENT_SWAGGER_OPTIONS);
app.UseMvc();
}

关键代码拆解

action 方法的 xml 注释

new CustsomSwaggerOptions(){
AddSwaggerGenAction = c =>
{
var filePath = System.IO.Path.Combine(System.AppContext.BaseDirectory, typeof(Program).GetTypeInfo().Assembly.GetName().Name + ".xml");
//controller及action注释
c.IncludeXmlComments(filePath, true);
}
}

当然还需要生成xml,编辑解决方案添加(或者在vs中项目属性->生成->勾选生成xml文档文件)如下配置片段

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile>.\项目名称.xml</DocumentationFile>
</PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>.\项目名称.xml</DocumentationFile>
</PropertyGroup>

目前.net core2.1我这会将此 xml 生成到项目目录,故可能需要将其加入.gitignore中。

版本控制

添加 Nuget 包:Microsoft.AspNetCore.Mvc.VersioningMicrosoft.AspNetCore.Mvc.Versioning.ApiExplorer

并在 ConfigureServices 中设置

    //版本控制
services.AddMvcCore().AddVersionedApiExplorer(o => o.GroupNameFormat = "'v'VVV");
services.AddApiVersioning(option =>
{
// allow a client to call you without specifying an api version
// since we haven't configured it otherwise, the assumed api version will be 1.0
option.AssumeDefaultVersionWhenUnspecified = true;
option.ReportApiVersions = false;
});

controller 使用

    /// <summary>
/// 测试接口
/// </summary>
[ApiVersion("1.0")]
[Route("api/v{api-version:apiVersion}/test")]
[ApiController]
public class TestController : ControllerBase
{
}

自定义主题

将 index.html 修改为内嵌资源就可以使用GetManifestResourceStream获取文件流,使用此 html,可以自己使用var configObject = JSON.parse('%(ConfigObject)');获取到 swagger 的配置信息,从而根据此信息去写自己的主题即可。

    /// <summary>
/// 使用自定义首页
/// </summary>
/// <returns></returns>
public static void UseCustomSwaggerIndex(this SwaggerUIOptions c)
{
var currentAssembly = typeof(CustsomSwaggerOptions).GetTypeInfo().Assembly;
c.IndexStream = () => currentAssembly.GetManifestResourceStream($"{currentAssembly.GetName().Name}.index.html");
}

若想注入 css,js 则在 UseSwaggerUIAction 委托中调用对应的方法接口,官方文档

另外,目前 swagger-ui 3.19.0 并不支持多语言,不过可以根据需要使用 js 去修改一些东西

比如在 index.html 的 onload 事件中这样去修改头部信息

document.getElementsByTagName(
'span'
)[0].innerText = document
.getElementsByTagName('span')[0]
.innerText.replace('swagger', '项目接口文档')
document.getElementsByTagName(
'span'
)[1].innerText = document
.getElementsByTagName('span')[1]
.innerText.replace('Select a spec', '版本选择')

在找汉化解决方案时追踪到 Swashbuckle.AspNetCore3.0 主题时使用的swagger-ui 为 3.19.0,从issues2488了解到目前不支持多语言,其他的问题也可以查看此仓库

在使用过程中遇到的问题,基本上 readme 和 issues 都有答案,遇到问题多多阅读即可

参考文章

Swashbuckle.AspNetCore3.0的二次封装与使用的更多相关文章

  1. 在asp.net core2.1中添加中间件以扩展Swashbuckle.AspNetCore3.0支持简单的文档访问权限控制

    Swashbuckle.AspNetCore3.0 介绍 一个使用 ASP.NET Core 构建的 API 的 Swagger 工具.直接从您的路由,控制器和模型生成漂亮的 API 文档,包括用于探 ...

  2. AFNetworking3.0+MBProgressHUD二次封装,一句话搞定网络提示

    对AFNetworking3.0+MBProgressHUD的二次封装,使用更方便,适用性非常强: 一句话搞定网络提示: 再也不用担心网络库更新后,工程要修改很多地方了!网络库更新了只需要更新这个封装 ...

  3. .Net Framework下对Dapper二次封装迁移到.Net Core2.0遇到的问题以及对Dapper的封装介绍

    今天成功把.Net Framework下使用Dapper进行封装的ORM成功迁移到.Net Core 2.0上,在迁移的过程中也遇到一些很有意思的问题,值得和大家分享一下.下面我会还原迁移的每一个过程 ...

  4. OkGo3.0 --真实项目使用和二次封装(转)

    转载:https://blog.csdn.net/jiushiwo12340/article/details/79011480  11.OkGo3.0真实项目使用和二次封装: ====  11.OkG ...

  5. 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传)

    前言 首先声明一下,我这个是对WebUploader开源上传控件的二次封装,底层还是WebUploader实现的,只是为了更简洁的使用他而已. 下面先介绍一下WebUploader 简介: WebUp ...

  6. Quick Cocos (2.2.5plus)CoinFlip解析(MenuScene display AdBar二次封装)

    转载自:http://cn.cocos2d-x.org/tutorial/show?id=1621 从Samples中找到CoinFlip文件夹,复制其中的 res 和 script 文件夹覆盖新建工 ...

  7. 对jquery的ajax进行二次封装以及ajax缓存代理组件:AjaxCache

    虽然jquery的较新的api已经很好用了, 但是在实际工作还是有做二次封装的必要,好处有:1,二次封装后的API更加简洁,更符合个人的使用习惯:2,可以对ajax操作做一些统一处理,比如追加随机数或 ...

  8. Android 应用程序集成Google 登录及二次封装

    谷歌登录API:  https://developers.google.com/identity/sign-in/android/ 1.注册并且登录google网站 https://accounts. ...

  9. AFNetworking二次封装的那些事

    AFNetworking可是iOS网络开发的神器,大大简便了操作.不过网络可是重中之重,不能只会用AFNetworking.我觉得网络开发首先要懂基本的理论,例如tcp/ip,http协议,之后要了解 ...

随机推荐

  1. 闪回工具flashback

    Ⅰ.背景 早先操作数据误操作后,我们一般通过全量备份+binlog的方式来实现恢复(前滚) 有时只想撤销一个几分钟前的操作,采用这种方式就会显得很笨重 大家都知道Oracle有个叫做flashback ...

  2. Get Docker CE for CentOS

    To get started with Docker CE on CentOS, make sure you meet the prerequisites, then install Docker. ...

  3. python 基础语法学习

    .注释 python单行注释以#开头 如:#!/usr/bin/env python3 #查找运行环境 多行注释有' ' '和" " " .python最具有特色的是使用 ...

  4. 1.2 lambda 表达式的语法

    1.2 lambda 表达式的语法 还以上一节中的排序为例.我们传递代码来检查某个字符串的长度是否小于另一个字符串的长度,如下所示: Integer.compare(first.length(), s ...

  5. BZOJ_1954_Pku3764 The xor-longest Path_Trie树

    Description 给定一棵n个点的带权树,求树上最长的异或和路径 把根到点路径上点权异或和求出来,然后变成了Trie树裸题.   代码: #include <cstdio> #inc ...

  6. Windows上安装配置SSH教程(7)——几种方式对比

    服务端:Windows XP 客户端:Windows 10 由于Cygwin也可以安装OpenSSH,所以客户端其实可以直接使用Cygwin安装OpenSSH,那么在Windows下使用SCP(安全拷 ...

  7. linux安装nvm node版本管理器 nvm常用命令 部署node服务器环境

    1,nvm git地址点击打开链接,安装命令 curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh ...

  8. Mybatis之旅第六篇-关联查询

    一.引言 通过动态SQL我们可以进行复杂SQL的编写,但之前的例子都是单表查询,在实际开发中,当然不可能都是单表,很多时候我们需要进行关联多表查询(有些公司为了性能还是尽量的使用单表查询),表与表之间 ...

  9. Android根据word模板文档将表单数据生成word文档的方案整理

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 尝试的方案包括以下几种: freemarker 只能在java项目上运行,无法在Android项目上运行: 参考资料:<Fre ...

  10. Python调用ansible API系列(五)综合使用

    如何把动态生成资产信息.执行playbook以及自定义结果结合起来用呢? #!/usr/bin/env python # -*- coding: utf-8 -*- """ ...