如何實(shí)現(xiàn) ASP.NET Core WebApi 的版本化
本文轉(zhuǎn)載自微信公眾號(hào)「 碼農(nóng)讀書(shū)」,作者 碼農(nóng)讀書(shū) 。轉(zhuǎn)載本文請(qǐng)聯(lián)系 碼農(nóng)讀書(shū)公眾號(hào)。
Web API 的版本化可以盡量保證在相同url情況下保留一個(gè) api 的多個(gè)版本,通常一個(gè) webapi 會(huì)有多個(gè)client,這些client包括:app,web,html5,crawl 等等同構(gòu)或者異構(gòu)的平臺(tái),當(dāng) api 升級(jí)之后,往往升級(jí)前的 api 也得保留,當(dāng)維護(hù)兩個(gè)api的時(shí)候就是一個(gè)不小的挑戰(zhàn),畢竟還是存在一些 client 用戶(hù)需要訪(fǎng)問(wèn)老的api,這時(shí)候就需要將 webapi 版本化。
安裝 Versioning 包
要想使用 webapi 的版本化功能,需要用 nuget 引用 Microsoft.AspNetCore.Mvc.Versioning 包,還可以通過(guò) Visual Studio 2019 的 NuGet package manager 可視化界面安裝 或者 通過(guò) NuGet package manager 命令行工具輸入以下命令:
- dotnet add package Microsoft.AspNetCore.Mvc.Versioning
 
啟動(dòng) API 版本化
當(dāng)包成功添加到項(xiàng)目之后,接下來(lái)就可以在 Startup.ConfigureServices 中將 ApiVersioning 注入到容器中,如下代碼所示:
- public class Startup
 - {
 - public void ConfigureServices(IServiceCollection services)
 - {
 - services.AddControllers();
 - services.AddApiVersioning();
 - }
 - }
 
在調(diào)用 AddApiVersioning() 的時(shí)候記得 using Microsoft.AspNetCore.Mvc.Versioning,除了這個(gè)默認(rèn)方法,還可以做一些全局配置,如下代碼所示:
- public class Startup
 - {
 - public void ConfigureServices(IServiceCollection services)
 - {
 - services.AddControllers();
 - services.AddApiVersioning(v =>
 - {
 - v.ReportApiVersions = true;
 - v.AssumeDefaultVersionWhenUnspecified = true;
 - v.DefaultApiVersion = new ApiVersion(1, 0);
 - });
 - }
 - }
 
使用 QueryString 指定版本號(hào)
先來(lái)看一下代碼,考慮如下的 api。
- [ApiController]
 - [ApiVersion("2.0")]
 - [Route("api/[controller]")]
 - public class WeatherForecastController : ControllerBase
 - {
 - private static readonly string[] Summaries = new[]
 - {
 - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
 - };
 - [HttpGet]
 - public IEnumerable<WeatherForecast> Get()
 - {
 - var rng = new Random();
 - return Enumerable.Range(1, 5).Select(index => new WeatherForecast
 - {
 - Date = DateTime.Now.AddDays(index),
 - TemperatureC = rng.Next(-20, 55),
 - Summary = Summaries[rng.Next(Summaries.Length)]
 - })
 - .ToArray();
 - }
 - }
 
從代碼中可以看到,我在 WeatherForecastController 上標(biāo)記了該 Controller 是 v2.0 版本,接下來(lái)如何訪(fǎng)問(wèn)呢?可以通過(guò)如下鏈接: http://localhost:61582/api/weatherforecast?api-version=2.0
看到這里,有些朋友就有疑問(wèn)了,v2.0 的 Get 是有了,那 v1.0 的 Get 怎么訪(fǎng)問(wèn)呢?實(shí)際開(kāi)發(fā)中的做法是這樣的,會(huì)用兩個(gè)命名空間來(lái)表示相應(yīng)的版本號(hào),可以看如下代碼:
- namespace WebApplication6.Controllers.v1
 - {
 - [ApiController]
 - [ApiVersion("1.0")]
 - [Route("api/[controller]")]
 - public class WeatherForecastController : ControllerBase
 - {
 - private static readonly string[] Summaries = new[]
 - {
 - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
 - };
 - private readonly ILogger<WeatherForecastController> _logger;
 - public WeatherForecastController(ILogger<WeatherForecastController> logger)
 - {
 - _logger = logger;
 - }
 - [HttpGet]
 - public IEnumerable<WeatherForecast> Get()
 - {
 - var rng = new Random();
 - return Enumerable.Range(1, 5).Select(index => new WeatherForecast
 - {
 - Date = DateTime.Now.AddDays(index),
 - TemperatureC = rng.Next(-20, 55),
 - Summary = Summaries[rng.Next(Summaries.Length)]
 - })
 - .ToArray();
 - }
 - }
 - }
 - namespace WebApplication6.Controllers.v2
 - {
 - [ApiController]
 - [ApiVersion("2.0")]
 - [Route("api/[controller]")]
 - public class WeatherForecastController : ControllerBase
 - {
 - private static readonly string[] Summaries = new[]
 - {
 - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
 - };
 - private readonly ILogger<WeatherForecastController> _logger;
 - public WeatherForecastController(ILogger<WeatherForecastController> logger)
 - {
 - _logger = logger;
 - }
 - [HttpGet]
 - public IEnumerable<WeatherForecast> Get()
 - {
 - var rng = new Random();
 - return Enumerable.Range(1, 5).Select(index => new WeatherForecast
 - {
 - Date = DateTime.Now.AddDays(index),
 - TemperatureC = rng.Next(-20, 55),
 - Summary = Summaries[rng.Next(Summaries.Length)]
 - })
 - .ToArray();
 - }
 - }
 - }
 
從上面代碼可以看到 WebApplication6.Controllers.v1 表示版本 v1.0 , WebApplication6.Controllers.v2 表示版本 v2.0,接下來(lái)依次瀏覽這兩個(gè)url。
使用 routes 指定版本號(hào)
很顯然使用 QueryString 的方式不是很優(yōu)雅也不符合 Restful 規(guī)范,接下來(lái)看一下如何通過(guò) Route 改造,考慮下面的類(lèi),請(qǐng)注意我是如何在 route 中進(jìn)行版本化的。
- [ApiController]
 - [ApiVersion("1.0")]
 - [Route("api/v{version:apiVersion}/[controller]")]
 - public class WeatherForecastController : ControllerBase
 - {
 - private static readonly string[] Summaries = new[]
 - {
 - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
 - };
 - [HttpGet]
 - public IEnumerable<WeatherForecast> Get()
 - {
 - var rng = new Random();
 - return Enumerable.Range(1, 5).Select(index => new WeatherForecast
 - {
 - Date = DateTime.Now.AddDays(index),
 - TemperatureC = rng.Next(-20, 55),
 - Summary = Summaries[rng.Next(Summaries.Length)]
 - })
 - .ToArray();
 - }
 - }
 
在這里,我將 [Route("api/[controller]")] 替換成了 [Route("api/v{version:apiVersion}/[controller]")],接下來(lái)將項(xiàng)目跑起來(lái),如下圖所示:
忽略 API 版本
在 API 版本化時(shí),有些 API 可能只有一個(gè)版本的需求,這時(shí)候可以使用 ApiVersionNeutral 特性來(lái)忽視版本化,如下代碼所示:
- [ApiVersionNeutral]
 - [Route("api/[controller]")]
 - [ApiController]
 - public class WeatherForecastController : ControllerBase
 - {
 - private static readonly string[] Summaries = new[]
 - {
 - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
 - };
 - [HttpGet]
 - public IEnumerable<WeatherForecast> Get()
 - {
 - var rng = new Random();
 - return Enumerable.Range(1, 5).Select(index => new WeatherForecast
 - {
 - Date = DateTime.Now.AddDays(index),
 - TemperatureC = rng.Next(-20, 55),
 - Summary = Summaries[rng.Next(Summaries.Length)]
 - })
 - .ToArray();
 - }
 - }
 
譯文鏈接:https://www.infoworld.com/article/3433156/advanced-versioning-in-aspnet-core-web-api.html



















 
 
 


 
 
 
 