在 .NET 中有提供 Obsolete Attribute ,可以標記方法或類別為棄用,當其他程式呼叫這些被標記為棄用的方法或類別時就會收到警告,但在現代化的系統中,會有許多 API 呼叫是透過 Web API 的方式,也就是 HTTP 呼叫,這時候就沒有現成的機制來幫助我們處理這些棄用的 API 了,這時候我們可以透過 Middleware 來幫助我們處理這些情況。
首先,我參考了 Obsolete Attribute 原始碼 ,建立了一個用於定義 API 是否為棄用的 Attribute,這個 Attribute 會提供一個訊息,讓呼叫端知道這個 API 即將棄用,並可以設定是否強制報錯,使該 API 的呼叫無法繼續執行。程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false) ] public class DeprecatedAttribute : Attribute { public string Message { get ; } public bool IsError { get ; } public DeprecatedAttribute (string message ) { Message = message; } public DeprecatedAttribute (string message, bool error ) { Message = message; IsError = error; } public DeprecatedAttribute () { Message = "This API is deprecated, and it may cause to failed." ; } }
接著,我們要設定 Middleware 來處理這些被標記成即將棄用的 API,這個 Middleware 會檢查每個請求是否有被標記棄用,如果是的話,就會回應的 Header 中,加上 X-API-Deprecation-Message 標頭,並提供相對應的訊息。
如果我們有設定 IsError 使之強制報錯,則該呼叫會直接回應 HTTP 405 狀態,並提供對應的錯誤訊息。程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class ApiDeprecationMiddleware { private readonly RequestDelegate _next; public ApiDeprecationMiddleware (RequestDelegate next ) { _next = next; } public async Task InvokeAsync (HttpContext context ) { var endpoint = context.GetEndpoint(); if (endpoint != null ) { var deprecatedAttribute = endpoint.Metadata.GetMetadata<DeprecatedAttribute>(); if (deprecatedAttribute != null ) { if (deprecatedAttribute.IsError) { context.Response.StatusCode = StatusCodes.Status405MethodNotAllowed; context.Response.Headers.Add("X-API-Deprecation-Message" , deprecatedAttribute.Message); await context.Response.WriteAsync(deprecatedAttribute.Message); return ; } else { context.Response.Headers.Add("X-API-Deprecation-Message" , deprecatedAttribute.Message); } } } await _next(context); } }
接著,我們要在 Program.cs 中設定啟用此 Middleware 的啟用,如下列程式碼:
1 app.UseMiddleware<ApiDeprecationMiddleware>();
在使用上,我們可以在 Controller 或 Action 上標記 DeprecatedAttribute,端看你是要從哪個層級做棄用,以下是棄用特定 API 的範例:
1 2 3 4 5 6 7 8 9 10 11 12 13 [Route("api/[controller]" ) ] [ApiController ] public class DemoController : ControllerBase { public DemoController () { } [Deprecated("This API is deprecated, please use 'api/XXX' instead" ) ] public IActionResult Get () { return Ok("Demo" ); } }
呼叫棄用的 API 會在 Headers 中加上對應的棄用訊息,如下圖:
若有設定 IsError 使之強制報錯,則呼叫該 API 會直接回應 HTTP 405 狀態,並提供對應的錯誤訊息,如下圖:
參考資料: