介绍
RestSharp 的主要目的是通过 HTTP 对远程资源进行同步和异步调用。顾名思义,RestSharp 的主要受众是使用 REST API 的开发人员。但是,RestSharp 可以通过 HTTP(但不是 HTTP/2)调用任何 API,只要您拥有符合 W3C HTTP 标准的资源 URI 和要发送的请求参数。 .NET 开发人员使用 HTTP API 的主要挑战之一是处理不同类型的请求和响应,并将它们转换为复杂的 C# 类型。RestSharp 可以负责将请求正文序列化为 JSON 或 XML 并反序列化响应。它还可以根据不同的参数类型(路径、查询、表单或正文)形成有效的请求 URI。 查看[入门](
https://www.yuque.com/lengda/dyh56h/rgc1qp)页面以了解如何在您的应用程序中使用 RestSharp。
入门
在您的应用程序中使用 RestSharp 之前,您需要添加 NuGet 包。您可以使用 IDE 或命令行执行此操作:
dotnet add package RestSharp
基本用法
如果您只有少数一次性请求要向 API 发出,您可以像这样使用 RestSharp:
using RestSharp;
using RestSharp.Authenticators;
var client = new RestClient("https://api.twitter.com/1.1");
client.Authenticator = new HttpBasicAuthenticator("username", "password");
var request = new RestRequest("statuses/home_timeline.json", DataFormat.Json);
var response = client.Get(request);
IRestResponse 包含从远程服务器返回的所有信息。您可以访问标头、内容、HTTP 状态等。 我们建议使用通用重载,例如 Get
异步调用
所有同步方法都有它们对应的异步方法,后缀为 Async。 因此,您可以使用 GetAsync
using RestSharp;
using RestSharp.Authenticators;
var client = new RestClient("https://api.twitter.com/1.1");
client.Authenticator = new HttpBasicAuthenticator("username", "password");
var request = new RestRequest("statuses/home_timeline.json", DataFormat.Json);
var timeline = await client.GetAsync(request, cancellationToken);
然而,最重要的区别在于,以 HTTP 方法命名的异步方法返回的是 Task
https://www.yuque.com/lengda/dyh56h/sne7td)阅读有关 RestSharp 如何处理异常的信息。
内容类型
RestSharp 支持将 XML 或 JSON 正文作为请求的一部分发送。要将主体添加到请求中,只需调用 IRestRequest 实例的 AddJsonBody 或 AddXmlBody 方法即可。 使用这些方法时无需设置 Content-Type 或添加 DataFormat 参数到请求中,RestSharp 会为您完成。 RestSharp 还将处理 XML 和 JSON 响应并执行所有必要的反序列化任务,具体取决于服务器响应类型。因此,如果您想手动反序列化响应,您只需要添加 Accept 标头。 例如,您只需要这些行来发出携带 JSON 正文的请求:
var request = new RestRequest("address/update")
.AddJsonBody(updatedAddress);
var response = await client.PostAsync(request);
响应
当您使用 Execute 或 ExecuteAsync 时,您将获得一个返回的具有 Content 属性的 IRestResponse 实例,其中包含字符串形式的响应。您可以在那里找到其他有用的属性,例如StatusCode,ContentType 等等。如果请求不成功,您将收到一个响应,其 IsSuccessful 属性设置为 false 以及 ErrorException 和 ErrorMessage 属性中解释的错误。 使用泛型 Execute
IRestClient.ThrowOnAnyError 属性设置为 true。通过这样做,您告诉 RestSharp 在出现问题时抛出异常。然后,您可以将调用包装在 try/catch 块中并相应地处理异常。要了解有关 RestSharp 如何处理异常的更多信息,请参阅[异常处理](
https://www.yuque.com/lengda/dyh56h/sne7td)页面。
推荐用法
RestSharp 最适合作为 API 代理类的基础。以下是来自[Twilio](
http://github.com/twilio/twilio-csharp)库的几个示例。 创建一个类以包含您的 API 代理实现,并使用 Execute 方法将所有请求汇集到 API。这允许您设置跨请求共享的常用参数和其他设置(如身份验证)。因为每个请求都需要帐户 ID 和密钥,所以在创建代理的新实例时,您需要传递这两个值。
警告 请注意,`Execute` 不会抛出异常,但在 `ErrorException` 属性中可用。
// TwilioApi.cs
public class TwilioApi
{
const string BaseUrl = "https://api.twilio.com/2008-08-01";
readonly IRestClient _client;
string _accountSid;
public TwilioApi(string accountSid, string secretKey)
{
_client = new RestClient(BaseUrl);
_client.Authenticator = new HttpBasicAuthenticator(accountSid, secretKey);
_accountSid = accountSid;
}
public T Execute(RestRequest request) where T : new()
{
request.AddParameter("AccountSid", _accountSid, ParameterType.UrlSegment); // used on every request
var response = _client.Execute(request);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
var twilioException = new Exception(message, response.ErrorException);
throw twilioException;
}
return response.Data;
}
}
接下来,定义一个映射到 API 返回的数据的类。
// 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; }
}
然后添加一个方法来查询 API 以获取特定 Call 资源的详细信息。
// TwilioApi.cs, GetCall method of TwilioApi class
public Call GetCall(string callSid)
{
var request = new RestRequest("Accounts/{AccountSid}/Calls/{CallSid}");
request.RootElement = "Call";
request.AddParameter("CallSid", callSid, ParameterType.UrlSegment);
return Execute(request);
}
这里有一些 RestSharp 负责处理的魔法,所以你不必做。 API 返回 XML,使用默认的 XmlDeserializer xml 被自动检测并反序列化为 Call 对象。默认情况下, RestRequest 是通过 GET HTTP 请求进行的。您可以通过设置 RestRequest 的 Method 属性,或在创建实例时在构造函数中指定方法,来更改此设置(如下所述)。类型参数的 UrlSegment 值根据存在于 Resource 属性值中的匹配标记名称注入到 URL 中。因为 AccountSid 对每个请求都是通用的,所以把它设置在 TwilioApi.Execute。我们指定要开始反序列化的根元素的名称。在这种示例中,返回的 XML 是
// 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("Accounts/{AccountSid}/Calls", Method.POST);
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(request);
}
此示例还演示了 RestSharp 的轻量级验证帮助程序。这些帮助程序允许您在发出请求之前验证提交的值是否有效。在此处阅读有关验证的更多信息。 本示例中所有通过 AddParameter 添加的值都将作为标准编码表单提交,类似于通过网页提交的表单。如果是 GET 样式的请求(GET/DELETE/OPTIONS/HEAD),则参数值将通过查询字符串提交。您还可以使用 AddParameter 添加标头和 cookie 参数。要将对象的所有属性添加为参数,请使用 AddObject。要添加要上传的文件,请使用 AddFile(请求将作为多部分编码形式发送)。要包含 XML 或 JSON 之类的请求正文,请使用 AddXmlBody 或 AddJsonBody。
序列化
RestSharp 内置了 JSON 和 XML 序列化器,无需任何额外的包或配置。还有一些 JSON 序列化程序作为附加包提供。
提示 RestSharp 的默认行为是吞下反序列化错误并在响应的 Data 属性中返回 null。在[错误处理](
https://www.yuque.com/lengda/dyh56h/sne7td)中阅读更多关于它的信息。
默认序列化程序
RestSharp 核心包包括一些用于 JSON 和 XML 格式的默认序列化程序。
JSON
默认的 JSON 序列化程序使用 SimpleJson 的分支版本。它非常简单,在许多情况下无法处理高级场景。我们不打算修复或添加新功能到默认 JSON 序列化器,因为它已经处理了很多情况,当您需要处理更复杂的对象时,请考虑使用下面提到的可选的 JSON 序列化器。 有一个[已知问题](
https://github.com/restsharp/RestSharp/issues/1433),当使用常规的 .NET 日期格式(yyyy-MM-ddTHH:mm:ssZ)时,SimpleJson 不使用 UTC 时区。正如问题中所建议的,可以通过为 SimpleJson 显式设置日期格式来解决:
client.UseSerializer(
() => new JsonSerializer { DateFormat = "yyyy-MM-ddTHH:mm:ss.FFFFFFFZ" }
);
XML
您可以使用默认的 XML 序列化程序或 DotNetXmlSerializer,后者使用 .NET 的 System.Xml.Serialization 库。要使用 DotNetXmlSerializer 您需要配置 REST 客户端实例:
client.UseDotNetXmlSerializer();
NewtonsoftJson(又名Json.NET)
该 NewtonsoftJson 包是最流行的 .NET JSON 序列化程序。它处理所有可能的场景并且非常可配置。这种灵活性伴随着性能成本。如果您需要一些速度更快的,请查看 Utf8Json 或 System.Text.Json 序列化程序(如下)。 RestSharp 通过单独的包支持 Json.Net 序列化程序。您可以从 NuGet 安装它:
dotnet add package RestSharp.Serializers.NewtonsoftJson
使用包提供的扩展方法来配置客户端:
client.UseNewtonsoftJson();
序列化器配置了一些默认选项:
JsonSerializerSettings DefaultSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
DefaultValueHandling = DefaultValueHandling.Include,
TypeNameHandling = TypeNameHandling.None,
NullValueHandling = NullValueHandling.Ignore,
Formatting = Formatting.None,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};
如果您需要使用不同的设置,您可以提供您的 JsonSerializerSettings 实例作为扩展方法的参数。
Utf8json
众所周知,Utf8Json 包是最快的 .NET JSON 序列化程序。 RestSharp 通过单独的包支持 Utf8Json 序列化程序。您可以从 NuGet 安装它:
dotnet add package RestSharp.Serializers.Utf8Json
使用扩展方法配置您的 REST 客户端:
client.UseUtf8Json();
不带参数调用扩展方法时,会配置默认选项: - 允许私有属性 - 排除空值 - 使用驼峰式 如果需要使用不同的选项,可以提供 IJsonFormatterResolver 实例作为扩展方法的参数。
警告 请记住,默认情况下,此序列化程序区分大小写。
System.Text.Json
Microsoft 将新的 JSON 序列化程序包 System.Text.Json 包含在 .NET Core 3 内。它是一个小型且快速的序列化程序,默认情况下用于 .NET Core 3 及更高版本的 WebApi 版本。该包也可用于 .NET Standard 2.0 和 .NET Framework 4.6.1 及更高版本。 RestSharp 通过单独的包支持 System.Text.Json 序列化程序。您可以从 NuGet 安装它:
dotnet add package RestSharp.Serializers.SystemTextJson
使用扩展方法配置您的 REST 客户端:
client.UseSystemTextJson();
除非您向扩展方法提供自己的 JsonSerializerOptions 实例,否则序列化程序将使用默认选项。
警告 请记住,默认情况下,此序列化程序区分大小写。
自定义
您还可以实现自定义序列化程序。要同时支持序列化和反序列化,您必须实现该 IRestSerializer 接口。 这是一个使用 System.Text.Json 自定义序列化程序的示例:
public class SimpleJsonSerializer : IRestSerializer
{
public string Serialize(object obj) => JsonSerializer.Serialize(obj);
public string Serialize(Parameter bodyParameter) => Serialize(bodyParameter.Value);
public T Deserialize(IRestResponse response) => JsonSerializer.Deserialize(response.Content);
public string[] SupportedContentTypes { get; } =
{
"application/json", "text/json", "text/x-json", "text/javascript", "*+json"
};
public string ContentType { get; set; } = "application/json";
public DataFormat DataFormat { get; } = DataFormat.Json;
}
SupportedContentTypes 属性的值将和响应 Content-Type 标头一起用于匹配序列化程序。 ContentType 属性将在发出请求时使用,以便服务器知道如何处理有效负载。
处理文件
这是一个示例,它将使用 Stream 来避免请求内容的内存缓冲。在检索将立即写入磁盘的大量数据时很有用。
var tempFile = Path.GetTempFileName();
using var writer = File.OpenWrite(tempFile);
var client = new RestClient(baseUrl);
var request = new RestRequest("Assets/LargeFile.7z");
request.ResponseWriter = responseStream =>
{
using (responseStream)
{
responseStream.CopyTo(writer);
}
};
var response = client.DownloadData(request);
鉴权
RestSharp 包括用于基本 HTTP(授权标头)、NTLM 和基于参数的系统的鉴权。
使用 SimpleAuthenticator
SimpleAuthenticator 允许传递用户名和密码(或API和密钥)作为请求方法的 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 将上述请求更改为使用 POST 或 PUT 会将值作为编码的表单值发送。
基本认证
OAuth1
JWT
自定义鉴权
您可以通过 IAuthenticator 来编写自己的实现,并在您的 RestClient 中注册:
var client = new RestClient();
client.Authenticator = new SuperAuthenticator(); // implements IAuthenticator
Authenticate 方法是调用 RestClient.Execute 或 RestClient.Execute
请求参数
创建 RestRequest 之后,您可以向其添加参数。这是使用默认 IHttp 实现时当前支持的 5 种类型及其行为的描述。
Cookie
将参数添加到与请求一起发送的 cookie 列表中。cookie 名称是参数的名称,值是您传入的 Value.ToString()。
Http Header
添加参数作为与请求一起发送的 HTTP 标头。header 名称是参数的名称,header 值是参数的值。 请注意,有一些受限制的标头可能表现不同或被简单地忽略。请查看 _restrictedHeaderActions 字典 Http.cs 以了解哪些 header 是特殊的以及它们的行为方式。
Get 或 Post
这取决于方法的不同表现。如果您执行 GET 调用,RestSharp 会将参数以 url?name1=value1&name2=value 的形式附加到 Url 中。 在 POST 或 PUT 请求中,这取决于您是否有文件附加到请求中。如果没有,参数将作为请求的正文以 name1=value1&name2=value2 的形式发送。此外,请求将作为
application/x-www-form-urlencoded 发送。 在这两种情况下,名称和值都将自动进行 url 编码。 如果您有文件,RestSharp 将发送 multipart/form-data 请求。您的参数将以如下形式作为此请求的一部分:
Content-Disposition: form-data; name="parameterName"
ParameterValue
Url 分段
与 GetOrPost 不同, ParameterType 替换 RequestUrl 中的占位符值:
var request = new RestRequest("health/{entity}/status")
.AddUrlSegment("entity", "s2");
当请求执行时,RestSharp 将尝试用该名称的参数(不带 {} )匹配 {placeholder} 与并将其替换为值。所以上面的代码结果是 url health/s2/status。
请求体
如果设置了这个参数,它的值将作为请求的正文发送。只有一个 RequestBody 参数会被接受——第一个。 参数的名称将用作 Content-Type 请求标头。 RequestBody 不适用于 GET 或 HEAD 请求,因为它们不发送正文。 如果您也有 GetOrPost 参数,它们将覆盖 RequestBody ——RestSharp 不会组合它们,而是将 RequestBody 参数扔掉。 我们推荐使用 AddJsonBody 或 AddXmlBody 方法而不是使用 AddParameter 携带类型 BodyParameter。这些方法将设置正确的请求类型并为您执行序列化工作。
AddJsonBody
当您调用 AddJsonBody 时,它会为您执行以下操作: - 指示 RestClient 在发出请求时将对象参数序列化为 JSON - 将内容类型设置为 application/json - 将请求正文的内部数据类型设置为 DataType.Json 不要设置内容类型标头或发送 JSON 字符串或某种 JObject 实例到 AddJsonBody ,它不会工作! 示例如下:
var param = new MyClass { IntData = 1, StringData = "test123" };
request.AddJsonBody(param);
AddXmlBody
当您调用 AddXmlBody 时,它会为您执行以下操作: - 指示 RestClient 在发出请求时将对象参数序列化为 XML - 将内容类型设置为 application/xml - 将请求正文的内部数据类型设置为 DataType.Xml 不要设置内容类型标头或将 XML 字符串发送到 AddXmlBody ,它不会工作!
Query String
这与 GetOrPost 类似,不同之处在于它总是将参数以 url?name1=value1&name2=value2 的形式附加到 url,而不管请求方法如何。 例子:
var client = new RestClient("https://search.me");
var request = new RestRequest("search")
.AddParameter("foo", "bar");
var response = await client.GetAsync(request);
它将发送 GET 请求到 https://search.me/search?foo=bar 。 您还可以明确指定查询字符串参数类型:
request.AddParameter("foo", "bar", ParameterType.QueryString);
在某些情况下,您可能需要阻止 RestSharp 对查询字符串参数进行编码。为此,请使用 QueryStringWithoutEncode 参数类型。
异常处理
如果存在网络传输错误(网络关闭、DNS 查找失败等)或任何类型的服务器错误(404 除外),
RestResponse.ResponseStatus 将设置为 ResponseStatus.Error,否则为 ResponseStatus.Completed。 如果 API 返回 404,ResponseStatus 仍将是 Completed 。如果您需要访问返回的 HTTP 状态代码,您可以在 RestResponse.StatusCode 中找到它。 Status 属性是独立于 API 异常处理的完成指示符。 通常,如果请求失败,RestSharp 不会抛出异常。 然而,可以配置 RestSharp 在不同情况下抛出。
追求更好阅读体验的同学推荐查看本人语雀原文,链接如下:
本文暂时没有评论,来添加一个吧(●'◡'●)