API升级,新旧版本的API共存,怎么管理呢?

一、前言

最近,单位APP做了升级,同步的,API也做了升级。

升级过程中,出现了一点问题:API升级后,旧API也需要保留,因为有旧的APP还在使用中。

那么,API端如何作到多个版本共存呢?

二、快速的解决办法

API的露出,是在API的Route定义中实现的。看下面的例子:

[Route("api/[controller]")]
public class DemoController : ControllerBase
{[Route("demo")]public ActionResult<T> DemoFunc(){}
}

那我们知道,这个API的终结点是:/api/demo/demo。代码中[controller]是个可替换变量,编译时会替换为当前控制器的名称。

这个Route,里面的参数是个字符串,也就是说是可以随便换的。所以,对于多版本API,有个快速的办法,就是在里面做文章。

我们可以写成:

[Route("api/v1/[controller]")]
public class DemoController : ControllerBase
{[Route("demo")]public ActionResult<T> DemoFunc(){}
}

或者

[Route("api/[controller]")]
public class DemoController : ControllerBase
{[Route("v1/demo")]public ActionResult<T> DemoFunc(){}
}

这样就区分出了版本号。

当然,这样做比较LOW,因为版本号是硬编码在代码中的。而且,这个改动会影响到API的终结点,例如上面两个变化,会让终结点变为:/api/v1/demo/demo/api/demo/v1/demo。如果前端可以方便修改,也算是一个方法。但对于我们APP已经上线运行来说,这个改动无法接受。

三、优雅的解决办法

这个方案,才是今天要说的核心内容。

首先,我们需要从Nuget上引入两个库:

% dotnet add package Microsoft.AspNetCore.Mvc.Versioning
% dotnet add package Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer

这两个库,Versioning用来实现API的版本控制,Versioning.ApiExplorer用来实现元数据的发现工作。

引入完成后,修改Startup.cs

public void ConfigureServices(IServiceCollection services)
{services.AddApiVersioning(options =>{options.DefaultApiVersion = new ApiVersion(1, 0);options.AssumeDefaultVersionWhenUnspecified = true;options.ReportApiVersions = true;});services.AddVersionedApiExplorer(options =>{options.GroupNameFormat = "'v'VVV";options.SubstituteApiVersionInUrl = true;});services.AddControllers();
}

就可以了。

这里面用了两个配置:AddApiVersioning,主要用来配置向前兼容,定义了如果没有带版本号的访问,会默认访问v1.0的接口。AddVersionedApiExplorer用来添加API的版本管理,并定义了版本号的格式化方式,以及兼容终结点上带版本号的方式。

到这儿,引入版本管理的工作就完成了。

使用时,就直接在控制器或方法上定义版本号:

[ApiVersion("1")]
[Route("api/[controller]")]
public class DemoController : ControllerBase
{[MapToApiVersion("2")][Route("demo")]public ActionResult<T> DemoFunc(){}
}

这里面,又是两个属性:ApiVersion定义控制器提供哪个版本的API。这个属性可以定义多个。例如,我们控制器里既有v1的API,也有v2的API,我们可以写成:

[ApiVersion("1")]
[ApiVersion("2")]
[Route("api/[controller]")]
public class DemoController : ControllerBase
{
}

MapToApiVersion是API的版本定义,定义我们这个API是哪一个版本。

方法就这么简单。其它的,微软都帮我们做好了。

那,通常我们会用Swagger来做API文档。这个方法如何跟Swagger配合呢?

四、与Swagger的配合

Swagger也来自于Nuget的引用:

% dotnet add package swashbuckle.aspnetcore

引用后,通常我们Startup.cs里的配置是这样的:

public void ConfigureServices(IServiceCollection services)
{services.AddSwaggerGen(option =>{option.SwaggerDoc("v1", new OpenApiInfo { Title = "Demo", Version = "V1" });});services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{app.UseSwagger();app.UseSwaggerUI(option =>{option.SwaggerEndpoint("/swagger/v1/swagger.json", "Demo");});}

API多版本管理与Swagger配合,也有一个快速但比较LOW的方法:

public void ConfigureServices(IServiceCollection services)
{services.AddSwaggerGen(option =>{option.SwaggerDoc("v1", new OpenApiInfo { Title = "Demo", Version = "V1" });option.SwaggerDoc("v1", new OpenApiInfo { Title = "Demo", Version = "V2" });});services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{app.UseSwagger();app.UseSwaggerUI(option =>{option.SwaggerEndpoint("/swagger/v1/swagger.json", "Demo V1");option.SwaggerEndpoint("/swagger/v2/swagger.json", "Demo V2");});
}

这个方法也可以快速实现,不过跟上边的情况一样,版本号是硬编码的。

其实,也有另一个比较优雅的方式,就是手动实现IConfigureOptions<SwaggerGenOptions>和过滤IOperationFilter

先看Startup.cs里:

public void ConfigureServices(IServiceCollection services)
{services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();services.AddSwaggerGen(options => options.OperationFilter<SwaggerDefaultValues>());services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{app.UseSwagger();app.UseSwaggerUI(option =>{foreach (var description in provider.ApiVersionDescriptions){c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());}});
}

这里加了两个类,第一个ConfigureSwaggerOptions

internal class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
{private readonly IApiVersionDescriptionProvider _provider;public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) => _provider = provider;public void Configure(SwaggerGenOptions options){foreach (var description in _provider.ApiVersionDescriptions){options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description));}}private OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description){var info = new OpenApiInfo(){Title = "Demo API",Version = description.ApiVersion.ToString(),};if (description.IsDeprecated){info.Description += " 方法被弃用.";}return info;}
}

第二个SwaggerDefaultValues

internal class SwaggerDefaultValues : IOperationFilter
{public void Apply(OpenApiOperation operation, OperationFilterContext context){var apiDescription = context.ApiDescription;operation.Deprecated |= apiDescription.IsDeprecated();if (operation.Parameters == null)return;foreach (var parameter in operation.Parameters){var description = apiDescription.ParameterDescriptions.First(p => p.Name == parameter.Name);if (parameter.Description == null){parameter.Description = description.ModelMetadata?.Description;}if (parameter.Schema.Default == null && description.DefaultValue != null){parameter.Schema.Default = new OpenApiString(description.DefaultValue.ToString());}parameter.Required |= description.IsRequired;}}
}

代码不一行行解释了,都是比较简单的。

运行,进入Swagger界面,右上角Select a definition,可以选择我们定义的版本号。

今天的配套代码已上传到Github,位置在:https://github.com/humornif/Demo-Code/tree/master/0035/demo

喜欢就来个三连,让更多人因你而受益

Dotnet Core多版本API共存的优雅实现相关推荐

  1. dotnet core高吞吐Http api服务组件FastHttpApi

    简介 是dotNet core下基于Beetlex实现的一个高度精简化和高吞吐的HTTP API服务开源组件,它并没有完全实现HTTP SERVER的所有功能,而是只实现了在APP和WEB中提供数据服 ...

  2. Dotnet Core异常处理的优雅实践

    异常处理,也可以做得很优雅.   一.前言 异常处理的重要性,老司机都清楚.   这篇文章,我们来理一下Dotnet Core异常处理的几种方式. Try Catch方式 Exception Filt ...

  3. Dotnet Core Public API的安全实践

    公开API的安全,其实更重要.   一.API的安全 作为一个Dotnet Core的老司机,写API时,能兼顾到API的安全,这是一种优雅.   通常,我们会用认证来保证API的安全,无敌的Auth ...

  4. dotNET Core 3.X 使用 Web API

    现在的 Web 开发大多都是前后端分离的方式,后端接口的正确使用显得尤为重要,本文讲下在 dotNET Core 3.X 下使用 Web API . 环境 操作系统:Mac IDE:Rider dot ...

  5. 使用 dotnet core 和 Azure PaaS服务进行devOps开发(Web API 实例)

    引子 这一篇文章将用一个完整的实例,给大家介绍如何基于dotnet core(微软.NET的最新版本,支持跨平台,跨设备的应用开发,详情请参考 https://www.microsoft.com/ne ...

  6. 国产中标麒麟Linux部署dotnet core 环境并运行项目 (三) 部署运行WEB API项目

    部署dotnet Core Web API 上一步的文章,是我们公司最核心的一个ORM组件,在中标麒麟系统完成了一个插入数据的任务,这一步是将正式的从dot net framework 迁移到 dot ...

  7. Dotnet Core 优雅的命令行实现

    介绍一个命令行的实现库,可以优雅而简单的实现命令行应用.   前言 控制台应用 Console,在我们开发中用处很多.小到一个简单的功能测试,或一组不需要复杂 UI 的工具类应用,大到后端的服务,都会 ...

  8. Dotnet Core应用跨框架版本运行

    有时候,我们真想用新框架,可也真不想改代码.   有一个前置的知识需要了解,就是微软 Dotnet Core 框架的版本体系.我前边的文章「Dotnet Core使用特定的SDK&Runtim ...

  9. Dotnet Core使用特定的SDKRuntime版本

    Dotnet Core的SDK版本总在升级,怎么使用一个特定的版本呢?   假期过完了,心情还在.今天写个短的. 一.前言 写这个是因为昨天刷微软官方文档,发现global.json在 SDK 3.0 ...

最新文章

  1. Jquery封装(学习)01
  2. linux shell 提示符设置
  3. 数仓建模 项目_模型设计_数仓建模 PDF 下载
  4. 暑期项目经验(九) -- request session application
  5. 基础知识很扎实 - 但是面试就是做不出来, 怎么办? (长, 慎入)
  6. python的scapy_Python Scapy vs dp
  7. nodejs的事件处理机制
  8. 前端圈小可爱 Vue 的自白:我年少成名,却又屡陷 React、Angular 混战
  9. cropper.js插件做图片上传裁剪图片大小
  10. 软件工程中需要学习和掌握的软件都有哪些_高三孩子:你想学软件工程,要先知道这些...
  11. HTML调用QQ临时会话
  12. 计算机网络国家职业三级,计算机网络管理员国家职业标准
  13. 如何用css设置文字加粗,css如何设置文字加粗
  14. 用Python能下载抖音无水印视频?免费教程来了!
  15. 飞思卡尔 智能车(山大 Router) 核心源码
  16. 成为一名数据分析师,需要学习统计学吗?
  17. win10重装为Ubuntu 20.04
  18. DirectX的发展历程!
  19. 什么是Linkerd
  20. 中国国际货代行业市场运营规划及发展潜力研究报告2022年版

热门文章

  1. ubuntu linux下建立stm32开发环境: 程序烧录 openocd+openjtag
  2. labelme2coco问题:TypeError: Object of type 'int64' is not JSON serializable
  3. Java多线程之静态代理
  4. 机器学习(一)—— 线性回归
  5. 解决安装Weblogic domain卡住问题(Primeton BPS)
  6. 关于内存的划分和传引用传参数的区别
  7. lz98n外接电源注意问题
  8. Commons里的DButil
  9. [Forward] 因为火炬,所以迟到,工资照扣
  10. outlook存档邮件_如何在Outlook 2013中存档电子邮件