場景:
任何不斷髮展變化的API都需要API版本控制策略。你的API版本可以適應根據API使用者的期望而切換不同版本變得有所不同。我通常建議將以下API版本控制策略作爲整體API管理系統的一部分。
1.如果你的API處於早期測試版本中,爲了獲得消費者的反饋,請建立您的API可能會發生變化的正確期望。在此階段內,你會保留這個版本一段時間,因爲你的API設計可能還會更改。作爲消費者,API是不穩定的,因此他們應該預期到可能會發生的變化。
2.一旦發佈,你的API應被視爲契約,如果沒有新版本,則不能被替換。
3.不間斷的更改會導致次要版本出現問題,客戶端會自動遷移到最新版本,不會出現任何負面副作用。
4.突破性的變化意味着客戶必須遷移到此新版本,因爲它包含一個或多個重大更改。你必須與API使用者建立適當的時間表並定期溝通,以確保他們能方便地遷移到新版本。但在某些情況下,這可能無法馬上實現,所以你的團隊將會被要求暫時性支持以前的API版本。
實現API版本控制的方法
Install-Package Microsoft.AspNetCore.Mvc.Versioning
在 Startup
的 ConfigureServices
中增加一下配置。然後在Configure方法添加app.UseApiVersioning();
services.AddApiVersioning(o => { //在請求響應標頭(Header)中返回所有的版本信息(默認爲api-supported-versions:1.0,2.0,3.0),可以在下面ApiVersionReader中自定義替代參數名稱 o.ReportApiVersions = true; //此選項將用於不提供版本的請求。默認情況下, 假定的 API 版本爲1.0 o.AssumeDefaultVersionWhenUnspecified = true; //缺省api版本號,支持時間或數字版本號 o.DefaultApiVersion = new ApiVersion(1, 0); //支持MediaType、Header、QueryString 設置版本號;缺省爲QueryString、UrlSegment設置版本號 o.ApiVersionReader = ApiVersionReader.Combine( new MediaTypeApiVersionReader("api-version"), new HeaderApiVersionReader("api-version"),
new QueryStringApiVersionReader("api-version"), new UrlSegmentApiVersionReader()); });
其他參數:
o.ApiVersionSelector可以設置四種值來確定選擇版本的策略
DefaultApiVersionSelector如果請求中沒有指定,則選擇默認版本
CurrentImplementationApiVersionSelector如果請求中沒有指定,則選擇最新的 api 版本
LowestImplementedApiVersionSelector如果請求中沒有指定,則選擇最低的 api 版本
ConstantApiVersionSelector不管請求是否指定, 一直選擇在構造函數中傳遞的常量 api 版本
o.ErrorResponses設置版本匹配錯誤時返回的響應信息
o.RegisterMiddleware默認爲true,可以省略在Configure方法添加app.UseApiVersioning();的代碼
如果控制器不應用[ApiController]的話,需要設置o.UseApiBehavior = false;才能正常工作
(1)通過QueryString進行版本控制
分別在兩個不同的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()); } }
HttpContext.GetRequestedApiVersion().ToString()
是用於獲取請求接口的版本信息。
通過URL Path進行版本控制
一般在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()); } }
不能像QueryString一樣調用默認的Api版本,因爲URL Path的方式不允許隱式匹配設置的默認Api版本。所以必須申明所有的Api版本。且在請求Api同時必須帶上Api版本號。
[Route("api/v{version:ApiVersion}/[controller]")]中的ApiVersion可以通過o.RouteConstraintName = "ApiName";自定義
通過Media Type進行版本控制
我們還可以使用content-type
來實現版本的控制
分別修改兩個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",Deprecated = true)]
[ApiController]
[Route("api/[controller]")]
public class ValuesController : Controller
{
[HttpGet("version")]
public string Version() => (HttpContext.GetRequestedApiVersion().ToString());
}
}
訪問時添加content-type:application/json;v=2.0
Deprecated = true表示API已過時
如果應用[ApiVersionNeutral]則表示此Controller或Action不需要版本控制
MapToApiVersion 用法舉例
[Route("api/v{version:apiVersion}/[controller]")] [ApiVersion("1")] [ApiVersion("3")] public class ValuesController : Controller { [HttpGet] public IEnumerable<string> Get1() { return new string[] {}; } [HttpGet, MapToApiVersion("2"), MapToApiVersion("4")] public IEnumerable<string> Get2() { return new string[] {}; } [HttpGet, MapToApiVersion("5")] public IEnumerable<string> Get3() { return new string[] {}; } }
Get1支持的版本是:1、3;
Get2支持的版本是:2、4;
Get3支持的版本是:5。