翻譯自:https://github.com/restsharp/RestSharp/wiki,轉載請注明。
一、新手入門##
如果只有少量一次性請求需要封裝為API,則可以如下使用RestSharp :
using RestSharp;
using RestSharp.Authenticators;
var client = new RestClient();
client.BaseUrl = new Uri("http://twitter.com");
client.Authenticator = new HttpBasicAuthenticator("username", "password");
var request = new RestRequest();
request.Resource = "statuses/friends_timeline.xml";
IRestResponse response = client.Execute(request);
IRestResponse 接口中包含了所有遠程服務返回的信息,可以訪問頭信息(header)數據內容(content)、HTTP狀態等。建議使用泛型將返回結果自動反序列化為.NET實體類。
關於錯誤處理:
如果發生了網絡傳輸錯誤(網絡癱瘓,DNS查找失敗等),RestResponse.ResponseStatus 將會置為Error ,否則RestResponse.ResponseStatus的值為Completed 。如果API返回404,ResponseStatus 仍然是Completed 。如果需要訪問返回的HTTP狀態碼,則需要查看RestResponse.StatusCode 的值,Status 屬性是請求完成的標識,獨立於API錯誤處理。
二、推薦用法##
RestSharp適合作為API代理類實現的基礎,下面是 Twilio類庫中的一些使用示例:
創建一個包含API代理實現的類,聲明一個執行方法當作所有請求的入口。這個執行方法允許設置常用參數和其它跨請求共享設置(例如認證),因為每一個請求都需要帳戶ID和密鑰,所以在建立新的代理實例時都需要傳遞這兩個值。需要注意的是執行過程中不會拋出異常,但是可以在ErrorException 中訪問到異常信息。
// TwilioApi.cs
public class TwilioApi {
const string BaseUrl = "https://api.twilio.com/2008-08-01";
readonly string _accountSid;
readonly string _secretKey;
public TwilioApi(string accountSid, string secretKey) {
_accountSid = accountSid;
_secretKey = secretKey;
}
public T Execute<T>(RestRequest request) where T : new()
{
var client = new RestClient();
client.BaseUrl = new System.Uri(BaseUrl);
client.Authenticator = new HttpBasicAuthenticator(_accountSid, _secretKey);
request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment); // used on every request
var response = client.Execute<T>(request);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
var twilioException = new ApplicationException(message, response.ErrorException);
throw twilioException;
}
return response.Data;
}
}
接下來,定義一個實體類來映射API返回的數據,再定義一個方法用來訪問API同時獲取返回的Call資源的具體信息:
// Call.cs
public class Call
{
public string Sid { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateUpdated { get; set; }
public string CallSegmentSid { get; set; }
public string AccountSid { get; set; }
public string Called { get; set; }
public string Caller { get; set; }
public string PhoneNumberSid { get; set; }
public int Status { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public int Duration { get; set; }
public decimal Price { get; set; }
public int Flags { get; set; }
}
// TwilioApi.cs, method of TwilioApi class
public Call GetCall(string callSid)
{
var request = new RestRequest();
request.Resource = "Accounts/{AccountSid}/Calls/{CallSid}";
request.RootElement = "Call";
request.AddParameter("CallSid", callSid, ParameterType.UrlSegment);
return Execute<Call>(request);
}
有一些神奇之處是RestSharp 需要關心而我們不必關注:
1、API返回的XML數據被默認XmlDeserializer 檢測到,同時反序列化為Call對象。
2、默認RestRequest 對應HTTP中的GET 請求,可以通過設置RestRequest 的Method屬性或者在創建請求實例時通過構造函數指定Method 類型來改變請求類型。
3、UrlSegment 類型參數會根據Resource 屬性值中匹配的名稱標簽將值注入到URL中,AccountSid 在 TwilioApi.Execute 賦值,對於每一個請求它都是相同的。
4、我們指定了從哪里開始反序列化的根元素名稱,在本例中,返回的XML形如
我們還可以定義POST(和 PUT/DELETE/HEAD/OPTIONS )請求:
// TwilioApi.cs, method of TwilioApi class
public Call InitiateOutboundCall(CallOptions options)
{
Require.Argument("Caller", options.Caller);
Require.Argument("Called", options.Called);
Require.Argument("Url", options.Url);
var request = new RestRequest(Method.POST);
request.Resource = "Accounts/{AccountSid}/Calls";
request.RootElement = "Calls";
request.AddParameter("Caller", options.Caller);
request.AddParameter("Called", options.Called);
request.AddParameter("Url", options.Url);
if (options.Method.HasValue) request.AddParameter("Method", options.Method);
if (options.SendDigits.HasValue()) request.AddParameter("SendDigits", options.SendDigits);
if (options.IfMachine.HasValue) request.AddParameter("IfMachine", options.IfMachine.Value);
if (options.Timeout.HasValue) request.AddParameter("Timeout", options.Timeout.Value);
return Execute<Call>(request);
}
本示例同樣證明RestSharp是一個輕量級驗證助手,可以在請求前先校驗提交的參數值是否有效。
示例中通過AddParameter 方法添加的參數值將通過標准編碼格式提交,類似於通過網頁提交的表單。如果是GET形式的請求(GET/DELETE/OPTIONS/HEAD) ,參數值將通過查詢字符串提交,AddParameter() 方法也可以添加頭信息和cookie 參數。將一個對象的所有屬性作為參數時,使用AddObject() 方法。上傳一個文件時用 AddFile() 方法(請求會以多種編碼格式發送),當請求中包含請求體時(例如XML或者JSON),用AddBody()方法。
三、其它應用示例##
下面的示例演示了用流(stream)代替內存緩沖請求內容,這在請求大量數據同時需要立刻寫入磁盤的場景下非常有用:
string tempFile = Path.GetTempFileName();
using (var writer = File.OpenWrite(tempFile))
{
var client = new RestClient(baseUrl);
var request = new RestRequest("Assets/LargeFile.7z");
request.ResponseWriter = (responseStream) => responseStream.CopyTo(writer);
var response = client.DownloadData(request);
}
四、反序列化##
RestSharp擁有處理XML和JSON的反序列化器,當收到響應時,RestClient通過服務器返回的Content Type 選擇適合的反序列化器。默認設置可以通過自定義設置的Content Type覆蓋,支持的Content Type如下:
- application/json - JsonDeserializer
- application/xml - XmlDeserializer
- text/json - JsonDeserializer
- text/xml - XmlDeserializer
- *+json - JsonDeserializer (content types using a Structured Suffix Syntax specifying JSON)
- *+xml - XmlDeserializer (content types using a Structured Suffix Syntax specifying XML)
- @*@ - XmlDeserializer (all other content types not specified)
默認的反序列化器嘗試解除必須解析XML或者JSON的痛苦,通過映射CLR實體類來實現。實體類定義了如何反序列化返回的數據。RestSharp不再采用遍歷返回的數據,再從實體類中查找匹配的屬性的方式反序列化數據,而是把實體類當作起點,循環遍歷可訪問的可寫屬性,同時在返回的數據中查找相應的元素。
注意:默認的反序列化器不支持 DataAnnotation/DataMember ,如果要使用,必須實現和注冊自己的IDeserializer ,IDeserializer 是包裝了與實體類中屬性兼容的反序列化庫。
例如下面的XML和JSON:
<Person>
<Name>John</Name>
<Id>28</Id>
</Person>
{
"Name": "John",
"Id": 28
}
映射相同的實體類Person:
public class Person
{
public string Name { get; set; }
public int Id { get; set; }
}
支持的屬性類型(數據類型):###
XmlDeserializer:####
- Primitives (int, short, long, etc)
- Decimal
- DateTime
- String
- Guid
- List
- Nested classes
- Nullable versions of the above listed types
JsonDeserializer####
- Primitives
- Decimal
- DateTime
- String
- Guid
- List
- Dictionary<T1, T2>
- Nested classes
- Nullable versions of the above listed types
名稱匹配:###
XmlDeserializer####
當查找匹配元素時,默認的XML反序列化器查找元素和特性遵循以下順序:
- 元素和名稱絕對匹配
- 元素和名稱的小寫匹配
- 元素和名稱的駱駝命名匹配
- 元素和名稱去掉下划線和破折號匹配
- 特性和名稱絕對匹配
- 特性和名稱的小寫匹配
- 特性和名稱的駱駝命名匹配
- 特性和名稱去掉下划線和破折號匹配
可以使用@DeserializeAs@ 特性來更改將在屬性中查找的名稱,如果要將屬性的命名與XML中的名稱同,這一點將非常有用。
例如:
[DeserializeAs(Name = "forecast_information")]
public ForecastInformation Forecast { get; set; }
有一種返回元素值的特殊情況,示例如下:
如果返回的XML數據如下:
<Response>Hello world</Response>
沒有辦法用c#的類直接描述
public class Response
{
}
需要一些東西來保存返回的元素值,在本例中,添加一個Value屬性:
public class Response
{
public string Value { get; set; }
}
JsonDeserializer####
當為匹配元素查找數據時,默認的JSON反序列化器在查找元素時將遵循以下順序:
- 與名稱絕對匹配
- 與名稱駱駝命名匹配
- 與名稱小寫匹配
- 與名稱加了下划線匹配 (e.g. ProductId -> Product_Id)
- 與名稱加了下划線小寫形式匹配 (e.g. Product_id -> product_id)
XML反序列化器可以通過設置屬性的DeserializeAs 特性來改變如何與JSON的鍵映射。
例如:
[DeserializeAs(Name = "forecast_information")]
public ForecastInformation Forecast { get; set; }
集合處理(List/Dictionary)###
XmlDeserializer####
處理兩種不同形式的集合:內聯和嵌套
<?xml version="1.0" encoding="utf-8" ?>
<InlineListSample>
<image src="1.gif">value1</image>
<image src="2.gif">value2</image>
<image src="3.gif">value3</image>
<image src="4.gif">value4</image>
</InlineListSample>
<?xml version="1.0" encoding="utf-8" ?>
<NestedListSample>
<images>
<image src="1.gif">value1</image>
<image src="2.gif">value2</image>
<image src="3.gif">value3</image>
<image src="4.gif">value4</image>
</images>
</NestedListSample>
對應的c#形式如下:
public class ListSample
{
public List<Image> Images { get; set; }
}
public class Image
{
public string Src { get; set; }
public string Value { get; set; }
}
如果在同一份文檔中兩種元素結構恰巧同時存在,優先級按此順序:parented/nested/regular 。
JsonDeserializer####
在映射JSON數組和字典時,RestSharp支持集合(List)和字典(Dictionary<string, T> )
日期處理###
XmlDeserializer####
- 如果RestRequest.DateFormat已經指定了返回值的格式,則返回值使用指定格式字符串解析。
- 如果 RestRequest.DateFormat 沒有指定, 用DateTime.Parse計算元素值. 如果該方法無法處理當前格式, 則需要改變屬性類型為String然后再進行處理 。
JsonDeserializer####
如果沒有通過RestRequest.DateFormat指定日期格式,RestSharp嘗試用以下格式字符轉來反序列化DateTime類型的屬性(順序如下):
- "u"
- "s"
- "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
- "yyyy-MM-ddTHH:mm:ssZ"
- "yyyy-MM-dd HH:mm:ssZ"
- "yyyy-MM-ddTHH:mm:ss"
- "yyyy-MM-ddTHH:mm:sszzzzzz"
JsonSerializer 默認支持以下JSON日期格式,如果指定了具體的RestRequest.DateFormat ,則默認被忽略:
- ISO - 1910-09-25T09:30:25Z
- Javascript Date Objects - new Date(-1870352975000)
- Unix Timestamps - 1435206458
對於JS日期對象,在JS紀元時間基礎上加毫秒級的時間間隔,根據指定的時區調整。
自定義###
重寫默認反序列化器####
可以通過如下步驟重寫自己的反序列化器處理返回的數據內:
- 創建一個類同時實現IDeserializer接口。
- 用RestClient.AddHandler(contentType, IDeserializer)方法注冊handler並關聯content類型,如果此content類型已經被注冊過,則會被指定的剛剛指定的handker重寫,可以通過 RestClient.ClearHandlers()方法移除所有注冊的handler,或者通過RestClient.RemoveHandler(contentType)移除某一個handler。
重寫默認的序列化器####
當使用XML或者JSON格式數據作為請求體時,可以使用自己實現的ISerializer :
var request = new RestRequest();
request.RequestFormat = DataFormat.Xml;
request.XmlSerializer = new SuperXmlSerializer(); // implements ISerializer
request.AddBody(person); // object serialized to XML using your custom serializer;
重寫JsonSerializationStrategy####
序列化過程中,嘗試支持c#和JSOM間不同投影策略將會陷入麻煩,重寫MapClrMemberNameToJsonFieldName 將會有幫助:
class SnakeJsonSerializerStrategy : PocoJsonSerializerStrategy
{
protected override string MapClrMemberNameToJsonFieldName(string clrPropertyName)
{
//PascalCase to snake_case
return string.Concat(clrPropertyName.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + char.ToLower(x).ToString() : x.ToString()));
}
}
然后在代碼中使用:
SimpleJson.CurrentJsonSerializerStrategy = new SnakeJsonSerializerStrategy();
五、認證##
RestSharp包含HTTP認證,可以通過IAuthenticator 完成自己的實現同時用RestClient注冊:
var client = new RestClient();
client.Authenticator = new SuperAuthenticator(); // implements IAuthenticator
在使用RestClient.Execute 或 RestClient.Execute
使用SimpleAuthenticator###
SimpleAuthenticator 允許把用戶名和密碼當作GET 或 POST參數傳遞,具體取決於所使用的請求方法:
var client = new RestClient("http://example.com");
client.Authenticator = new SimpleAuthenticator("username", "foo", "password", "bar");
var request = new RestRequest("resource", Method.GET);
client.Execute(request);
請求生成的URL應該是如下形式:http://example.com/resource?username=foo&password=bar
上述請求如果使用PUT或者POST請求時,將會以編碼表單形式提交值。
六、RestRequest的參數類型##
新建了RestRequest 后,可以為它添加參數,下面是5種當前支持的參數類型以及其在使用默認IHttp實現下的特性描述。
Cookie###
添加到cookies 列表的參數將會隨着請求被單獨發送,Cookie名稱是參數的名稱,值則是傳遞的參數的值(.ToString )。
HttpHeader###
添加作為 HTTP header 的參數會隨着請求被單獨發送,Header名稱是參數的名稱,Header值則是傳遞的參數的值。
注意有些受限制的headers表現不同或者會被忽略,可以在Http.cs中的_restrictedHeaderActions 字典中查看它們的特性。
GetOrPost###
如果執行GET請求,RestSharp將會追加參數到URL中,形式如下:“url?name1=value1&name2=value2” ;
如果是POST或者是PUT請求,則取決於請求中是否有文件,如果沒有,則參數以請求體發送,形如“name1=value1&name2=value2” ,將會以application/x-www-form-urlencoded格式發送,基於不同的請求方法會有不同的表現。
兩種情形下,參數名稱和值都會自動被url編碼。
如果請求中有文件,RestSharp將會發送multipart/form-data 形式的請求,發送的參數將會形如以下格式:
Content-Disposition: form-data; name="parameterName"
ParameterValue
UrlSegment###
不同於GetOrPost ,這種參數類型在RequestUrl 中用占位符代替值。
var request = new RestRequest("health/{entity}/status");
request.AddParameter("entity", "s2", ParameterType.UrlSegment);
當執行請求時,RestSharp將嘗試用參數名稱匹配占位符,匹配成功后則用參數值代替占位符,上面的代碼結果是:“health/s2/status” 。
RequestBody###
如果設置了這個參數,參數值會以請求的body方式傳遞。請求只能接收一個RequestBody 參數(第一個)。
參數名稱將被用作請求的Content-Type header 。
RequestBody 參數對於GET或者HEAD 是無效的,它們不需要發送請求體。
如果同時還有GetOrPost 參數,則該參數將重寫RequestBody ——RestSharp 不會合並這些參數,但會拋棄RequestBody 參數。
QueryString###
類似於GetOrPost ,除此之外,它總是用如下形式追加參數到URL:“url?name1=value1&name2=value2” ,不管是什么類型的請求方法。
七、緩存##
自動緩存管理###
RestSharp 102.4 +版本支持所有IRestClient 實例的請求共享同一個System.Net.CookieContainer 管理,通過這種方式,responses 設置或沒設置緩存在后續的請求中都會使用,為了共享CookieContainer ,在創建RestClient 時設置屬性即可:
var client = new RestClient("http://server/");
client.CookieContainer = new System.Net.CookieContainer();
八、跨平台支持##
RestSharp包含2個版本的lib:
- .NET Framework 4.5.2
- .NET Standard 2.0
意味着可以在以下平台應用RestSharp:
- Windows using .NET Framework
- Windows using .NET Core
- Linux or Mac using Mono
- Linux or Mac using .NET Core
- Any other platform that supports Mono 5 or .NET Core 2