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<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

微信公众号:老王Plus

扫描二维码,关注个人公众号,可以第一时间得到最新的个人文章和内容推送

本文版权归作者所有,转载请保留此声明和原文链接

Dotnet Core多版本API共存的优雅实现的更多相关文章

  1. dotnet core 使用 CoreRT 将程序编译为 Native 程序

    现在微软有一个开源项目 CoreRT 能通过将托管的 .NET Core 编译为单个无依赖的 Native 程序 这个项目现在还没发布,但是能尝试使用,可以带来很多的性能提升 使用 CoreRT 发布 ...

  2. 2017-03-04 dotnet core网站发布到Linux系统中

    今天开始学习dotnet core的开发,距离Visual Stuio 2017正式版的发布,也就是VS20周岁的生日还有三天,在我的电脑上安装的是VS2017 Enterprise RC版, 在VS ...

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

    作者:陈希章 发表于 2017年12月19日 引子 这一篇文章将用一个完整的实例,给大家介绍如何基于dotnet core(微软.NET的最新版本,支持跨平台,跨设备的应用开发,详情请参考 https ...

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

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

  5. linux上编写运行 dotnet core api

    安装 Ubuntu        dotnet core 跨平台已不再是梦,它带来的意义非凡,比如api接口可以在linux上编写及部署,也可以在windows上编写好,打包发布,然后copy到lin ...

  6. devOps开发(Web API 实例)dotnet core 和 Azure PaaS服务

    使用 dotnet core 和 Azure PaaS服务进行devOps开发(Web API 实例) 作者:陈希章 发表于 2017年12月19日 引子 这一篇文章将用一个完整的实例,给大家介绍如何 ...

  7. Dotnet Core Public API的安全实践

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

  8. spring cloud+dotnet core搭建微服务架构:Api网关(三)

    前言 国庆假期,一直没有时间更新. 根据群里面的同学的提问,强烈推荐大家先熟悉下spring cloud.文章下面有纯洁大神的spring cloud系列. 上一章最后说了,因为服务是不对外暴露的,所 ...

  9. spring cloud+dotnet core搭建微服务架构:Api授权认证(六)

    前言 这篇文章拖太久了,因为最近实在太忙了,加上这篇文章也非常长,所以花了不少时间,给大家说句抱歉.好,进入正题.目前的项目基本都是前后端分离了,前端分Web,Ios,Android...,后端也基本 ...

随机推荐

  1. MySQL优化篇(未完待续)

    一.优化SQL语句的一般步骤 1.通过 show status命令了解各种sql的执行频率 mysql客户端连接成功后,通过show[session|global] status命令,可以查看服务器的 ...

  2. Android应用测试指南

    一.Android 的 SDK Windows 版本安装 按顺序安装以下内容 1.    安装JDK(Java Development Kit, 即Java开发工具包) 2. 安装Eclipse 集成 ...

  3. shipyard中文版安装教程(附安装脚本)

    一. Docker Shipyard是什么 ? shipyard是一个开源的docker管理平台,其特性主要包括: 支持节点动态集群,可扩展节点的规模(swarm.etcd方案) 支持镜像管理.容器管 ...

  4. Linux 学习笔记01丨Ubuntu系统安装、配置及软件教程集合

    1. Ubuntu系统安装 Windows10安装ubuntu18.04双系统教程 Ubuntu 20.04.1 镜像下载 软碟通 机械革命进入BIOS模式 要按F2,注意将Boot Option中将 ...

  5. [GIT]获取git最新的tag

    背景 公司前端项目在Jenkins中打包,每次打包需要将新tag回推到仓库中.但是打包失败后如果不删除tag的话下次打包就会失败,需要手动删除,所以在Jenkinsfile中就需要在打包失败时自动删除 ...

  6. redis 一致性分析

    转载: https://blog.csdn.net/qq32933432/article/details/108690254

  7. Spring源码解析之BeanFactoryPostProcessor(二)

    上一章,我们介绍了在AnnotationConfigApplicationContext初始化的时候,会创建AnnotatedBeanDefinitionReader和ClassPathBeanDef ...

  8. uni-app 封装接口request请求

    我们知道一个项目中对于前期架构的搭建工作对于后期的制作有多么重要,所以不管做什么项目我们拿到需求后一定要认真的分析一下,要和产品以及后台沟通好,其中尤为重要的一个环节莫过于封装接口请求了.因为前期封装 ...

  9. 了不起的 Deno:带你极速获取各大平台今日热榜

    摘要:Deno 是一个 JavaScript/TypeScript 的运行时,默认使用安全环境执行代码,有着卓越的开发体验. 有人的地方就有江湖,有江湖的地方就有争论.前些天,继<[译]为什么如 ...

  10. JZOJ2020年8月11日提高组T1 密码

    JZOJ2020年8月11日提高组T1 密码 题目 Description 在浩浩茫茫的苍穹深处,住着上帝和他的神仆们,他们闲谈着下界的凡人俗事,对人世间表现的聪明智慧,大加赞赏.今天他们正在观赏大地 ...