博客园Logo
首页
新闻
博问
专区
闪存
班级
代码改变世界
搜索
注册
登录
返回主页
老王Plus的全栈
博客园 首页 新随笔 联系 订阅 管理随笔 - 34 文章 - 0 评论 - 115
Dotnet Core多版本API共存的优雅实现
API升级,新旧版本的API共存,怎么管理呢?
一、前言
最近,单位APP做了升级,同步的,API也做了升级。
升级过程中,出现了一点问题:API升级后,旧API也需要保留,因为有旧的APP还在使用中。
那么,API端如何作到多个版本共存呢?
为防止非授权转发,这儿给出本文的原文链接:https://www.cnblogs.com/tiger-wang/p/14167625.html
二、快速的解决办法
API的露出,是在API的Route定义中实现的。看下面的例子:
[Route(“api/[controller]”)]
public class DemoController : ControllerBase
{
[Route(“demo”)]
public ActionResult DemoFunc()
{
}
}
那我们知道,这个API的终结点是:/api/demo/demo。代码中[controller]是个可替换变量,编译时会替换为当前控制器的名称。
这个Route,里面的参数是个字符串,也就是说是可以随便换的。所以,对于多版本API,有个快速的办法,就是在里面做文章。
我们可以写成:
[Route(“api/v1/[controller]”)]
public class DemoController : ControllerBase
{
[Route(“demo”)]
public ActionResult DemoFunc()
{
}
}
或者
[Route(“api/[controller]”)]
public class DemoController : ControllerBase
{
[Route(“v1/demo”)]
public ActionResult 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 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和过滤IOperationFilter。
先看Startup.cs里:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IConfigureOptions, ConfigureSwaggerOptions>();
services.AddSwaggerGen(options => options.OperationFilter());
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
{
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
微信公众号:老王Plus
扫描二维码,关注个人公众号,可以第一时间得到最新的个人文章和内容推送
本文版权归作者所有,转载请保留此声明和原文链接
分类: .Net core
标签: dotnet core, c#
好文要顶 关注我 收藏该文
老王Plus
关注 - 3
粉丝 - 53
+加关注
3 0
« 上一篇: 一文说通C#中的异步迭代器
posted @ 2020-12-23 09:17 老王Plus 阅读(317) 评论(2) 编辑 收藏
评论列表
#1楼 2020-12-23 09:40 mrfangzheng
有2种方式,
[1] 客户端URL主动指定服务端API版本号(比如v1,v2)
[2 ]客户端请求头header中带有客户端版本号(比如1.0.2.1, 1.0.3.188).
第二种情况下, 服务端根据客户端版本来判断调哪个API, 感觉更灵活.
支持(0) 反对(0)
#2楼 [楼主] 2020-12-23 10:49 老王Plus
@mrfangzheng
有2种方式,
[1] 客户端URL主动指定服务端API版本号(比如v1,v2)
[2 ]客户端请求头header中带有客户端版本号(比如1.0.2.1, 1.0.3.188).
第二种情况下, 服务端根据客户端版本来判断调哪个API, 感觉更灵活.
这是一个理论上的理想状态,但实际开发的时候一般不会这么做。API版本升级来自于业务升级,是先有的业务升级,才有API升级,然后才是APP升级。如果能提前规划到API版本的升级,这倒是个好想法。
支持(0) 反对(0)
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
写给园友们的一封求助信
【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】有你助力,更好为你——博客园用户消费观调查,附带小惊喜!
【推荐】博客园x丝芙兰-圣诞特别活动:圣诞选礼,美力送递
【推荐】了不起的开发者,挡不住的华为,园子里的品牌专区
【福利】AWS携手博客园为开发者送免费套餐+50元京东E卡
【推荐】未知数的距离,毫秒间的传递,声网与你实时互动
【推荐】新一代 NoSQL 数据库,Aerospike专区新鲜入驻
相关博文:
· 2019-11-29-dotnet-core-使用-GBK-编码
· dotnetcore2.2在linux下不支持画图
· Docker简单发布dotnetcore项目文本版
· 【ASP.NETCore学习】WebAPI
· Docker简单发布dotnetcore项目图文版
» 更多推荐…
最新 IT 新闻:
· 四周都是“气氛组”,只有你是傻白甜
· 让神经网络给符号AI“打工”,MIT和IBM联合解决深度学习痛点,未来将用于自动驾驶
· 互联网存款产品48小时集体下架 原因定性:“无照驾驶”非法金融活动
· NASA开放新发射台,支持小型运载火箭发射客户
· 花12亿买和解!瑞幸咖啡未来何解?律师:不排除重新上市
» 更多新闻…
公告
昵称: 老王Plus
园龄: 4年9个月
粉丝: 53
关注: 3
+加关注
< 2020年12月 >
日 一 二 三 四 五 六
29 30 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
3 4 5 6 7 8 9
搜索
找找看
谷歌搜索
常用链接
我的随笔
我的评论
我的参与
最新评论
我的标签
我的标签
dotnet core(28)
c#(8)
mongodb(7)
架构(6)
debian(5)
dotnet(4)
设计模式(4)
异步(3)
安装(2)
k8s(2)
更多
随笔分类
.Net core(31)
Blazor(1)
Debian(5)
Kubernetes(2)
Mono(2)
MonogDB(7)
Python(1)
机器学习(1)
架构(6)
区块链(1)
项目管理(1)
随笔档案
2020年12月(3)
2020年11月(3)
2020年10月(2)
2020年9月(4)
2020年8月(4)
2020年7月(4)
2020年6月(4)
2020年5月(6)
2020年4月(3)
2016年3月(1)
最新评论
-
Re:Dotnet Core多版本API共存的优雅实现
@mrfangzheng 有2种方式, [1] 客户端URL主动指定服务端API版本号(比如v1,v2) [2 ]客户端请求头header中带有客户端版本号(比如1.0.2.1, 1.0.3.188)…
–老王Plus -
Re:Dotnet Core多版本API共存的优雅实现
有2种方式, [1] 客户端URL主动指定服务端API版本号(比如v1,v2) [2 ]客户端请求头header中带有客户端版本号(比如1.0.2.1, 1.0.3.188). 第二种情况下, 服务端…
–mrfangzheng -
Re:Dotnet Core下的Channel, 你用了吗?
又学到了新的知识
–鑫神 -
Re:Dotnet Core下的Channel, 你用了吗?
跟队列有什么区别? 优劣势分析一下呗
–提伯斯 -
Re:Dotnet Core下的Channel, 你用了吗?
内置的生产者,消费者模式
–说书的猫
阅读排行榜 -
一文说通C#中的异步编程(2400)
-
.Net Core实现区块链初探(1813)
-
Dotnet core使用JWT认证授权最佳实践(一)(1689)
-
15分钟从零开始搭建支持10w+用户的生产环境(四)(1669)
-
15分钟从零开始搭建支持10w+用户的生产环境(二)(1505)
评论排行榜 -
一文说通C#中的异步编程(14)
-
.Net Core实现区块链初探(13)
-
Dotnet Core下的Channel, 你用了吗?(12)
-
Dotnet Core Public API的安全实践(11)
-
C#实践设计模式原则SOLID(6)
推荐排行榜 -
一文说通C#中的异步编程(25)
-
.Net Core实现区块链初探(23)
-
C#实践设计模式原则SOLID(13)
-
一文说通C#中的异步编程补遗(11)
-
一文说通C#中的异步迭代器(10)
Copyright © 2020 老王Plus
Powered by .NET 5.0.1-servicing.20575.16 on Kubernetes