应用是演进的,通常我们用版本号来管理。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.0
api-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);
});