原文链接: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. django自制后台左侧导航代码

    自定义一个sort.py页面: 写入一下代码: class lanmusort(object): def __init__(self): self.arr=[] def lanmuget(self,o ...

  2. PHP调用微博接口实现微博登录的方法示例

    在平时项目开发过程中,除了注册本网站账号进行登录之外,还可以调用第三方接口进行登录网站.这里以微博登录为例.微博登录包括身份认证.用户关系以及内容传播.允许用户使用微博帐号登录访问第三方网站,分享内容 ...

  3. Hadoop namenode节点无法启动的问题解决

    namenode是Hadoop集群HDFS的管理节点,管理着整个分布式文件系统的命名空间,以及文件与块的映射关系等,在Hadoop集群中扮演着至关重要的作用. 我之前安装的Hadoop集群中namen ...

  4. Linux正则表达式练习

    练习一 1.生成30位的随机口令 [root@centos7 ~]#cat /dev/urandom | tr -dc "[:alnum:]" | head -c30 RJL5qc ...

  5. 微信小程序开发---自定义组件

    开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用:也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护.自定义组件在使用时与基础组件非常相似. 创建自定义组件 类似于页面, ...

  6. javaWeb+servlet+mysql实现简单的企业员工管理系统

    企业员工信息管理系统 一.源码描述       本程序为企业员工信息管理系统.是javaEE一个系统,主要实现登录功能和两个模块信息的增删改查.可以作为JAVAweb学习,也可在原有基础上进行深一步的 ...

  7. Cmd命令 查看端口被占用

    1)第一步 打开cmd命令窗口,输入命令:netstat -ano|findstr 输入端口号 2)第二步 继续输入命令:tasklist|findstr  第一步查询到的进程号 3)第三步 根据第二 ...

  8. Python基础之变量作用域

    一.分类: 二.变量名的查找规则: 三.局部变量: 四.全局变量: 五.global语句: 六.nonlocal语句: 七.基础代码: # 全局变量:当前.py文件内部都可访问 g01 = 100 d ...

  9. layui 表格内容显示更改

    在cole 中使用temple 属性进行修改 例: table.render({ elem: '#messageTable' ,id: 'search_table_mId' ,height: 500 ...

  10. ubuntu connect to windows folder share

    在windows上给远程登录的用户设置一个账号密码.”右击计算机图标“——"管理”——“本地用户和组”——“用户”.然后右击选择“新用户”,输入账号密码,并勾选“密码永不过期”,这样,在远程 ...