OSS.Http項目對於.Net Standard標準庫的支持已經遷移完畢,OSS開源系列兩個最底層的類庫已經具有跨運行時支持的能力。因爲OSS.Http類庫是幾年前我參照RestSharp的思路,完成的一個輕量型Http請求框架。由於時間較久底層使用的仍是HttpWebRequest,此次基本上是徹底重構,這篇文章主要包含 1. HttpClient的介紹,2. 重構的思路, 3. 容易遇到的問題。ios
一. httpclient的基本介紹git
HttpClient應該是在.net framework4.5版本左右引用的新功能,在此以前經常使用的是HttpWebRequest,相比較而言,前者更加的簡單清晰,最重要的是徹底支持.net standard API,這也是我選擇它的重要緣由。github
HttpClient在結構上作了很大的調整,而且是徹底異步的實現,能夠說從底層上完成了異步的支持,這裏先介紹對應的幾個主要類:web
1. HtttpRequestMessagejson
請求的基本信息,請求地址,請求動做等,此值是在HttpClient發起請求的方法中當參數傳入,與他對應的是響應 HttpResponseMessagecookie
2. HttpContent框架
請求的內容體,主要包含請求的具體內容,contenttype,contentlenght等,是HtttpRequestMessage的一個屬性,這兩個都包含Headers屬性,可是範圍分別不同,這個是很容易混淆出錯的地方,我給作了簡單分類:異步
HttpRequestMessage的頭部(HttpRequestHeaders )主要是請求的屬性,如Accept,UserAgent,AcceptEncoding等http連接的基本屬性。函數
HttpContent的頭部(HttpContentHeaders)主要是當前請求內容的屬性,主要有:Allow,Content-Encoding,Content-Length,Content-Type ,Expires ,Last-Modified 等,詳見官方類庫。spa
HttpContent 系統提供了幾個默認實現,主要以下幾個:
3. HttpMessageHandler
此類主要做用是請求內容處理動做等的定義,如是否支持重定向,是否可使用cookie,代理Proxy等,偏向於系統的設置,能夠此值經過HttpClient構造函數傳入其中,系統默認的提供的子類爲 HttpClientHandler。
4. HttpClient
具體的請求實現調用實現,完整實現了POST,GET,Delete等Http請求方法,全部的方法最終調用的是SendAsync方法。
上邊的四個主要類,構成了HttpClient請求的主要實現,若是你只是簡單的使用,那麼只須要關心HttpClient便可,以下:
其實在它內部已經默認實現了HttpRequestMessage和HttpClientHandler的賦值。
雖然簡單介紹,可是基本上能夠看出,HttpClient的實現作了很是明確的分工,不是再像之前全部的設置都集中在webrequest中。分工的明確最直接的優點是HttpClient實現了多請求共用,參見博文:
The default HttpClient is the simplest way in which you can start sending requests. A single HttpClient can be used to send as many HTTP requests as you want concurrently so in many scenarios you can just create one HttpClient and then use that for all your requests.
也就是當你係統中要發起不一樣的請求時,能夠共用一個HttpClient,而不用像HttpWebReqest基本每次請求都須要從新定義一個對象,以減小資源的消耗。
二. 重構OSS.Http
回到正題,重構咱們的當前代碼模塊,如我所說,因爲.Net Standard下徹底不提供httpWebRequest的支持,直接致使了我作出從新實現的決定,由於之前httpWebRequest的簡陋,因此我基本上作了很大的封裝框架,上層徹底不須要接觸具體的底層實現,基本上實現了RestSharp的核心,有興趣的同窗能夠參考代碼 OSS.Http 下Old分支。
重構以前因爲對HttpClient不是十分了解,本想延續已有框架流程,轉換實現。不過隨着對Client文檔的查看研究,發現不少封裝已經徹底不須要,流程也發生了變化,因此刪除不少原來框架下的東西,從新整理出最終的實現。
固然如今的HttpClient自己實現已經足夠簡單清晰,不過在不少狀況下直接調用POST,GET等方法,會減小部分代碼的重用,像在OSS.Social項目中,底層我只須要實現一個RestCommon方法,便可達到全局請求控制,調用方只須要提供Url,HttpMothed,Parameter便可。
這裏我畫了一個簡單的流程圖做爲呈現:
流程基本沒有太大的出入,代碼在Github,文件的結構以下:
Mos文件下: Enum.cs 枚舉類,FileParameter.cs 文件參數類,FormParameter Form表單參數類 ,OsHttpRequest 請求參數類,
OsRest.cs 是當前封裝類的主要實現,同時爲了保證HttpClient自己功能通用,OsRest繼承自HttpClient,同時提供了RestSend方法,在這個方法中完成流程的實現並最終調用SendAsync方法執行請求。
RestUtil.cs 輔助類,完成了全局OsRest(HttpClient)的共用,並定義了一個默認HttpClientHandler實現,正常直接調用這個類就能夠了。
流程中的執行用戶自定義設置,能夠在OSHttpRequest中的RequestSet委託屬性中設置,例如能夠設置訪問類型是json:
三. 容易遇到的問題
雖然整個重構後的代碼已經很少了,可是應該仍是有些問題能夠給你們分享下
1. Header賦值問題,請參見我第一部分,必定要分清不一樣Headers,不然就可能給你報不正確的值錯誤
2. 能夠發現上邊的流程圖中有個「是不是Get」的判斷,由於若是是Get請求,Content是不能賦值的,就像在HttpWebReqest中,若是get請求調用了GetRequestStream方法,會有「沒法發送具備此謂詞類型的內容正文」的異常錯誤。固然若是你使用的是OSS.Http做爲請求,那麼就沒有這個問題了。
3. 和上傳文件同時上傳的表單參數,與單獨的表單參數提交,是不同的,請注意處理,不懂得參見OsRest類便可,已經作了處理。
若是你還有其餘問題,或者對後續的更新感興趣,請關注公衆號(OSSCoder):