应用是演进的,通常我们用版本号来管理。api也是演进的,这篇博文就说说asp.net web api演进时的版本管理。
asp.net web api的版本管理是通过微软的一个包来实现的。
Install-Package Microsoft.AspNetCore.Mvc.Versioning
通过url参数: api/order/api-version=2.0
在startup中注入ApiVersion
public void ConfigureServices(IServiceCollection services) { services.AddApiVersioning(); services.AddControllers(); }
在ProductController中标注版本特性
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace APIVersionDemo.Controllers { [ApiController] [Route("api/[controller]")] [ApiVersion("1.0", Deprecated = true)] [ApiVersion("2.0")] public class ProductController : ControllerBase { private readonly ILogger<ProductController> _logger; public ProductController(ILogger<ProductController> logger) { _logger = logger; } //1.0的api [HttpGet("{id}")] public Product QueryProduct([FromRoute] int id) { _logger.LogInformation("v1.0查询产品"); return new Product() { ID = id, Name = "A物品", Price = 100.20m }; } //2.0的api [HttpGet("{id}")] [MapToApiVersion("2.0")] public Product QueryProductv2([FromRoute] int id) { _logger.LogInformation("v2.0查询产品"); return new Product2() { ID = id, Name = "A物品", Price = 100.20m, Description = "产自山西" }; } } /// <summary> /// 1.0的产品类 /// </summary> public class Product { public int ID { get; set; } public string Name { get; set; } public decimal Price { get; set; } } /// <summary> /// 2.0的产品类 /// </summary> public class Product2 : Product { public string Description { get; set; } } }
通过http://localhost:5000/api/product/1?api-version=2.0方式访问不同的版本。显而易见,这种通过在请求url末尾加参数的方式有点啰嗦。
通过MediaType:{Accept:application/json;version=2.0}或header:{version:2.0}
修改startup的apiversion注入参数
public void ConfigureServices(IServiceCollection services) { services.AddApiVersioning(opt => { opt.AssumeDefaultVersionWhenUnspecified = true; opt.DefaultApiVersion = new ApiVersion(1, 0); opt.ApiVersionReader = ApiVersionReader.Combine( new MediaTypeApiVersionReader("version"), new HeaderApiVersionReader("api-version") ); opt.ReportApiVersions = true; }); services.AddControllers(); }
ProductController不变。
请求http://localhost:5000/api/product/1,header参数,可以适配两种方式:Accept : application/json;version=2.0api-version : 2.0
这样方便客户端请求的整体处理。
通过url:api/v2.0/order
strartup.cs注入apiversion
public void ConfigureServices(IServiceCollection services) { services.AddApiVersioning(); services.AddControllers(); }
这里引入OrderController,在Route特性上改变url,在url里增加版本信息{version:apiVersion}
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace APIVersionDemo.Controllers { [ApiController] [Route("api/v{version:apiVersion}/[controller]")] [ApiVersion("1.0", Deprecated = true)] [ApiVersion("2.0")] public class OrderController : ControllerBase { private readonly ILogger<OrderController> _logger; public OrderController(ILogger<OrderController> logger) { _logger = logger; } //v1订单api [HttpGet("{id}")] public Order QueryOrder() { _logger.LogInformation("v1查询产品"); return new Order() { OrderID = 1, Products = new List<Product>() { new Product() { ID = 1, Name = "A物品", Price = 100.20m } } }; } //v2订单api [HttpGet("{id}")] [MapToApiVersion("2.0")] public Order2 QueryOrder2() { _logger.LogInformation("v2查询产品"); return new Order2() { OrderID = 1, Products = new List<Product2>() { new Product2() { ID = 1, Name = "A物品", Price = 100.20m, Description = "产自山西" } } }; } } //v1订单类 public class Order { public int OrderID { get; set; } public List<Product> Products { get; set; } } //v2订单类 public class Order2 { public int OrderID { get; set; } public List<Product2> Products { get; set; } } }
这时请求就变成http://localhost:5000/api/v2.0/order了,可以通过不同的url来访问不同的api版本,这种方式也有利于客户端统一配置baseurl,来切换请求api版本。
最后,apiversion这个包还带来了一个无侵入controller的方式来配置api的版本,本质与加在Controller上的特性信息是一致的——附加版本信息和对应关系。
services.AddApiVersioning(opt => { opt.Conventions.Controller<ProductController>() .HasApiVersion(2, 0) .HasDeprecatedApiVersion(1, 0) .Action(typeof(ProductController) .GetMethod(nameof(ProductController.QueryProductv2))!) .MapToApiVersion(2, 0); });
想要更快更方便的了解相关知识,可以关注微信公众号