.NetCore使用Swagger+API多版本控制
本文实例环境及版本.NetCore3.1、Swagger6.1
现在的开发大部分都是前后端分离的模式了,后端提供接口,前端调用接口。后端提供了接口,需要对接口进行测试,之前都是使用浏览器开发者工具,或者写单元测试,再或者直接使用Postman,但是现在这些都已经out了。后端提供了接口,如何跟前端配合说明接口的性质,参数等这也是一个问题。有没有一种工具可以根据后端的接口自动生成接口文档,说明接口的性质,参数等信息,又能提供接口调用等相关功能呢?答案是有的。Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。而作为.net core开发,Swashbuckle是swagger应用的首选!
总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法、参数和模型紧密集成到服务器端的代码,允许 API 来始终保持同步。Swagger 让部署管理和使用功能强大的 API 从未如此简单。
Swashbuckle.AspNetCore源码地址:https://github.com/domaindrivendev/Swashbuckle.AspNetCore
整个swagger页面访问流程如下:
1、浏览器输入swaggerUI页面地址,比如:http://localhost:5000/swagger/index.html,这个地址是可配置的
2、请求被SwaggerUI中间件拦截,然后返回页面,这个页面是嵌入的资源文件,也可以设置成外部自己的页面文件(使用外部静态文件拦截)
3、页面接收到Swagger的Index页面后,会根据SwaggerUI中间件中使用SwaggerEndpoint方法设置的文档列表,加载第一个文档,也就是获取文档架构信息swagger.json
4、浏览器请求的swagger.json被Swagger中间件拦截,然后解析属于请求文档的所有接口,并最终返回一串json格式的数据
5、浏览器根据接收到的swagger,json数据呈现UI界面
一、Swagger基本使用
1、新建NetCore项目,添加相关Controller并添加引用Swashbuckle.AspNetCore.Swagger
2、在Startup中添加配置
在ConfigureServices中注入Swashbuckle服务
services.AddSwaggerGen(c => { c.SwaggerDoc("V1", new OpenApiInfo { //版本 Version = "V1", //标题 Title = $"接口文档-NetCore3.1", //描述 Description = $"NetCore Http API v1", //联系方式 Contact = new OpenApiContact { Name = "测试", Email = "", Url = new Uri("https://www.cnblogs.com/mzflog/") }, License = new OpenApiLicense { Name = "测试2", Url = new Uri("https://www.cnblogs.com/mzflog/") } }); // 加载XML注释 c.IncludeXmlComments(XmlCommentsFilePath); });
新增XmlCommentsFilePath 属性,此时需要引用 Microsoft.Extensions.PlatformAbstractions
/// <summary> /// 获取当前项目名的XML文件 /// </summary> static string XmlCommentsFilePath { get { var basePath = PlatformServices.Default.Application.ApplicationBasePath; var fileName = typeof(Startup).GetTypeInfo().Assembly.GetName().Name + ".xml"; return Path.Combine(basePath, fileName); } }
在Configure中添加Swagger中间件UseSwagger,UseSwaggerUI
UseSwagger:添加Swagger中间件,主要用于拦截swagger.json请求,从而可以获取返回所需的接口架构信息
UseSwaggerUI:添加SwaggerUI中间件,主要用于拦截swagger/index.html页面请求,返回页面给前端
app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint($"/swagger/V1/swagger.json", $"NetCore V1"); //c.RoutePrefix = string.Empty; //如果是为空 访问路径就为 根域名/index.html,注意localhost:8001/swagger是访问不到的 //路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件 c.RoutePrefix = "swagger"; // 如果你想换一个路径,直接写名字即可,比如直接写c.RoutePrefix = "swagger"; 则访问路径为 根域名/swagger/index.html });
右键项目属性在生成中添加XML
此时通过 http://localhost:端口号/swagger即可访问
二、 Swagger结合版本控制
版本控制的好处:
1、有助于及时推出功能, 而不会破坏现有系统。
2、它还可以帮助为选定的客户提供额外的功能。
1、添加对Microsoft.AspNetCore.Mvc.Versioning和Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer的引用,本文使用版本4.1.0
2、在ConfigureServices中
services.AddApiVersioning(option => { // 可选,为true时API返回支持的版本信息 option.ReportApiVersions = true; // 请求中未指定版本时默认为1.0 option.DefaultApiVersion = new ApiVersion(1, 0); //版本号以什么形式,什么字段传递 option.ApiVersionReader = ApiVersionReader.Combine(new HeaderApiVersionReader("api-version")); // 在不提供版本号时,默认为1.0 如果不添加此配置,不提供版本号时会报错"message": "An API version is required, but was not specified." //option.AssumeDefaultVersionWhenUnspecified = true; //默认以当前最高版本进行访问 //option.ApiVersionSelector = new CurrentImplementationApiVersionSelector(option); }).AddVersionedApiExplorer(opt => { //以通知swagger替换控制器路由中的版本并配置api版本 opt.SubstituteApiVersionInUrl = true; // 版本名的格式:v+版本号 opt.GroupNameFormat = "'v'VVV"; //是否提供API版本服务 opt.AssumeDefaultVersionWhenUnspecified = true; });
//方式一 (不建议使用) 此种方式报警告:ASP0000 从应用程序代码调用“BuildServiceProvider”会导致创建单例服务的附加副本。考虑替代方案,例如将依赖注入服务作为“配置”的参数 services.AddSwaggerGen(options => { // 解析IApiVersionDescriptionProvider服务 var provider = services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>(); //为每个发现的API版本添加一个swagger文档 可跳过不需要记录的 foreach (var description in provider.ApiVersionDescriptions) { options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description)); } //加载XML注释 并启用控制器的注释信息默认为false不启用 options.IncludeXmlComments(XmlCommentsFilePath,true); }); //方式二 (建议使用) services.AddSwaggerGen(); //解决上面报ASP0000警告的方案 services.AddOptions<SwaggerGenOptions>() .Configure<IApiVersionDescriptionProvider>((options, service) => { options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); // 添加文档信息 foreach (var item in service.ApiVersionDescriptions) { options.SwaggerDoc(item.GroupName, CreateInfoForApiVersion(item)); } //给swagger添加过滤器 //options.OperationFilter<SwaggerParameterFilter>(); // 加载XML注释 options.IncludeXmlComments(XmlCommentsFilePath, true); });
添加CreateInfoForApiVersion方法
static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description) { var info = new OpenApiInfo() { //标题 Title = $".NET Core API for 测试项目 {description.ApiVersion}", //当前版本 Version = description.ApiVersion.ToString(), //文档说明 Description = "api项目 当前环境-" + EnvironmentName, //联系方式 Contact = new OpenApiContact() { Name = "标题", Email = "", Url = null }, TermsOfService = new Uri(""), //许可证 License = new OpenApiLicense() { Name = "文档", Url = new Uri("") } };
//当有弃用标记时的提示信息 if (description.IsDeprecated) { info.Description += " - 此版本已放弃兼容"; } return info; }
3、在Configure中添加
IApiVersionDescriptionProvider:用于枚举定义的API版本的API版本描述符提供程序
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVersionDescriptionProvider provider)
//添加Swagger中间件,主要用于拦截swagger.json请求,从而可以获取返回所需的接口架构信息 app.UseSwagger(opt => { //路由模板,默认值是/swagger/{documentName}/swagger.json,这个属性很重要!而且这个属性中必须包含{documentName}参数。 //opt.RouteTemplate= "/swagger/{documentName}/swagger.json"; // 表示按Swagger2.0格式序列化生成swagger.json,这个不推荐使用,尽可能的使用新版本的就可以了 //opt.SerializeAsV2 }); //添加SwaggerUI中间件,主要用于拦截swagger / index.html页面请求,返回页面给前端 app.UseSwaggerUI(options => { // 为每个版本创建一个JSON foreach (var description in provider.ApiVersionDescriptions) { //这个属性是往SwaggerUI页面head标签中添加我们自己的代码,比如引入一些样式文件,或者执行自己的一些脚本代码 //options.HeadContent += $"<script type='text/javascript'>alert('欢迎来到SwaggerUI页面')</script>"; //展示默认头部显示的下拉版本信息 //options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant()); //自由指定头部显示的下拉版本内容 options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", "coreApi" + description.ApiVersion); //如果是为空 访问路径就为 根域名/index.html,注意localhost:8001/swagger是访问不到的 //options.RoutePrefix = string.Empty; // 如果你想换一个路径,直接写名字即可,比如直接写c.RoutePrefix = "swagger"; 则访问路径为 根域名/swagger/index.html options.RoutePrefix = "swagger"; } });
4、在api的Controller中添加版本
[ApiVersion("1.0", Deprecated = false)] //Deprecated是否弃用该版本 默认为false不弃用。即使标记了弃用此接口还是会显示,只是做个提示此版本将会被弃用了。 [Route("api/[controller]")] [ApiController] //[ApiExplorerSettings(IgnoreApi = true)] 隐藏该接口Controller public class ValuesController : Controller
[Obsolete] //弃用该Action方法
[ApiExplorerSettings(IgnoreApi = true)] //隐藏该Action方法
public IEnumerable<string> Get()
为体验版本控制在新建一个控制器并添加 [ApiVersion("2.0")]
此时访问页面,在右侧的下拉框中可选择不同的版本,会展示不同版本下的控制器。
才疏学浅,相关文档等仅供自我总结,如有相关问题可留言交流谢谢。