前情提要
筆者在公司負責的專案,大多數都跟其他廠商串接有關,串接方式百百種,最多就是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