前情提要
筆者在公司負責的專案,大多數都跟其他廠商串接有關,串接方式百百種,最多就是Http Request了,因新專案已都使用dotnet 6來開發,透過AddHttpClient註冊,注入HttpClient,再將HttpRequest的實作封裝成HttpClientRepository,確實都滿順利的,但光HttpClient串接也是有百百種,有的廠商要FormPost方式送出RequestContent,有的廠商則一般常見的將RequestContent放在Body,格式方面有些則json格式,有些則xml等等,組合也是挺可怕的多,要一直調整其底層共用程式HttpClientRepository。
再則筆者在實作中遇到一個滿常見的問題,Header重複設定的錯誤,因Http連線成本確實不低,因此透過AddHttpClient使用HttpClient,希望由dotnet底層管理連線,降低其連線成本,以常見的Header設定來說,就屬Authorization了,筆者這邊為了加速往廠商端的查詢,會透過Parallel的方式併發出Request,全部Response都回來後才做商業邏輯處理,因此第一次連線後Header尚未設定的情況下,有一定的機率兩組執行緒碰撞一次,也有一定的機率兩組同時進到判斷式,要新增Header的值,搞得筆者連Lock機制都用上了,目前尚未找到更好的解,只能先這樣暴力解了。最後筆者自己本身在Linqpad上先行測試時會使用HttpRequest相關套件,例:RestSharp,心血來潮認真看了下其API,看到有Headers章節中的API: AddOrUpdateHeader,覺得完全是解決筆者的痛點,突然有一種HttpRequest應該是一個基礎建設,若能有一個套件幫忙實作完成,就可以專心地將所有精力投入在商業邏輯層面就好,進而縮短開發時間,然而某天在LinkedIn貼文上看到一個套件叫[Refit](https://github.com/reactiveui/refit),不查還好,查完後覺得就它了。
內容
筆者主要選擇使用Refit,有以下原因:
- 可透過注入的方式取得(底層亦是透過
HttpClientFactory取得HttpClient物件) - 可繼續沿用客製化
HttpMessageHandler - 可繼續沿用
Polly機制 - 最棒的一點,要增加不同廠商的
API串接,多一組Interface宣告即可,終於不用再調整HttpClient底層邏輯了
因此目前筆者開發串接廠商API的流程大致上如下:
- 觀看廠商提供的
API文件,若有範例,則透過Postman試打 - 將
API文件或Postman中的Response Sample丟至ChatGPT轉成C# class - 定義對應的
Refit API interface - 於
Startup中註冊其服務
筆者這篇文章內容則透過政府公開平台OpenData的API為例,示範怎麼使用,因簡單示範,就透過Linqpad來完成,但因Refit必須要有產生虛擬代碼,Linqpad上面要做一點手腳才有辦法進行,剛好筆者有看到解法
http://share.linqpad.net/xn3ac8.linq
載入套件
筆者就照Liqnpad引用套件流程套用Refit
宣告API
筆者就省略上方列出的前兩個步驟,假設已拿到C# class內容,先宣告QueryParameters
1 | public class LandPriceParameters |
再宣告ResponseModel,Refit預設會透過System.Text.Json做序列化及反序列化,切記套用的Json相關Attribute,必須為System.Text.Json下的
1 | public class LandData |
最後宣告主體,API規格,只要定義就等同寫完串接API
[Get("/WEBAPI/LandPrice/Lastest")]Route中的第一個/非常重要,一定要加,不然會爆錯
1 | public interface OpenDataApiService |
使用方式
筆者示範使用Liqnpad工具呈現,需參考上方所列的linq檔案
1 | //為上方所列之linq檔案載入 |
跑完後的結果如下(僅截取部份資料):
| LandNo | LandPrice(元/平方公尺) | CurrentValue(元/平方公尺) |
|---|---|---|
| 00760050 | 81685 | |
| 00810017 | 81685 | |
| 00720014 | 71400 | |
| 00720015 | 81685 | |
| 00730003 | 163540 | |
| 00740001 | 166591 |
結論
到這邊是不是覺得呼叫HttpRequest很簡單呢,當然不管是否自己實作HttpClient呼叫,或使用Refit完成HttpRequest,前面轉C# Class是避免不了的,後面測試也是免不了的,其中最大的好處還是在於HttpClient呼叫的基礎建設方法,不用因為你多串一個新的廠商,與以往不同而調整基礎建設,可以順順地依照筆者上方列出的串接廠商API流程完成串接,多了很多處理商業邏輯的時間,覺得CP值非常高,下一篇將介紹Dotnet Core專案套用Refit的流程。
參考
- https://github.com/reactiveui/refit
- https://forum.linqpad.net/discussion/2396/source-generator-support
- https://data.gov.tw/dataset/163138
- https://data.gov.tw/dataset/163141