前情提要
延續[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的值做商業邏輯處理,省了不少工,此篇就到這邊了,下次見。
參考