在後端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
功能還能強大的,基本知足了大部分的需求,還有一些功能可能沒有在本文中涉及到,能夠去這裏.翻閱。