在C#中使用RESTful API的几种好方法

什么是Restful API

  • REST

    即Representational State Transfer的缩写。直接翻译的意思是"表现层状态转化"。
    它是一种互联网应用程序的API设计理念:URL定位资源,用HTTP动词描述操作。

  • URI

    即统一资源标识符,服务器上每一种资源,比如文档、图像、视频片段、程序 都由一个通用资源标识符(Uniform Resource Identifier, 简称"URI")进行定位。

  • HTTP动词

    • GET(SELECT):从服务器取出资源(一项或多项)。
    • POST(CREATE):在服务器新建一个资源。
    • PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
    • PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
    • DELETE(DELETE):从服务器删除资源。

通过Web开发的路径,您发现自己迟早需要处理外部API(应用程序编程接口)。在本文中,我的目标是列出在C#项目中使用RESTful API的方法的最全面列表,并通过一些简单示例向您展示如何做到这一点。阅读本文之后,您将更深入地了解哪些选项可用,以及下次需要使用RESTful API时如何选择正确的选项.

如何使用RESTful API

有几种方法可以在C#中使用RESTful API:

例如,我们将通过GitHub API收集有关RestSharp发布版本及其发布日期的信息。此信息是公开可用的,您可以在此处查看原始JSON响应的内容:查看RestSharp版本信息

HttpWebRequest / Response类

这是WebRequest 类的特定于HTTP的实现,该实现最初用于处理HTTP请求,但已过时并由WebClient该类代替。
该HttpWebRequest 班提供细粒度控制的要求制定过程的每一个环节。您可以想象,这可能是一把双刃剑,您很容易浪费大量时间来微调您的请求。另一方面,这可能正是您针对特定案例所需要的。
HttpWebRequest 类不会阻止用户界面,也就是说,我相信您会同意这一点,这一点非常重要。
HttpWebResponse 类为传入的响应提供了一个容器。
这是有关如何使用这些类使用API​​的简单示例:

public class HttpWebRequestHandler : IRequestHandler
{
    public string GetReleases(string url)
    {
        var request = (HttpWebRequest)WebRequest.Create(url);
 
        request.Method = "GET";
        request.UserAgent = RequestConstants.UserAgentValue;
        request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
 
        var content = string.Empty;
 
        using (var response = (HttpWebResponse)request.GetResponse())
        {
            using (var stream = response.GetResponseStream())
            {
                using (var sr = new StreamReader(stream))
                {
                    content = sr.ReadToEnd();
                }
            }
        }
 
        return content;
    }
}

尽管是一个简单的示例,但是当您需要处理更复杂的需求(例如,发布表单信息,授权等)时,它会变得更加复杂。

WebClient类

这个类是包装器HttpWebRequest。它通过HttpWebRequest从开发人员中提取的细节来简化流程。该代码更容易编写,并且您通过这种方式犯错误的可能性较小。如果您想编写更少的代码,而不用担心所有细节,并且执行速度是不重要的,请考虑使用WebClientclass。

这个例子应该给你一个大概的想法WebClient,与HttpWebRequest/ HttpWebResponse方法相比,使用起来要容易得多:

public string GetReleases(string url)
{
    var client = new WebClient();
    client.Headers.Add(RequestConstants.UserAgent, RequestConstants.UserAgentValue);
 
    var response = client.DownloadString(url);
 
    return response;
}

除了其他DownloadString方法,WebClient类还提供了许多其他有用的方法。我们可以轻松地使用它来操作字符串,文件或字节数组,代价是性能比HttpWebRequest/ HttpWebResponse方法要慢几毫秒。
无论是HttpWebRequest/ HttpWebResponse和WebClient类在旧版本的.NET可供选择。 WebClient MSDN

HttpClient类

HttpClient 是“new kid on the block”,它提供了旧库所缺乏的一些现代.NET功能。例如,您可以使用的单个实例发送多个请求HttpClient,它不绑定到特定的HTTP服务器或主机,而是使用了异步/等待机制。

您可以在此视频中找到使用HttpClient的五个很好的理由:

  1. 强类型标题。
  2. 共享缓存,cookie和凭据
  3. 访问cookie和共享cookie
  4. 控制缓存和共享缓存。
  5. 将您的代码模块注入ASP.NET管道。清洁和模块化的代码。
    HttpClient在我们的示例中,如下:
public string GetReleases(string url)
{
    using (var httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Add(RequestConstants.UserAgent, RequestConstants.UserAgentValue);
 
        var response = httpClient.GetStringAsync(new Uri(url)).Result;
 
        return response;
    }
}

另外,我还要提到一件事。是否HttpClient应该包装在using块中还是在应用程序级别上进行静态讨论。尽管它实现了IDisposable,但似乎通过将它包装在using块中,会使应用程序出现故障并获得SocketException。静态初始化与动态使用测试
并且不要忘记,由于是现代的,它HttpClient是.NET 4.5专有的,因此在某些旧项目中使用它可能会遇到麻烦。

RestSharp

RestSharp是标准.NET库的OpenSource替代品,也是目前最酷的.NET库之一。它以NuGet软件包的形式提供,出于某些原因,您应该考虑尝试一下。

就像HttpClientRestSharp 一样,它是一个现代而全面的库,易于使用且令人愉悦,同时仍支持旧版本的.NET Framework。它具有内置的身份验证和序列化/反序列化机制,但允许您使用自定义机制覆盖它们。它可跨平台使用,并支持OAuth1,OAuth2,基本,NTLM和基于参数的身份验证。您可以选择同步或异步工作。该库还有很多其他功能,而这些只是它提供的众多好处中的一部分。有关RestSharp的用法和功能的详细信息,您可以访问GitHub上的RestSharp 页面。

现在,让我们尝试使用RestSharp get获取RestSharp版本的列表:

public string GetReleases(string url)
{
    var client = new RestClient(url);
 
    var response = client.Execute(new RestRequest());
 
    return response.Content;
}

很简单。但是请不要让自己愚弄,RestSharp非常灵活,拥有使用RESTful API时几乎实现任何目的所需的所有工具。

在此示例中要注意的一件事是,由于示例的一致性,我没有使用RestSharp的反序列化机制,这有点浪费,但是我鼓励您使用它,因为它确实非常容易和方便。因此,您可以轻松地制作一个这样的Model:

public class GitHubRelease
{
    [JsonProperty(PropertyName = "name")]
    public string Name { get; set; }
    [JsonProperty(PropertyName = "published_at")]
    public string PublishedAt { get; set; }
}

然后使用该Execute方法直接反序列化对该容器的响应。您可以仅添加所需的属性,并使用属性JsonProperty将它们映射到C#属性(很好的触摸)。由于我们在响应中获得了发布列表,因此我们将List 用作包含类型。

public List<GitHubRelease> GetDeserializedReleases(string url)
{
    var client = new RestClient(url);
 
    var response = client.Execute<List<GitHubRelease>>(new RestRequest());
 
    return response.Data;
}

非常简单而优雅的方式来获取我们的数据。

RestSharp不仅具有发送GET请求的功能,还可以自己探索并观察它的酷炫之处。

RestSharp案例中要补充的最后一点是,它的存储库需要维护者。

Flurl

Flurl代表Fluent Url Builder,这是库构建其查询的方式。对于不熟悉流利的做事方式的人来说,流利只是意味着库的构建方式是将方法链接在一起以实现更高的可读性,类似于人类语言。
为了使事情更容易理解,让我们举一些例子(这个例子来自官方文档):

// Flurl will use 1 HttpClient instance per host
var person = await "https://api.com"
    .AppendPathSegment("person")
    .SetQueryParams(new { a = 1, b = 2 })
    .WithOAuthBearerToken("my_oauth_token")
    .PostJsonAsync(new
    {
        first_name = "Claire",
        last_name = "Underwood"
    })
    .ReceiveJson<Person>();

您可以看到方法如何链接在一起以完成“句子”。

在后台,Flurl使用HttpClient或通过自己的语法糖增强HttpClient库。因此,这意味着Flurl是一个异步库,因此请牢记这一点。

与其他高级库一样,我们可以通过两种不同的方式来做到这一点:

public string GetReleases(string url)
{
    var result = url
        .WithHeader(RequestConstants.UserAgent, RequestConstants.UserAgentValue)
        .GetJsonAsync<List<GitHubRelease>>()
        .Result;
 
    return JsonConvert.SerializeObject(result);
}

这种方式相当糟糕,因为我们只序列化结果以便稍后对其进行反序列化。如果您使用的是Flurl之类的库,则不应以这种方式进行操作。

更好的做事方式是:

public List<GitHubRelease> GetDeserializedReleases(string url)
{
    var result = url
        .WithHeader(RequestConstants.UserAgent, RequestConstants.UserAgentValue)
        .GetJsonAsync<List<GitHubRelease>>()
        .Result;
 
    return result;
}

使用.Result,我们将强制代码的同步行为。使用Flurl的实际和预期方式如下所示:

public async Task<List<GitHubRelease>> GetDeserializedReleases(string url)
{
    var result = await url
        .WithHeader(RequestConstants.UserAgent, RequestConstants.UserAgentValue)
        .GetJsonAsync<List<GitHubRelease>>();
 
    return result;
}

这里对Flurl做了简单的展示,易于使用,现代,可读性和可测试性。

更多请查看原文

posted @ 2020-01-19 09:28  非法关键字  阅读(3801)  评论(0编辑  收藏  举报