在后端Api的开发过程当中,没法避免的会遇到接口迭代的过程,如何保证新老接口的共存和接口的向前的兼容呢,这时候就须要对Api进行版本的控制,那如何优雅的控制Api的版本呢?git
Microsoft.AspNetCore.Mvc.Versioning
是一个微软官方推出的一个用于管理Api版本的包,配置简单,功能强大。 github地址.github
新建一个WebApi项目并经过命令引用包。后端
Install-Package Microsoft.AspNetCore.Mvc.Versioning
api
最新版本已经支持Core3.1post
项目结构以下测试
在 Startup
的 ConfigureServices
中增长一下配置。url
services.AddApiVersioning(options => { options.ReportApiVersions = true; options.AssumeDefaultVersionWhenUnspecified = true; options.DefaultApiVersion = new ApiVersion(1, 0); });
分别在两个不一样的Controller
中添加一个获取版本信息的接口spa
namespace version.Controllers.v1 { [ApiVersion("1.0")] [ApiController] [Route("api/[controller]")] public class ValuesController : Controller { [HttpGet("version")] public string Version() => (HttpContext.GetRequestedApiVersion().ToString()); } }
namespace version.Controllers.v2 { [ApiVersion("2.0")] [ApiController] [Route("api/[controller]")] public class ValuesController : Controller { [HttpGet("version")] public string Version() => (HttpContext.GetRequestedApiVersion().ToString()); } }
HttpContext.GetRequestedApiVersion().ToString()
是用于获取请求接口的版本信息。版本控制
咱们经过postman来请求这两个接口当咱们没有给到具体请求哪一个版本的时候会根据在ConfigureServices
中配置的默认版本去执行。code
指定版本请求结果
在响应头中会显示当前支持的全部的Api版本
通常在Api开发中不会去QueryString的方式去进行版本控制,而是使用URL路径段的方式来控制版本。
修改两个Controller
中的代码以下。
namespace version.Controllers.v1 { [ApiVersion("1.0")] [ApiController] [Route("api/v{version:ApiVersion}/[controller]")] public class ValuesController : Controller { [HttpGet("version")] public string Version() => (HttpContext.GetRequestedApiVersion().ToString()); } }
namespace version.Controllers.v2 { [ApiVersion("2.0")] [ApiController] [Route("api/v{version:ApiVersion}/[controller]")] public class ValuesController : Controller { [HttpGet("version")] public string Version() => (HttpContext.GetRequestedApiVersion().ToString()); } }
经过postman进行测试
能够看到当咱们使用指定的版本是能够正常访问的时候,可是若是咱们去掉了Api版本号就会抛出404,并不能像QueryString同样调用默认的Api版本,由于URL Path的方式不容许隐式匹配设置的默认Api版本。因此必须申明全部的Api版本。且在请求Api同时必须带上Api版本号。
咱们还可使用content-type
来实现版本的控制
修改ConfigureServices
中的配置
services.AddApiVersioning(options => { options.ApiVersionReader = new MediaTypeApiVersionReader(); options.AssumeDefaultVersionWhenUnspecified = true; options.ApiVersionSelector = new CurrentImplementationApiVersionSelector(options); });
CurrentImplementationApiVersionSelector
若是没有在content-type中传递Api版本好,将默认匹配最新的Api版本
分别修改两个Controller
namespace version.Controllers.v1 { [ApiVersion("1.0")] [ApiController] [Route("api/[controller]")] public class ValuesController : Controller { [HttpGet("version")] public string Version() => (HttpContext.GetRequestedApiVersion().ToString()); } }
namespace version.Controllers.v2 { [ApiVersion("2.0")] [ApiController] [Route("api/[controller]")] public class ValuesController : Controller { [HttpGet("version")] public string Version() => (HttpContext.GetRequestedApiVersion().ToString()); } }
使用Postman测试
修改ConfigureServices
中的配置
services.AddControllers(); services.AddApiVersioning(options => { options.ReportApiVersions = true; options.ApiVersionReader = new HeaderApiVersionReader("api_version"); options.AssumeDefaultVersionWhenUnspecified = true; options.DefaultApiVersion = new ApiVersion(1, 0); });
api_version
是你Headers中Key的名字。
使用Postman测试
当哪一个Api版本不在更新,就须要弃用掉这个版本。当Deprecated
值为true
时说明该Api版本已经已经弃用,可是弃用不表明不能请求。只是会在响应头中告知次版本已经已经弃用。
namespace version.Controllers.v1 { [ApiVersion("1.0",Deprecated= true)] [ApiController] [Route("api/[controller]")] public class ValuesController : Controller { [HttpGet("version")] public string Version() => (HttpContext.GetRequestedApiVersion().ToString()); } }
项目总有一些功能是不须要版本的控制,因此咱们但愿它不受版本控制。能够添加[ApiVersionNeutral]
特性使Api支持版本控制。
namespace version.Controllers.v1 { [ApiVersionNeutral] [ApiController] [Route("api/[controller]")] public class ValuesController : Controller { [HttpGet("version")] public string Version() => (HttpContext.GetRequestedApiVersion().ToString()); } }
MapToApiVersion
能够将单个Api归类于任何版本。在一个Controller
中能够存在多个版本的Api。咱们能够配合Deprecated
来灵活的控制咱们的Api。
namespace version.Controllers.v1 { [ApiVersion("3.0")] [ApiVersion("1.0",Deprecated= true)] [ApiController] [Route("api/v{version:ApiVersion}/[controller]")] public class ValuesController : Controller { [HttpGet("version"), MapToApiVersion("1.0")] public string Version() => (HttpContext.GetRequestedApiVersion().ToString()); [HttpGet("version3"), MapToApiVersion("3.0")] public string Version3() => (HttpContext.GetRequestedApiVersion().ToString()); } }
经过postman测试一下。
能够看到Microsoft.AspNetCore.Mvc.Versioning
功能还能强大的,基本知足了大部分的需求,还有一些功能可能没有在本文中涉及到,能够去这里.翻阅。