前情提要
延續[DotnetCore]Refit:類ApiGateway實作文章,筆者在開發前台,後台這種隔離架構時,還會有一個需求是,比較正式的API規格,會有一些客製化的Header
值必須要辨別,不外乎就是AcesssToken
,或者必要的Client
資訊,及封包簽章等資訊,以前台轉發到後台這段來說,猶如上一篇提到透過Refit
完成。
筆者的思路是這樣,驗證這些Client Request
資訊的職責來說,止於前台,不需要再原封不動將客製化的Header
資訊送到後台,因為後台商業邏輯處理來說也不需要這些資訊,因此某些Header的值必須下放到Model
層級,讓後台收到的Request
中已經含有商業邏輯處理的必要資訊。
再則前台這一層必須要驗證Request
的合理性,一定會讀取Header
資訊,若要把這些Header
資訊原封不動的送到後台,反而還要額外動工,第一是要製作成Refit的參數,第二是後台還要再拆解一次Header資訊,完全是做了很多不需要的步驟,於是乎,這篇就誕生啦。
內容
筆者主要目的就是想要把一些Header
上的資訊,想要放到Request
的Body
上,讓API Pipeline
走到Action
時,已經將Request Model
都繫結好了,筆者一開始的方向是Customize Model Binding
,找到Microsoft Learn
上面的教學https://learn.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-6.0,看了一下情境都不太符合,
RequestBaseModel
筆者這邊交代一下,因為這個新系統包含OAuth
的驗證,基本上都會有ClientId
以及RequestId
(識別Request
),筆者這邊僅列出BaseModel
1 | public class BaseRequestDto |
HeaderKeyConfigHelper
後面寫到Middleware
時會用到讀取Header
中的值,基本上都會有一個定義好的Header Key
,筆者這邊習慣會定義好const
變數
- 集中
Key
定義 - 若有一個以上地方使用後須調整時,只要更改一個地方即可
1 | public class HeaderKeyConfigHelper |
HeaderModelBindingMiddleware
這邊主要邏輯是讀出RequestBody
,透過dynamic
的ExpandObject
,指定客製化欄位的值後再變更其RequestBody
1 | public class HeaderModelBindingMiddleware |
上述code
中透過ExpandObject
擴充其屬性,筆者這個版本好處有幾個
- 若沒有對應的
header key
也不會壞掉,先判斷有header key
對應的value
才指定 - 接著即便是
Action
所接的Model
沒有這些屬性也只是被捨去這些值而已,沒有其他SideEffect
當然這個版本的缺點就是若沒有再用Endpoint
過濾的掛上Middleware
的話,每個Action
都會經過這個Middleware
,若沒有需要這些屬性的Model
就顯得多了一些步驟做判斷是否存在header Key
及對應的值,筆者這個站台的使用情境是滿符合的,因此要考慮用的讀者可能要思考一下使用情境再做使用。
註冊Middleware
就註冊在Startup
中就可以了
1 | public partial class Startup |
這樣Action
接的Model
只要有繼承BaseRequestDto
就會自動Binding
裡面的RequestId
跟ClientId
屬性了
結論
筆者因有一個前台站台,不處理邏輯,裡面剛好用到的此篇的技巧,轉發到後台時,不用再另外包裝Header
值,轉發到後台後,後台站台也不用再另外解析Header
的值做商業邏輯處理,省了不少工,此篇就到這邊了,下次見。
參考