如何实现 ASP.NET Core WebApi 的版本化

开发 前端
Web API 的版本化可以尽量保证在相同url情况下保留一个 api 的多个版本,通常一个 webapi 会有多个client,这些client包括:app,web,html5,crawl 等等同构或者异构的平台。

[[373697]]

本文转载自微信公众号「 码农读书」,作者 码农读书 。转载本文请联系 码农读书公众号。

 Web API 的版本化可以尽量保证在相同url情况下保留一个 api 的多个版本,通常一个 webapi 会有多个client,这些client包括:app,web,html5,crawl 等等同构或者异构的平台,当 api 升级之后,往往升级前的 api 也得保留,当维护两个api的时候就是一个不小的挑战,毕竟还是存在一些 client 用户需要访问老的api,这时候就需要将 webapi 版本化。

安装 Versioning 包

要想使用 webapi 的版本化功能,需要用 nuget 引用 Microsoft.AspNetCore.Mvc.Versioning 包,还可以通过 Visual Studio 2019 的 NuGet package manager 可视化界面安装 或者 通过 NuGet package manager 命令行工具输入以下命令:

  1. dotnet add package Microsoft.AspNetCore.Mvc.Versioning 

启动 API 版本化

当包成功添加到项目之后,接下来就可以在 Startup.ConfigureServices 中将 ApiVersioning 注入到容器中,如下代码所示:

  1. public class Startup 
  2.     { 
  3.         public void ConfigureServices(IServiceCollection services) 
  4.         { 
  5.             services.AddControllers(); 
  6.  
  7.             services.AddApiVersioning(); 
  8.         } 
  9.     } 

在调用 AddApiVersioning() 的时候记得 using Microsoft.AspNetCore.Mvc.Versioning,除了这个默认方法,还可以做一些全局配置,如下代码所示:

  1. public class Startup 
  2.     { 
  3.         public void ConfigureServices(IServiceCollection services) 
  4.         { 
  5.             services.AddControllers(); 
  6.  
  7.             services.AddApiVersioning(v => 
  8.             { 
  9.                 v.ReportApiVersions = true
  10.                 v.AssumeDefaultVersionWhenUnspecified = true
  11.                 v.DefaultApiVersion = new ApiVersion(1, 0); 
  12.             }); 
  13.         } 
  14.     } 

使用 QueryString 指定版本号

先来看一下代码,考虑如下的 api。

  1. [ApiController] 
  2.     [ApiVersion("2.0")] 
  3.     [Route("api/[controller]")] 
  4.     public class WeatherForecastController : ControllerBase 
  5.     { 
  6.         private static readonly string[] Summaries = new[] 
  7.         { 
  8.             "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching" 
  9.         }; 
  10.  
  11.         [HttpGet] 
  12.         public IEnumerable<WeatherForecast> Get() 
  13.         { 
  14.             var rng = new Random(); 
  15.             return Enumerable.Range(1, 5).Select(index => new WeatherForecast 
  16.             { 
  17.                 Date = DateTime.Now.AddDays(index), 
  18.                 TemperatureC = rng.Next(-20, 55), 
  19.                 Summary = Summaries[rng.Next(Summaries.Length)] 
  20.             }) 
  21.             .ToArray(); 
  22.         } 
  23.     } 

从代码中可以看到,我在 WeatherForecastController 上标记了该 Controller 是 v2.0 版本,接下来如何访问呢?可以通过如下链接: http://localhost:61582/api/weatherforecast?api-version=2.0

看到这里,有些朋友就有疑问了,v2.0 的 Get 是有了,那 v1.0 的 Get 怎么访问呢?实际开发中的做法是这样的,会用两个命名空间来表示相应的版本号,可以看如下代码:

  1. namespace WebApplication6.Controllers.v1 
  2.     [ApiController] 
  3.     [ApiVersion("1.0")] 
  4.     [Route("api/[controller]")] 
  5.     public class WeatherForecastController : ControllerBase 
  6.     { 
  7.         private static readonly string[] Summaries = new[] 
  8.         { 
  9.             "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching" 
  10.         }; 
  11.  
  12.         private readonly ILogger<WeatherForecastController> _logger; 
  13.  
  14.         public WeatherForecastController(ILogger<WeatherForecastController> logger) 
  15.         { 
  16.             _logger = logger; 
  17.         } 
  18.  
  19.         [HttpGet] 
  20.         public IEnumerable<WeatherForecast> Get() 
  21.         { 
  22.             var rng = new Random(); 
  23.             return Enumerable.Range(1, 5).Select(index => new WeatherForecast 
  24.             { 
  25.                 Date = DateTime.Now.AddDays(index), 
  26.                 TemperatureC = rng.Next(-20, 55), 
  27.                 Summary = Summaries[rng.Next(Summaries.Length)] 
  28.             }) 
  29.             .ToArray(); 
  30.         } 
  31.     } 
  32.  
  33.  
  34. namespace WebApplication6.Controllers.v2 
  35.     [ApiController] 
  36.     [ApiVersion("2.0")] 
  37.     [Route("api/[controller]")] 
  38.     public class WeatherForecastController : ControllerBase 
  39.     { 
  40.         private static readonly string[] Summaries = new[] 
  41.         { 
  42.             "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching" 
  43.         }; 
  44.  
  45.         private readonly ILogger<WeatherForecastController> _logger; 
  46.  
  47.         public WeatherForecastController(ILogger<WeatherForecastController> logger) 
  48.         { 
  49.             _logger = logger; 
  50.         } 
  51.  
  52.         [HttpGet] 
  53.         public IEnumerable<WeatherForecast> Get() 
  54.         { 
  55.             var rng = new Random(); 
  56.             return Enumerable.Range(1, 5).Select(index => new WeatherForecast 
  57.             { 
  58.                 Date = DateTime.Now.AddDays(index), 
  59.                 TemperatureC = rng.Next(-20, 55), 
  60.                 Summary = Summaries[rng.Next(Summaries.Length)] 
  61.             }) 
  62.             .ToArray(); 
  63.         } 
  64.     } 

从上面代码可以看到 WebApplication6.Controllers.v1 表示版本 v1.0 , WebApplication6.Controllers.v2 表示版本 v2.0,接下来依次浏览这两个url。

使用 routes 指定版本号

很显然使用 QueryString 的方式不是很优雅也不符合 Restful 规范,接下来看一下如何通过 Route 改造,考虑下面的类,请注意我是如何在 route 中进行版本化的。

  1. [ApiController] 
  2.    [ApiVersion("1.0")] 
  3.    [Route("api/v{version:apiVersion}/[controller]")] 
  4.    public class WeatherForecastController : ControllerBase 
  5.    { 
  6.        private static readonly string[] Summaries = new[] 
  7.        { 
  8.            "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching" 
  9.        }; 
  10.  
  11.        [HttpGet] 
  12.        public IEnumerable<WeatherForecast> Get() 
  13.        { 
  14.            var rng = new Random(); 
  15.            return Enumerable.Range(1, 5).Select(index => new WeatherForecast 
  16.            { 
  17.                Date = DateTime.Now.AddDays(index), 
  18.                TemperatureC = rng.Next(-20, 55), 
  19.                Summary = Summaries[rng.Next(Summaries.Length)] 
  20.            }) 
  21.            .ToArray(); 
  22.        } 
  23.    } 

在这里,我将 [Route("api/[controller]")] 替换成了 [Route("api/v{version:apiVersion}/[controller]")],接下来将项目跑起来,如下图所示:

忽略 API 版本

在 API 版本化时,有些 API 可能只有一个版本的需求,这时候可以使用 ApiVersionNeutral 特性来忽视版本化,如下代码所示:

  1. [ApiVersionNeutral] 
  2.     [Route("api/[controller]")] 
  3.     [ApiController] 
  4.     public class WeatherForecastController : ControllerBase 
  5.     { 
  6.         private static readonly string[] Summaries = new[] 
  7.         { 
  8.             "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching" 
  9.         }; 
  10.  
  11.         [HttpGet] 
  12.         public IEnumerable<WeatherForecast> Get() 
  13.         { 
  14.             var rng = new Random(); 
  15.             return Enumerable.Range(1, 5).Select(index => new WeatherForecast 
  16.             { 
  17.                 Date = DateTime.Now.AddDays(index), 
  18.                 TemperatureC = rng.Next(-20, 55), 
  19.                 Summary = Summaries[rng.Next(Summaries.Length)] 
  20.             }) 
  21.             .ToArray(); 
  22.         } 
  23.     } 

译文链接:https://www.infoworld.com/article/3433156/advanced-versioning-in-aspnet-core-web-api.html

 

责任编辑:武晓燕 来源: 码农读书
相关推荐

2021-03-04 11:10:29

容器化Docker虚拟机

2021-01-15 05:38:28

ASPHttp端口

2021-01-13 07:33:41

API数据安全

2009-07-23 10:31:14

2021-03-17 09:45:31

LazyCacheWindows

2021-11-01 14:52:38

ElasticSear索引SQL

2021-02-02 16:19:08

Serilog日志框架

2021-02-06 21:40:13

SignalR通讯TypeScript

2021-03-10 09:40:43

LamarASP容器

2021-01-07 07:39:07

工具接口 Swagger

2021-02-03 13:35:25

ASPweb程序

2021-01-28 22:39:35

LoggerMessa开源框架

2021-02-28 20:56:37

NCache缓存框架

2021-01-31 22:56:50

FromServiceASP

2021-03-03 22:37:16

MediatR中介者模式

2021-02-19 06:54:33

配置系统ASP.NET Cor

2018-08-20 08:03:46

跨平台 Web操作系统

2021-03-18 07:33:54

PDF DinkToPdfC++

2021-02-07 17:29:04

监视文件接口

2021-04-14 07:35:12

Json格式化日期
点赞
收藏

51CTO技术栈公众号