在nuget.org上,您可以找到 Microsoft.AspNetCore.Mvc.Versioning包,它提供了有關如何對Web API端點進行版本化的更多選項。這個包的好處是允許你直接在控制器上使用帶參數的屬性,因此使用起來非常方便。
另一個好處是您可以選擇向客戶端報告它不支持嘗試調用的版本。在Startup.cs類中添加versionign服務時,只需啟用此選項即可
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddApiVersioning(o => o.ReportApiVersions = true); }
如果您剛開始對API進行版本控制並且到目前為止還沒有版本標識,那么您也可以設置默認版本控制。所有沒有版本控制數據的請求
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddApiVersioning(o => { o.ReportApiVersions = true; o.AssumeDefaultVersionWhenUnspecified = true; o.DefaultApiVersion = new ApiVersion(1,0); }); }
注意
確保您的默認版本未在控制器上標記為已棄用,並且您的客戶端調用不會被控制器上版本控制屬性聲明的版本控制策略拒絕
讓我們從不同版本控制選項的一些代碼示例和設置開始,看看在實踐中所有這些都是如此。
基於參數的版本控制
開箱即用支持查詢字符串版本控制,因此通過發送api-version = 1.0,我們告訴應用程序以版本屬性1.0路由到控制器
namespace Core.Versioning.Sample.Controllers { [ApiVersion("1.0")] [Route("api/[controller]")] public class ValueController : Controller { [HttpGet] public String Get() { return "Version 1.0"; } } }
要添加新版本,我們可以在具有ApiVersion屬性的不同命名空間內將相同的控制器名稱添加到新版本
namespace Core.Versioning.Sample.Controllers.v2 { [ApiVersion("2.0")] [ApiVersion("1.0", Deprecated = true)] [Route("api/[controller]")] public class ValueController : Controller { [HttpGet] public String Get() { return "Version 2.0"; } } }
現在讓我們'測試不同api-version參數值的響應
$ curl http:// localhost:5000 / api / value?api-version = 1.0 -iHTTP / 1.1 200 OK
日期:星期四,2018年6月14日08:11:13 GMT
內容類型:text / plain; charset = utf-8
服務器:Kestrel
Transfer-Encoding:chunked
api-supported-versions:1.0,2.0
Version 1.0
對於2.0版本,響應會有所不同
$ curl http:// localhost:5000 / api / value?api-version = 2.0 -i
HTTP / 1.1 200 OK
日期:星期四,2018年6月14日08:11:19 GMT
內容類型:text / plain; charset = utf-8
服務器:Kestrel
Transfer-Encoding:chunked
api-supported-versions:1.0,2.0
現在我將嘗試使用不受支持的3.0版調用API。讓我們看看在這種情況下會發生什么
$ curl http:// localhost:5000 / api / value?api-version = 3.0 -i
HTTP / 1.1 400 Bad Request
Date:Thu,14 Jun 2018 08:16:12 GMT
Content-Type:application / json; charset = utf-8
服務器:Kestrel
Transfer-Encoding:chunked
api-supported-versions:1.0,2.0
{
“error”:{
“code”:“UnsupportedApiVersion”,
“message”:“與請求URI匹配的HTTP資源” http:// localhost:5000 / api / value?api-version = 3.0'不支持API版本'3.0'。“,
”innerError“:null
}
}
您看到響應代碼不是200 OK,但400 Bad Request with JSON消息表明此版本不受支持。
基於標題的版本控制
如果將版本作為查詢字符串值發送到Web API端點不夠好,則可以使用標頭。對於這種版本控制方式,您需要在Startup.cs 文件中進行一些小的更改, 以告知版本控制包在特定鍵的標頭中查找版本值。我選擇使用與我用於api-version的查詢字符串相同的方法
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddApiVersioning(o => { o.ReportApiVersions = true; o.AssumeDefaultVersionWhenUnspecified = true; o.DefaultApiVersion = new ApiVersion(1,0); o.ApiVersionReader = new HeaderApiVersionReader(“api-version”); }); }
您可以 通過在請求標頭中添加api-version值,使用POSTMAN輕松測試 。使用此方法,您將始終使用具有不同請求標頭值的相同端點URL來訪問不同版本的端點。
為了進行快速測試以確認這是有效的,讓我們在標題中調用2.0版本的API
$ curl --header“api-version:2.0”http:// localhost:5000 / api / value -i
HTTP / 1.1 200 OK
日期:星期四,2018年6月14日08:27:49 GMT
內容類型:text / plain ; charset = utf-8
服務器:Kestrel
Transfer-Encoding:chunked
api-supported-versions:1.0,2.0
Version 2.0
基於路由的版本控制
基於路由的版本控制基於控制器的url結構,並期望路由包含版本。為此,我們需要將Startup.cs更改為不再從標題中讀取,而是查看URL
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddApiVersioning(o => { o.ReportApiVersions = true; o.AssumeDefaultVersionWhenUnspecified = true; o.DefaultApiVersion = new ApiVersion(1,0); o.ApiVersionReader = new UrlSegmentApiVersionReader(); }); }
為了支持我們設置為1.0的默認版本,我們還需要為沒有版本段的特定版本提供額外的路由,否則默認版本將不起作用
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddApiVersioning(o => { o.ReportApiVersions = true; o.AssumeDefaultVersionWhenUnspecified = true; o.DefaultApiVersion = new ApiVersion(1, 0); o.ApiVersionReader = new HeaderApiVersionReader("api-version"); }); }
這里感謝LamondLu的博客,其HeaderApiVersionReader已經淘汰,應該如以下代碼:
services.AddApiVersioning( o => o.ApiVersionReader = ApiVersionReader.Combine( new QueryStringApiVersionReader(), new HeaderApiVersionReader() { Headers = { "api-version" } } ) );
您可以 通過在請求標頭中添加api-version值,使用POSTMAN輕松測試 。使用此方法,您將始終使用具有不同請求標頭值的相同端點URL來訪問不同版本的端點。
為了進行快速測試以確認這是有效的,讓我們在標題中調用2.0版本的API
$ curl --header“api-version:2.0”http:// localhost:5000 / api / value -i
HTTP / 1.1 200 OK
日期:星期四,2018年6月14日08:27:49 GMT
內容類型:text / plain ; charset = utf-8
服務器:Kestrel
Transfer-Encoding:chunked
api-supported-versions:1.0,2.0
Version 2.0
基於路由的版本控制
基於路由的版本控制基於控制器的url結構,並期望路由包含版本。為此,我們需要將Startup.cs更改為不再從標題中讀取,而是查看URL
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddApiVersioning(o => { o.ReportApiVersions = true; o.AssumeDefaultVersionWhenUnspecified = true; o.DefaultApiVersion = new ApiVersion(1,0); o.ApiVersionReader = new UrlSegmentApiVersionReader(); }); }
為了支持我們設置為1.0的默認版本,我們還需要為沒有版本段的特定版本提供額外的路由,否則默認版本將不起作用
namespace Core.Versioning.Sample.Controllers { [ApiVersion("1.0")] [ApiVersion("1.0", Deprecated = true)] [Route("api/[controller]")] [Route("api/v{version:apiVersion}/[controller]")] public class ValueController : Controller { [HttpGet] public String Get() { return "Version 1.0"; } } } namespace Core.Versioning.Sample.Controllers.v2 { [ApiVersion("2.0")] [Route("api/v{version:apiVersion}/[controller]")] public class ValueController : Controller { [HttpGet] public String Get() { return "Version 2.0"; } } }
現在讓我們用curl檢查響應
$ curl http:// localhost:5000 / api / value -i
HTTP / 1.1 200 OK
日期:星期四,2018年6月14日08:03:34 GMT
內容類型:text / plain; charset = utf-8
服務器:Kestrel
Transfer-Encoding:chunked
api-supported-versions:
1.0,2.0 api-deprecated-versions:1.0
Version 1.0
您可能會注意到響應包含api-deprecated-vesion標頭密鑰設置為1.0。這是因為我們的新控制器具有以下屬性
ApiVersion(“1.0”,Deprecated = true)
這告訴Web API客戶端不再支持1.0版。如果您的REST服務支持來自不同供應商的多個不同客戶端,這可能非常有用。