原文链接:API Versioning in .Net Core

作者:Neel Bhatt

简介

Api的版本控制是Api开发中经常遇到的问题, 在大部分中大型项目都需要使用到Api的版本控制

在本篇博客中,我们将说明一下如何在.Net Core Api项目中使用Api版本控制。

本篇博客中测试项目的开发环境:

  • Visual Studio 2017
  • .Net Core 2.1 SDK

.Net Core Api中使用Api版本控制

创建一个Api项目

首先我们创建一个.NET Core Api项目

使用Nuget安装Api版本控制库

.NET Core Mvc中,微软官方提供了一个可用的Api版本控制库Microsoft.AspNetCore.Mvc.Versioning。 这里我们可以使用Nuget安装这个包。

PM> Install-Package Microsoft.AspNetCore.Mvc.Versioning

修改Startup类

Microsoft.AspNetCore.Mvc.Versioning库安装完成之后,下一步我们来添加Api版本控制服务。

这里我们需要在Startup类的ConfigureService方法中添加以下代码。

    services.AddApiVersioning(o => {
o.ReportApiVersions = true;
o.AssumeDefaultVersionWhenUnspecified = true;
o.DefaultApiVersion = new ApiVersion(1, 0);
});

代码解释

ReportApiVersion 属性是一个布尔类型,如果设置为true, 在Api请求的响应头部,会追加当前Api支持的版本, 例

Response Header
api-supported-versions: 1.0
content-type: application/json; charset=utf-8
date: Sat, 06 Oct 2018 05:24:21 GMT
server: Kestrel
status: 200
x-powered-by: ASP.NET

AssumeDefaultVersionWhenUnspecified属性是为了标记当客户端没有指定版本号的时候,是否使用默认版本号

DefaultApiVersion属性即默认版本号

创建多版本Api

这里为了测试.Net Core Mvc的Api版本控制库,我们创建如下2个Controller。


[ApiVersion("1.0")]
[Route("api/values")]
[ApiController]
public class ValuesV1Controller : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "Value1 from Version 1", "value2 from Version 1" };
}
} [ApiVersion("2.0")]
[Route("api/values")]
[ApiController]
public class ValuesV2Controller : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1 from Version 2", "value2 from Version 2" };
}
}

代码解释

  • Value1ControllerValue2Controller使用了一样的路由"/api/values"
  • Value1Controller类头部使用ApiVersion特性标记了当前Controller的Api版本号是1.0
  • Value2Controller类头部使用ApiVersion特性标记了当前Controller的Api版本号是2.0

    -Value1ControllerValue2Controller都持有相同方法签名的Get方法, 只是2个Get中返回了不同的字符串

现在我们启动项目,得到的结果如下,说明当没有指定Api版本号时,项目自动使用1.0版本的Api, 即ValuesV1Controller中的Get方法。

如何在查询字符串(Query String)中使用版本控制

Microsoft.AspNetCore.Mvc.Versioning支持以QueryString的形式指定请求Api的版本号。开发人员可以在Url中指定api-version参数来选择调用的Api版本号。

以当前项目为例

当请求https://localhost:44319/api/values?api-version=2.0时, 返回结果

["value1 from Version 2","value2 from Version 2"]

当请求https://localhost:44319/api/values?api-version=1.0时, 返回结果

["Value1 from Version 1","value2 from Version 1"]

如何使用路由约束中指定请求Api的版本

Microsoft.AspNetCore.Mvc.Versioning还支持使用路由约束指定请求Api的版本号。

例: [Route(“api/{v:apiVersion}/Values”)]

我们对之前2个Controller的代码作如下修改。

    [ApiVersion("1.0")]
[Route("api/{v:apiVersion}/values")]
[ApiController]
public class ValuesV1Controller : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "Value1 from Version 1", "value2 from Version 1" };
}
} [ApiVersion("2.0")]
[Route("api/{v:apiVersion}/values")]
[ApiController]
public class ValuesV2Controller : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1 from Version 2", "value2 from Version 2" };
}
}

现在我们通过以下2个Url请求Api, 返回的结果如下 :

/api/2.0/values

["value1 from Version 2","value2 from Version 2"]

/api/1.0/values

["Value1 from Version 1","value2 from Version 1"]

如何在请求头(HTTP Header)中使用版本控制

以上的2种方式需要修改请求的Url, 如果你不喜欢这2种方式,Microsoft.AspNetCore.Mvc.Versioning还提供了第三种指定Api版本号的方式,即在HTTP请求头中添加版本号参数。

为了启用这种方式,我们首先需要在Startup.cs中修改Microsoft.AspNetCore.Mvc.Versioning的配置, 代码如下:

    services.AddApiVersioning(o =>
{
o.ReportApiVersions = true;
o.AssumeDefaultVersionWhenUnspecified = true;
o.DefaultApiVersion = new ApiVersion(1, 0);
o.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
});

这里通过ApiVersionReader属性指定了Api版本号是从请求头部的x-api-version属性来的。

Tips: 一旦你使用o.ApiVersionReader = new HeaderApiVersionReader("x-api-version");, 在查询字符串中指定版本号的方式将不再可用,如果你希望同时支持2种方式,请改用o.ApiVersionReader = ApiVersionReader.Combine(new QueryStringApiVersionReader(), new HeaderApiVersionReader() { HeaderNames = { "x-api-version" }});(多谢seamaswang的更正)

下面我们通过Postman来请求2.0的Api, 结果正确返回了。

其他特性

弃用Api(Deprecated)特性

有些时候,我们需要标记一些过时的Api为弃用状态,但是我们又不希望完全移除这个版本的Api, 我们可以使用Deprecated特性。

例:我们当前希望弃用ValuesV1Controller, 我们可以指定Deprecated特性的值为true

    [ApiVersion("1.0", Deprecated = true)]
[Route("api/values")]
[ApiController]
public class ValuesV1Controller : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "Value1 from Version 1", "value2 from Version 1" };
}
}

当我们请求在此请求这个api的时候, 在响应头中会出现api-deprecated-versionsapi-supported-versions2个属性。

Response Header
api-deprecated-versions: 1.0
api-supported-versions: 2.0
content-type: application/json; charset=utf-8
date: Sat, 06 Oct 2018 06:32:18 GMT
server: Kestrel
status: 200
x-powered-by: ASP.NET

这段响应的意思就是1.0版本的Api已经过期了,2.0版本中有相同的Api, 可以换用2.0版本的Api。

使用ApiVersionNeutral指定不需要版本控制的Api

在编写Api的时候,对于一些非常简单的Api, 我们可能不需要指定Api版本号, 例如健康检查Api。我们可以使用ApiVersionNeutral特性,将它从Api版本控制中排除掉。

例:

    [ApiVersionNeutral]
[Route("api/[controller]")]
[ApiController]
public class HealthCheckController : ControllerBase
{
public string Get()
{
return "Good";
}
}

本篇源代码

.Net Core中的Api版本控制的更多相关文章

  1. 【转】.Net Core中的Api版本控制

    原文链接:API Versioning in .Net Core 作者:Neel Bhatt 简介 Api的版本控制是Api开发中经常遇到的问题, 在大部分中大型项目都需要使用到Api的版本控制 在本 ...

  2. ASP.NET Core 3.x API版本控制

    前言 一般来说需要更改我们API的时候才考虑版本控制,但是我觉得我们不应该等到那时候来实现它,我们应该有一个版本策略从我们应用程序开发时就开始制定好我们的策略,我们一直遵循着这个策略进行开发. 我们其 ...

  3. ASP.NET Core 中基于 API Key 对私有 Web API 进行保护

    这两天遇到一个应用场景,需要对内网调用的部分 web api 进行安全保护,只允许请求头账户包含指定 key 的客户端进行调用.在网上找到一篇英文博文 ASP.NET Core - Protect y ...

  4. EF Core中Fluent Api如何删除指定数据表中的行

    这两天一直在研究在code first下如何删除数据表中的指定行,于是开始搜狗,后来百度,压根就找不到资料,后来一想可能我的搜索关键字有问题,而且ef core命令与ef的命令差不多,于是从这两个方面 ...

  5. ASP.NET Core API 版本控制

    几天前,我和我的朋友们使用 ASP.NET Core 开发了一个API ,使用的是GET方式,将一些数据返回到客户端 APP.我们在前端进行了分页,意味着我们将所有数据发送给客户端,然后进行一些dat ...

  6. 【转】ASP.NET Core API 版本控制

    几天前,我和我的朋友们使用 ASP.NET Core 开发了一个API ,使用的是GET方式,将一些数据返回到客户端 APP.我们在前端进行了分页,意味着我们将所有数据发送给客户端,然后进行一些dat ...

  7. 【ASP.NET Core】ASP.NET Core API 版本控制

    几天前,我和我的朋友们使用 ASP.NET Core 开发了一个API ,使用的是GET方式,将一些数据返回到客户端 APP.我们在前端进行了分页,意味着我们将所有数据发送给客户端,然后进行一些dat ...

  8. [翻译]在 .NET Core 中的并发编程

    原文地址:http://www.dotnetcurry.com/dotnet/1360/concurrent-programming-dotnet-core 今天我们购买的每台电脑都有一个多核心的 C ...

  9. .NET Core 中的并发编程

    今天我们购买的每台电脑都有一个多核心的 CPU,允许它并行执行多个指令.操作系统通过将进程调度到不同的内核来发挥这个结构的优点. 然而,还可以通过异步 I/O 操作和并行处理来帮助我们提高单个应用程序 ...

随机推荐

  1. 部署ceph

    前提:因为ceph部署时要去国外源下载包,导致下载安装时会卡住,因此我们只需通过国内的源找到对应的rpm下载安装. 一.环境准备 4台机器,1台机器当部署节点和客户端,3台ceph节点,ceph节点配 ...

  2. Java 扫描实现 Ioc 动态注入,过滤器根据访问url调用自定义注解标记的类及其方法

    扫描实现 Ioc 动态注入 参考: http://www.private-blog.com/2017/11/16/java-%e6%89%ab%e6%8f%8f%e5%ae%9e%e7%8e%b0-i ...

  3. Go资源

    go语言实现的设计模式 http://tmrts.com/go-patterns/ https://design-patterns.readthedocs.io/zh_CN/latest/index. ...

  4. Do-Now—团队冲刺博客一(领航篇)

    Do Now -- 团队冲刺博客一(领航篇) 团队博客总目录:团队作业第一周 团队作业第二周 Do Now -- 团队冲刺博客一 领航目标 ① 各个成员在 Alpha 阶段认领的任务 ② 明日各个成员 ...

  5. centOS7.3新安装后,设置IP,以及Putty远程和Xshell远程 (学习是个持续的过程,也许中途放松过,但是仍然能重新捡起来,并学以致用,方为真勇士)

    有一段时间没有写学习心得了:现在开始加油,再接再励. 从最基础的开始 1.安装centOS7.3之后设置IP地址.一般linux的系统都是作为服务器的系统来使用,服务器的属性注定了他的IP不能随意的更 ...

  6. Web框架之Django篇

    1.创建Project 命令: django-admin startproject mysite 2.配置 (1)模板配置 (2)静态文件配置 (3)csrf隐藏 3.路由关系 一个url对应一个函数 ...

  7. [LeetCode] Race Car 赛车

    Your car starts at position 0 and speed +1 on an infinite number line.  (Your car can go into negati ...

  8. synchronized 与 volatile 原理 —— 内存屏障的重要实践

    单例模式的双重校验锁的实现: 第一种: private static Singleton _instance; public static synchronized Singleton getInst ...

  9. git常用方法整理

    Git是什么? Git是目前世界上最先进的分布式版本控制系统(没有之一). Git有什么特点?简单来说就是:高端大气上档次! 初始化本地仓库 mkdir xxx cd xxx git init 创建本 ...

  10. linux 使用sh@d0ws0cks client

    Linux Centos7下安装使用Shadowsocks客户端,实现*** 准备 SS: 搭建一个可以连接外网的服务器 教程可见 自己动手搭梯子 服务器:本人用的腾讯云服务器,系统为Centos7 ...