Asp.Net Core WebApi 4種版本控制的方式
作者:返回主頁她微笑的臉
https://www.cnblogs.com/linhuiy/p/12668535.html
前言
在后端Api的開發(fā)過程中,無法避免的會遇到接口迭代的過程,如何保證新老接口的共存和接口的向前的兼容呢,這時候就需要對Api進(jìn)行版本的控制,那如何優(yōu)雅的控制Api的版本呢?
開始
Microsoft.AspNetCore.Mvc.Versioning 是一個微軟官方推出的一個用于管理Api版本的包,配置簡單,功能強(qiáng)大。?
新建一個WebApi項(xiàng)目并通過命令引用包。
Install-Package Microsoft.AspNetCore.Mvc.Versioning
最新版本已經(jīng)支持Core3.1
項(xiàng)目結(jié)構(gòu)如下
在 Startup 的 ConfigureServices 中增加一下配置。
services.AddApiVersioning(options?=>
{
????options.ReportApiVersions?=?true;?
????options.AssumeDefaultVersionWhenUnspecified?=?true;?
????options.DefaultApiVersion?=?new?ApiVersion(1,?0);?
});
ReportApiVersions:是否在請求頭中返回受支持的版本信息。
AssumeDefaultVersionWhenUnspecified:請求沒有指明版本的情況下是否使用默認(rèn)的版本。
DefaultApiVersion:默認(rèn)的版本號。
1.通過QueryString進(jìn)行版本控制?
分別在兩個不同的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() 是用于獲取請求接口的版本信息
我們通過postman來請求這兩個接口當(dāng)我們沒有給到具體請求哪個版本的時候會根據(jù)在ConfigureServices中配置的默認(rèn)版本去執(zhí)行。
指定版本請求結(jié)果

在響應(yīng)頭中會顯示當(dāng)前支持的所有的Api版本
2.通過URL Path進(jìn)行版本控制?
一般在Api開發(fā)中不會去QueryString的方式去進(jìn)行版本控制,而是使用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進(jìn)行測試


可以看到當(dāng)我們使用指定的版本是可以正常訪問的時候,但是如果我們?nèi)サ袅薃pi版本號就會拋出404,并不能像QueryString一樣調(diào)用默認(rèn)的Api版本,因?yàn)?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">URL Path的方式不允許隱式匹配設(shè)置的默認(rèn)Api版本。所以必須申明所有的Api版本。且在請求Api同時必須帶上Api版本號。
3.通過Media Type進(jìn)行版本控制?
我們還可以使用content-type來實(shí)現(xiàn)版本的控制
修改ConfigureServices中的配置
services.AddApiVersioning(options?=>
{
????options.ApiVersionReader?=?new?MediaTypeApiVersionReader();
????options.AssumeDefaultVersionWhenUnspecified?=?true;
????options.ApiVersionSelector?=?new?CurrentImplementationApiVersionSelector(options);
});
CurrentImplementationApiVersionSelector 如果沒有在content-type中傳遞Api版本好,將默認(rèn)匹配最新的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測試

4.通過自定義Headers進(jìn)行版本控制?
修改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測試?

特性 當(dāng)哪個Api版本不在更新,就需要棄用掉這個版本。當(dāng)Deprecated值為true時說明該Api版本已經(jīng)已經(jīng)棄用,但是棄用不代表不能請求。只是會在響應(yīng)頭中告知次版本已經(jīng)已經(jīng)棄用。
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());
????}
}

項(xiàng)目總有一些功能是不需要版本的控制,所以我們希望它不受版本控制。可以添加[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測試一下。

總結(jié)
可以看到Microsoft.AspNetCore.Mvc.Versioning功能還能強(qiáng)大的,基本滿足了大部分的需求,還有一些功能可能沒有在本文中涉及到,可以去這里.翻閱。
往期推薦
知乎熱議:28歲程序員期權(quán)過億!這兩天1600人加我好友,問我賺了多少錢?

