RestClient 庫提供了一個簡單的連接器來使用 REST 服務。
要在專案中使用它,請將 Mafe.RestClient NuGet 套件新增到您的專案中。
RestClient 的目標是讓開發人員能夠以非常簡單的方式輕鬆連接到任何伺服器。只需定義您的資料傳輸物件 (Dto) 並開始與客戶端一起玩!
使用 Build() 方法從 Rest 建立 RestBuilder:
var rest = Rest . Build ( ) ;
要創建一個簡單的 get 調用,只需這樣做:
var rest = Rest . Build ( ) ;
var result = rest . Url ( "[URL]" ) . Get ( ) ;
或者我們可以使用 GetAsync() 方法:
var rest = Rest . Build ( ) ;
var result = await rest . Url ( "[URL]" ) . GetAsync ( ) ;
每當您在本文檔中找到「[URL]」一詞時,它都指的是 webAPI 的基本 URL 定義。
我們可以定義一個 Root() 端點並使用它來建構請求。
public RestBuilder Root ( ) => rest . Url ( "https://mywebapi.mydomain.com" ) ;
然後,我們可以使用它,如下所示:
public RestBuilder Root ( ) => Rest . Build ( ) . Url ( "https://mywebapi.mydomain.com" ) ;
var result = Root ( )
. Command ( "/my-action" )
. Payload ( "mystring" )
. Post ( ) ;
使用 RestProperties 配置您的休息根點。要建立一個簡單的配置,就像這樣:
RestProperties properties = new RestProperties
{
EndPoint = new Uri ( "[URL]" ) , //if you use .Url("[URL]") you override it
BufferSize = 4096 ,
CertificateOption = ClientCertificateOption . Manual ,
Timeout = TimeSpan . FromMinutes ( 2 )
} ;
使用帶有屬性的 Build() 方法從 Rest 建立 RestBuilder:
var rest = Rest . Build ( properties ) ;
X.509 憑證的驗證對於建立不易受到中間人攻擊的安全 SSL/TLS 會話至關重要。
憑證鏈驗證包括以下步驟:
不建議透過實施自訂憑證鏈驗證來重新發明輪子。
TLS 函式庫提供了應該使用的內建憑證驗證函數。
List < string > validCerts = new List < string > ( ) {
"CERT STRING"
} ;
var result = Rest . Build ( )
. CertificateValidation ( ( sender , certificate , chain , errors ) =>
{
// for development, trust all certificates
if ( development ) return true ;
// Compliant: trust only some certificates
return errors == SslPolicyErrors . None
&& validCerts . Contains ( certificate . GetCertHashString ( ) ) ;
} )
. Url ( "[URL]" )
. Get ( ) ;
根據 HTTP/1.1 [RFC2617] 的定義,應用程式應直接在授權請求標頭中傳送 access_token。您可以透過在 HTTP 請求正文中包含不記名令牌的 access_token 值作為「授權:不記名 {access_token_value}」來實現此目的。
如果經過驗證的使用者的不記名令牌的 access_token 或 refresh_token 已過期,則會傳回「401 - 未經授權(刷新令牌無效或過期)」錯誤。
var result = Rest . Build ( )
. Authentication ( ( ) => new AuthenticationHeaderValue ( "Bearer" , "[Token]" ) )
. Url ( "[URL]" )
. Get ( ) ;
有效的承載令牌(具有活動的 access_token 或 refresh_token 屬性)可以使使用者的身份驗證保持活動狀態,而不需要他或她經常重新輸入其憑證。 access_token 只要處於活動狀態即可使用,即登入或續訂後最多一小時。 fresh_token 的有效期限為 336 小時(14 天)。 access_token 過期後,可以使用活動的refresh_token 來取得新的access_token/refresh_token 對,如下例所示。此週期最多可持續 90 天,之後使用者必須再次登入。如果refresh_token過期,則無法更新token,使用者必須重新登入。
若要刷新令牌,請自動使用“RefreshTokenInvoke”。
var url = "[URL]" ;
var result = Rest . Build ( )
. Authentication ( ( ) => new AuthenticationHeaderValue ( "Bearer" , "[Token]" ) )
. RefreshToken ( true )
. RefreshTokenInvoke ( async ( ) =>
{
var result = await rest
. Url ( url )
. Command ( "/refresh" )
. GetAsync < TokenObjectResponse > ( ) ;
doSomethings ( ) ; //store the token inside your env.
return result ;
} )
. Command ( "/detail" )
. Url ( url )
. Get ( ) ;
應該撤銷refresh_token:
NetworkCredential 類別是一個基底類,它在基於密碼的驗證方案(例如基本、摘要、NTLM 和 Kerberos)中提供憑證。實作 ICredentials 介面的類別(例如 CredentialCache 類別)傳回 NetworkCredential 物件。此類不支援基於公鑰的身份驗證方法,例如安全通訊端層 (SSL) 用戶端身份驗證。
var result = Rest . Build ( )
. NetworkCredential ( "myUsername" , "myPassword" )
. Url ( "[URL]" )
. Get ( ) ;
var result = rest
. NetworkCredential ( ( ) => new System . Net . NetworkCredential ( "myUsername" , "myPassword" ) )
. Url ( "[URL]" )
. Get ( ) ;
Headers 集合包含與請求關聯的協定標頭。 Header((h)=>{}) 方法可讓您新增鍵列表。
var result = Rest . Build ( )
. Header ( ( h ) => {
if ( ! h . Contains ( "auth-custom" ) )
h . Add ( "auth-custom" , "value" ) ;
} )
. Url ( "[URL]" )
. Get ( ) ;
RestClient 支援兩種類型的序列化:Xml 和 Json,但可以實現 ISerializerContent 來自訂序列化。 RestClient 使用 .Json() 將物件序列化為 json。
var result = Rest . Build ( )
. Url ( "[URL]" )
. Json ( )
. Get < ResponseObject > ( ) ;
可以將 json 序列化器選項傳遞給 .Json() 方法,如下所示:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Json ( new JsonSerializerOptions {
WriteIndented = true
} )
. Get < ResponseObject > ( ) ;
上面的程式碼片段考慮使用 System.Text.Json 函式庫。如果我們像這樣使用 Netwnsoft:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Json ( new JsonSerializerSettings {
Formatting = Formatting . Indented
} )
. Get < ResponseObject > ( ) ;
RestClient 使用 .Xml() 將物件序列化為 xml。
var result = rest
. Url ( "[URL]" )
. Xml ( )
. Get < ResponseObject > ( ) ;
可以將設定傳遞給 .Xml() 方法,如下所示:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Xml ( new XmlReaderSettings { Indent = true } , new XmlWriterSettings { IgnoreWhitespace = true } )
. Get < ResponseObject > ( ) ;
下面的範例介紹如何透過實作 ISerializerContent 介面來執行自訂序列化:
public class MyCustomSerializer : ISerializerContent
{
public string MediaTypeAsString => throw new NotImplementedException ( ) ;
public object DeserializeObject ( string value , Type typeOf , object options = null )
{
throw new NotImplementedException ( ) ;
}
public string SerializeObject ( object value , Type typeOf , object options = null )
{
throw new NotImplementedException ( ) ;
}
}
現在,我們可以像這樣使用 MyCustomSerializer:
var result = Rest . Build ( )
. Url ( "[URL]" )
. CustomSerializer ( new MyCustomSerializer { } )
. Get < ResponseObject > ( ) ;
BufferSize 可用來設定上傳和下載流期間的緩衝區大小。預設值為 80Kb
var result = Rest . Build ( )
. Url ( "[URL]" )
. BufferSize ( 4096 * 5 * 5 ) //100Kb
. Get ( ) ;
在與指定資源通訊期間啟用 gzip 壓縮:
var result = Rest . Build ( )
. Url ( "[URL]" )
. EnableGZipCompression ( )
. Get ( ) ;
庫自動解壓縮響應。
GET 是最常見的 HTTP 方法之一,GET 用於向指定資源請求數據
var rest = Rest . Build ( ) ;
var result = rest
. Url ( "[URL]" )
. Get ( ) ;
var result = await rest
. Url ( "[URL]" )
. GetAsync ( ) ;
關於 GET 請求的其他一些注意事項:
請注意,查詢字串(名稱/值對)是在 GET 請求的 URL 中傳送的。
在某些情況下,我們需要使用參數作為查詢字串。我們可以使用 Parameter(key, value) 方法來解析它,如下所示:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/path" )
. Parameter ( "id" , "10" )
. Parameter ( "type" , "myType" )
. Get ( ) ;
產生的url為:[URL]/path?id=10&type=myType
POST 用於將資料傳送到伺服器以建立/更新資源。透過 POST 傳送到伺服器的資料儲存在 HTTP 請求的請求負載中:
var rest = Rest . Build ( ) ;
var result = rest
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. Post < ResponseObject > ( ) ;
var result = await rest
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. PostAsync < ResponseObject > ( ) ;
Post 是另一種常見的 http 方法,用於:
PUT 用於將資料傳送到伺服器以建立/更新資源。
POST 和 PUT 之間的差異在於 PUT 請求是冪等的。也就是說,多次呼叫相同的 PUT 請求將始終產生相同的結果。相反,重複呼叫 POST 請求會產生多次建立相同資源的副作用。
var rest = Rest . Build ( ) ;
var result = rest
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. Put < ResponseObject > ( ) ;
var result = await rest
. Url ( "[URL]" )
. Payload ( new Object { } )
. PutAsync < ResponseObject > ( ) ;
DELETE 方法刪除指定的資源。
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. Delete < ResponseObject > ( ) ;
var result = await Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. DeleteAsync < ResponseObject > ( ) ;
DOWNLOAD方法下載指定的資源。
var result = Rest . Build ( )
. Download ( "[URL]" ) ;
var result = await rest
. DownloadAsync ( "[URL]" ) ;
可以使用 OnDownloadProgress 顯示下載狀態。
var rest = Rest . Build ( ) ;
var result = await rest
. OnDownloadProgress ( ( d ) => Console . WriteLine ( $ " { d . CurrentBytes } / { d . TotalBytes } " ) )
. DownloadAsync ( "[URL]" ) ;
傳播應取消操作的通知。
CancellationToken 支援執行緒、執行緒池工作項目或任務物件之間的協作取消。您可以透過實例化 CancellationTokenSource 物件來建立取消令牌,該物件管理從其 CancellationTokenSource 檢索的取消令牌。
以下範例使用取消令牌來停止執行:
// Define the cancellation token.
CancellationTokenSource source = new CancellationTokenSource ( ) ;
CancellationToken token = source . Token ;
// Schedules a cancel operation on this System.Threading.CancellationTokenSource
// after the specified number of milliseconds
token . CancelAfter ( 3000 ) ;
var file1 = Rest . Build ( ) . DownloadAsync ( "[URL FILE1]" , token . Token ) ;
var file2 = Rest . Build ( ) . DownloadAsync ( "[URL FILE2]" , token . Token ) ;
var get1 = Rest . Build ( ) . Url ( "[URL GET1]" ) . GetAsync < MyObject > ( token . Token ) ;
Task . WaitAll ( file1 , file2 , get1 ) ;
取消請求後,它會拋出 TaskCancellatedException。異常將被封裝到 RestResult 物件中。
自訂指定資源的 CUSTOM 方法。
HttpMethod PATCH = new HttpMethod ( "PATCH" ) ;
var rest = Rest . Build ( ) ;
var result = rest
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. CustomCall < ResponseObject > ( PATCH ) ;
var result = await rest
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new Object { } )
. CustomCallAsync < ResponseObject > ( PATCH ) ;
RestClient 使用 Playload(obj) 方法根據請求設定物件:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new RequestObject { } )
. Post < ResponseObject > ( ) ;
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. Payload ( new RequestObject { } )
. Put < ResponseObject > ( ) ;
必要時我們可以使用表單 url 編碼的請求。要使用它,我們需要啟用它,如下所示:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. EnableFormUrlEncoded ( true )
然後我們可以將參數當作字典傳遞:
var params = new Dictionary < string , string > ( ) ;
params . Add ( "key1" , "value1" ) ;
params . Add ( "key2" , "value2" ) ;
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. EnableFormUrlEncoded ( true )
. FormUrlEncoded ( params )
. Post ( ) ;
可以在處理程序內部傳遞參數並啟用表單 URL 編碼:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. FormUrlEncoded ( true , ( p ) =>
{
p . Add ( "key1" , "value1" ) ;
p . Add ( "key2" , "value2" ) ;
} )
. Post ( ) ;
OnUploadProgress 在請求正在運作且資料即將傳出時發生。我們可以獲得上傳資料的百分比,如下所示:
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnUploadProgress ( p =>
{
DoSomethings ( p . ProgressPercentage ) ;
} ) //occurs during request
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnDownloadProgress 在回應運行且資料傳入時發生。
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnDownloadProgress ( p =>
{
DoSomethings ( p . ProgressPercentage ) ;
} ) //occurs during response
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
預設值為 100,000 毫秒(100 秒)。若要設定無限逾時,請將屬性值設為 InfiniteTimeSpan。網域名稱系統 (DNS) 查詢可能需要長達 15 秒才能返回或逾時。如果您的要求包含需要解析的主機名,並且您將 Timeout 設定為小於 15 秒的值,則可能需要 15 秒或更長時間才會引發異常以指示您的請求逾時。
var result = Rest . Build ( )
. Url ( "[URL]" )
. Timeout ( 3200 ) //milliseconds
. Get < ResponseObject > ( ) ;
var result = Rest . Build ( )
. Url ( "[URL]" )
. Timeout ( TimeSpan . FromMinutes ( 10 ) )
. Get < ResponseObject > ( ) ;
OnStart 是請求開始時觸發的事件。
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnStart ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnPreviewContentRequestAsString 是一個在請求準備就緒且尚未發送時觸發的事件。
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnPreviewContentRequestAsString ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnPreviewContentResponseAsString 是在收到回應且尚未反序列化時觸發的事件。
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnPreviewContentResponseAsString ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnPreResult 在請求正在完成但尚未完成時發生。當 OnPreResult 引發時,我們可以做一些事情,例如取得並使用請求的結果。
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnPreCompleted ( ( r ) => {
DoSomethings ( r . Result ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnException 當請求引發異常時發生。
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnException ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
OnCompleted 在請求完成時發生。
var result = Rest . Build ( )
. Url ( "[URL]" )
. Command ( "/action" )
. OnCompleted ( ( e ) => {
DoSomethings ( e ) ;
} )
. Payload ( new BigObject { } )
. Post < ResponseObject > ( ) ;
RestClient 允許建立靈活且健壯的網路層,並且非常容易使用。下面您可以找到完整的程式碼示範完整的程式碼範例。
public class NetworkService {
//building context
public RestBuilder Root ( )
=> Rest . Build ( )
. CertificateValidation ( ( sender , certificate , chain , errors ) =>
{
if ( development ) return true ;
return errors == SslPolicyErrors . None
&& validCerts . Contains ( certificate . GetCertHashString ( ) ) ;
} )
. Url ( "[URL]" ) ;
public RestBuilder RootAuthentication ( )
=> Root ( )
. Authentication ( ( ) => new AuthenticationHeaderValue ( "Bearer" , "[Token]" ) )
. RefreshToken ( )
. RefreshTokenInvoke ( async ( ) => await PostRefreshAsync ( new RefreshRequest { } ) ) ;
public RestBuilder UsersRoot ( )
=> Root ( ) . Command ( "/Users" ) ;
public RestBuilder DimensionsRoot ( )
=> Root ( ) . Command ( "/Dimensions" ) ;
public RestBuilder EventsRoot ( )
=> RootAuthentication ( ) . Command ( "/Events" ) ;
//requests
public async Task < RestResult < LoginResponse > > PostLoginAsync ( LoginRequest request )
=> await UsersRoot ( )
. Command ( "/Login" ) //[URL]/Users/Login
. Payload ( request )
. PostAsync < LoginResponse > ( ) ;
public async Task < RestResult < RuleResponse > > GetRulesAsync ( )
=> await UsersRoot ( )
. Command ( "/Rules" )
. GetAsync < RuleResponse > ( ) ;
public async Task < RestResult < RefreshResponse > > PostRefreshAsync ( RefreshRequest request )
=> await UsersRoot ( )
. Command ( "/Refresh" )
. Payload ( request )
. PostAsync < RefreshResponse > ( ) ;
public async Task < RestResult < CountryResponse > > PostCountriesAsync ( CountryRequest request )
=> await DimensionsRoot ( )
. Command ( "/Countries" )
. Payload ( request )
. PostAsync < CountryResponse > ( ) ;
public async Task < RestResult < EventDetailResponse > > PostEventDetailAsync ( EventDetailRequest request )
=> await EventsRoot ( )
. Command ( "/EventDetail" )
. Payload ( request )
. PostAsync < EventDetailResponse > ( ) ;
}