只有累積,沒有奇蹟

2021年5月30日 星期日

[NETCore] ASP.NET Core 中加入 API 版本控制

前言
在開發 API 時可能會因為代碼調整或是架構的演進,相同的 API 接口可能會有新的版本出現,為了不影響舊的呼叫端程式邏輯運作,就需要在代碼中加上新舊版本的對應來解決 API 版本問題,或許為了解決 API 版本問題可以有很多種不同的解法,在 ASP.NET Core 中可以透過  Microsoft.AspNetCore.Mvc.Versioning  來解決此問題,這篇就來分享一下有關Microsoft.AspNetCore.Mvc.Versioning 套件的安裝與基本使用,若有問題或是錯誤的地方歡迎網路的高手大大給予指導

安裝
首先直接透過專案的代碼可以方便大家可以更快的了解,起手式先建立一個 ASP.NET Core API 專案來作示範
建立完專案之後第一步是開啟開啟 Nuget Package Mnage 輸入 Microsoft.AspNetCore.Mvc.Versioning  搜尋,安裝目前最新版的套件
或是透過 Nuget Package Console 輸入下列指令
  1. Install-Package Microsoft.AspNetCore.Mvc.Versioning
安裝完畢之後到專案檔底下確認是否有安裝成功
  1. <ItemGroup>
  2. <PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="3.1.3" />
  3. </ItemGroup>

設定 
接著開啟專案中 Startup.cs 的 ConfigureServices 加上下列代碼
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  4. services.AddApiVersioning(o => {
  5. o.ReportApiVersions = true;
  6. o.AssumeDefaultVersionWhenUnspecified = true;
  7. o.DefaultApiVersion = new ApiVersion(1, 0);
  8. });
  9. }
簡單說明一下設定所代表的含意及意義

ReportApiVersions

支援在 API Response Header 中加入 API 支援的版本,讓呼叫端知道目前版本有哪些,舉例來說開啟設定後如下,可以看到目前 API 支援的版本有 1.0 及 2.0 兩種版本

AssumeDefaultVersionWhenUnspecified
當發送的請求未指定 api-version 版本號時,是否需要啟用預設版本號。如果設定為 false 也未指定版本耗時則會出現錯誤訊息 An API version is required, but was not specified.

DefaultApiVersion
預設 API 版本號碼

使用 URL Querystring 指定版本
在此框架中使用  ApiVersion  來區分不同版本 API,接著為了要測試不同版本 API 回傳與設定,在 Controller 中加入下列代碼來驗證
  1. using Microsoft.AspNetCore.Mvc;
  2.  
  3. namespace NetCoreWebAPIVersion.Controllers
  4. {
  5. [ApiController]
  6. [ApiVersion("1.0")]
  7. [Route("api/[controller]")]
  8. public class ValuesController : ControllerBase
  9. {
  10. [HttpGet]
  11. public string Get(ApiVersion apiVersion) => $"Controller = {GetType().Name}\nVersion = {apiVersion}";
  12. }
  13.  
  14. [ApiController]
  15. [ApiVersion("2.0")]
  16. [Route("api/values")]
  17. public class Values2Controller : ControllerBase
  18. {
  19. [HttpGet]
  20. public string Get(ApiVersion apiVersion) => $"Controller = {GetType().Name}\nVersion = {apiVersion}";
  21. }
  22. }
當未指定 API 版本時候,會參考稍早在 startup 中的 AssumeDefaultVersionWhenUnspecified 與 DefaultApiVersion 設定,在此範例中預設為 1.0 版因此可以看到回傳 version 為 1.0

透過上列代碼,可以在 url 帶入 api-version 參數來指定版本,舉例來說要指定版本為 2.0 則帶入 localhost/api/values?api-version=2.0 

使用 URL Route 指定版本 
也支援使用 Route 指定版本號,可以在 Route 加上  Route("api/v{version:api-version}/[controller]  ,根據上述調整做些微調如下
  1. namespace NetCoreWebAPIVersion.ControllersV2
  2. {
  3. [ApiController]
  4. [ApiVersion("1.0")]
  5. [Route("api/v{version:apiVersion}/[controller]")]
  6. public class ValuesController : ControllerBase
  7. {
  8. [HttpGet]
  9. public string Get(ApiVersion apiVersion) => $"Controller = {GetType().Name}\nVersion = {apiVersion}";
  10. }
  11.  
  12. [ApiController]
  13. [ApiVersion("2.0")]
  14. [Route("api/v{version:apiVersion}/values")]
  15. public class Values2Controller : ControllerBase
  16. {
  17. [HttpGet]
  18. public string Get(ApiVersion apiVersion) => $"Controller = {GetType().Name}\nVersion = {apiVersion}";
  19. }
  20. }
使用方式就很簡單,指定 1.0 版本
指定 2.0 版本  
如果需求情境是希望版號加在 Header 中,讓 url 避免透漏過多資訊也乾淨些,則可以在 service 中使用  HeaderApiVersionReader 進行設定,詳細可以參考官網說明。

設定過期 (棄用) 版本
在某些情境下可能早期的 API 版本將不在支援,在此框架中就可以透過設定 Deprecated  讓使用端知道,
舉例來說,下列代碼在 controller 一共有 0.1、1.0以及 2.0 三個版本,其中設定 0.1 版將不在支援,因此在 ApiVersion 中定義 Deprecated = true
  1. namespace NetCoreWebAPIVersion.ControllersV2
  2. {
  3. [ApiController]
  4. [ApiVersion("0.1", Deprecated =true)]
  5. [Route("api/v{version:apiVersion}/[controller]")]
  6. public class Values3Controller : ControllerBase
  7. {
  8. [HttpGet]
  9. public string Get(ApiVersion apiVersion) => $"Controller = {GetType().Name}\nVersion = {apiVersion}";
  10. }
  11.  
  12. [ApiController]
  13. [ApiVersion("1.0")]
  14. [Route("api/v{version:apiVersion}/[controller]")]
  15. public class ValuesController : ControllerBase
  16. {
  17. [HttpGet]
  18. public string Get(ApiVersion apiVersion) => $"Controller = {GetType().Name}\nVersion = {apiVersion}";
  19. }
  20.  
  21. [ApiController]
  22. [ApiVersion("2.0")]
  23. [Route("api/v{version:apiVersion}/values")]
  24. public class Values2Controller : ControllerBase
  25. {
  26. [HttpGet]
  27. public string Get(ApiVersion apiVersion) => $"Controller = {GetType().Name}\nVersion = {apiVersion}";
  28. }
  29. }
在呼叫 API 的 Response Header 中就可以看到目前支援版本為 1.0 與 2.0 兩種,版本 0.1 已過期

不限版本
在一些通用的 API 接口是不需要受到版號設定的,例如 Health Check 等資訊,硬是加上版號會讓人使用上更為不便,在此情境可以加上  ApiVersionNeurtal  屬性達到效果,並從 API 版本控制中移除
  1. [ApiVersionNeutral]
  2. [Route("api/[controller]")]
  3. [ApiController]
  4. public class HealthCheckController : ControllerBase
  5. {
  6. public string Get() => "OK";
  7. }

感想
透過以上說明相信對於ASP.NET Core WebApi Version 設定與應用有基本了解,在微軟 GitHub 官方 aspnet-api-versioning 也提供 sample code 範例給開發者了解,也可以發現版本控管框架不只支援 ASP.NET Core 也支援 .NET Framework WebAPI,如果對於細節或是應用想了解更多的話,不坊可以到 GitHub 可以看到更多有興趣的項目,希望這篇介紹可以有幫助到有需要的朋友 :)
Sample Code Path : sampleCode/NETCoreWebAPIVersioning

參考
aspnet-api-versioning
API Versioning in ASP.net Core
ASP.NET Core Web API Versioning 的做法

Related Posts:

  • [IIS] IIS 站台服務異常中止 - HttpEvent 問題 今天同事反應測試主機 IIS Server 無法使用,進到 QA 主機後發現所有的 IIS 服務都已停止,第一直覺就是到事件檢視器查看是否有異常的 Log 資訊,發現事件檢視器紀錄其中來源  HttpEvent  嫌疑重大,以下就針對解決此問題的方式做說明,若有問題歡迎提出一起討論或是給予指導。 解決方案 由於公司測試機對外預設都是以 80 port 為主,無故發生異常是蠻很奇怪,過去… Read More
  • [UnitTest] 如何測試目標方法中 Guid 型別的代碼 ?情境 如果要產生一個亂數時很常會想到 Guid 方法解決,在 C# 使用 Guid 的方式相當簡單僅要透過  Guid.NewGuid  靜態方法產生一組 Guid 使用,在目前公司很常看到使用 Guid 作為識別碼,今天在重構舊代碼時忽然想到如果遇到 Guid 該如何進行加上單元測試,以下就目前想到的解法進行測試與說明,如果各位高手們有更好的方法歡迎高抬貴手一起討論研究。 解決方案 寫個簡單的 Sa… Read More
  • [.NETCore] 如何取得 appsettings.json 組態設定問題 在開發時有時會將資訊紀錄在 Web.Config 設定檔中的開發經驗,在 .NET Framework 要取得 web.config 自訂組態設定時可以透過  ConfigurationManager.AppSettings ,相信大家都有了解且不陌生;但今天場景換到 ASP.NET Core 時,在一開始建立好新專案後只有  appsettings.json  設定檔,那麼該如何… Read More
  • [VisualStudio] .NET 分析測試代碼覆蓋率 AxoCover前言  最近在替既有專案補上單元測試,除了在 SonarQube 可以看到測試代碼覆蓋率之外,這幾天同事推薦一套可以在 Visual Studio 執行的程式碼覆蓋率分析工具 AxoCover,可運行在 .NET 環境且開源免費,簡單玩了一下覺得十分不錯推薦給大家,今天就來分享 AxoCover 在 Visual Studio 2017 的安裝及基本操作說明。 安裝 AxoCover  Step 1 :… Read More
  • [IIS] 程序無法存取檔案,因為檔案正由另一個程序使用。(發生例外狀況於HRESULT:0x80070020)問題 今天要在公司測試 Server 建立測試站台,在完成設定 Application Pool 與站台指定位置後按下啟動,跳出'程序無法存取檔案,因為檔案正由另一個程序使用。(發生例外狀況於HRESULT:0x80070020) 錯誤訊息,訊息內容看似有檔案被 lock 住造成啟動異常,但追根究底之後會發現其異常原因蠻單純的,以下就針對解決此問題的方式做說明,若有問題歡迎提出一起討論或是給予指導。 解決方案 根… Read More

0 意見:

張貼留言

Copyright © 2025 m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com