Dotnet Core多版本API共存的优雅实现
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共存的优雅实现相关推荐
- dotnet core高吞吐Http api服务组件FastHttpApi
简介 是dotNet core下基于Beetlex实现的一个高度精简化和高吞吐的HTTP API服务开源组件,它并没有完全实现HTTP SERVER的所有功能,而是只实现了在APP和WEB中提供数据服 ...
- Dotnet Core异常处理的优雅实践
异常处理,也可以做得很优雅. 一.前言 异常处理的重要性,老司机都清楚. 这篇文章,我们来理一下Dotnet Core异常处理的几种方式. Try Catch方式 Exception Filt ...
- Dotnet Core Public API的安全实践
公开API的安全,其实更重要. 一.API的安全 作为一个Dotnet Core的老司机,写API时,能兼顾到API的安全,这是一种优雅. 通常,我们会用认证来保证API的安全,无敌的Auth ...
- dotNET Core 3.X 使用 Web API
现在的 Web 开发大多都是前后端分离的方式,后端接口的正确使用显得尤为重要,本文讲下在 dotNET Core 3.X 下使用 Web API . 环境 操作系统:Mac IDE:Rider dot ...
- 使用 dotnet core 和 Azure PaaS服务进行devOps开发(Web API 实例)
引子 这一篇文章将用一个完整的实例,给大家介绍如何基于dotnet core(微软.NET的最新版本,支持跨平台,跨设备的应用开发,详情请参考 https://www.microsoft.com/ne ...
- 国产中标麒麟Linux部署dotnet core 环境并运行项目 (三) 部署运行WEB API项目
部署dotnet Core Web API 上一步的文章,是我们公司最核心的一个ORM组件,在中标麒麟系统完成了一个插入数据的任务,这一步是将正式的从dot net framework 迁移到 dot ...
- Dotnet Core 优雅的命令行实现
介绍一个命令行的实现库,可以优雅而简单的实现命令行应用. 前言 控制台应用 Console,在我们开发中用处很多.小到一个简单的功能测试,或一组不需要复杂 UI 的工具类应用,大到后端的服务,都会 ...
- Dotnet Core应用跨框架版本运行
有时候,我们真想用新框架,可也真不想改代码. 有一个前置的知识需要了解,就是微软 Dotnet Core 框架的版本体系.我前边的文章「Dotnet Core使用特定的SDK&Runtim ...
- Dotnet Core使用特定的SDKRuntime版本
Dotnet Core的SDK版本总在升级,怎么使用一个特定的版本呢? 假期过完了,心情还在.今天写个短的. 一.前言 写这个是因为昨天刷微软官方文档,发现global.json在 SDK 3.0 ...
最新文章
- Jquery封装(学习)01
- linux shell 提示符设置
- 数仓建模 项目_模型设计_数仓建模 PDF 下载
- 暑期项目经验(九) -- request session application
- 基础知识很扎实 - 但是面试就是做不出来, 怎么办? (长, 慎入)
- python的scapy_Python Scapy vs dp
- nodejs的事件处理机制
- 前端圈小可爱 Vue 的自白:我年少成名,却又屡陷 React、Angular 混战
- cropper.js插件做图片上传裁剪图片大小
- 软件工程中需要学习和掌握的软件都有哪些_高三孩子:你想学软件工程,要先知道这些...
- HTML调用QQ临时会话
- 计算机网络国家职业三级,计算机网络管理员国家职业标准
- 如何用css设置文字加粗,css如何设置文字加粗
- 用Python能下载抖音无水印视频?免费教程来了!
- 飞思卡尔 智能车(山大 Router) 核心源码
- 成为一名数据分析师,需要学习统计学吗?
- win10重装为Ubuntu 20.04
- DirectX的发展历程!
- 什么是Linkerd
- 中国国际货代行业市场运营规划及发展潜力研究报告2022年版
热门文章
- ubuntu linux下建立stm32开发环境: 程序烧录 openocd+openjtag
- labelme2coco问题:TypeError: Object of type 'int64' is not JSON serializable
- Java多线程之静态代理
- 机器学习(一)—— 线性回归
- 解决安装Weblogic domain卡住问题(Primeton BPS)
- 关于内存的划分和传引用传参数的区别
- lz98n外接电源注意问题
- Commons里的DButil
- [Forward] 因为火炬,所以迟到,工资照扣
- outlook存档邮件_如何在Outlook 2013中存档电子邮件