• .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")]

    此时访问页面,在右侧的下拉框中可选择不同的版本,会展示不同版本下的控制器。

    才疏学浅,相关文档等仅供自我总结,如有相关问题可留言交流谢谢。

    原文地址:https://www.cnblogs.com/mzflog/p/14969620.html

    世界再大也有尽头!
  • 相关阅读:
    C++ Programming Language中的narrow_cast实现
    使用反射处理protobuf数据结构
    Qt中三种解析xml的方式
    iterator简单描述
    关于Strategy和State设计模式
    Jedis连接redis客户端
    Redis基础命令
    redis的安装和启动linux环境
    Redis简介和常见的面试题
    SSM框架整合
  • 原文地址:https://www.cnblogs.com/shijiehaiyang/p/15751845.html
Copyright © 2020-2023  润新知