.net core 调用外部api

第三方 API 概览
我们将开发一个允许用户输入国家代码和年份的应用程序,然后我们将调用第三方 API 来获取该特定国家在该特定年份的公共假期列表。我们将使用的第三方 API 称为 Nager.Date,这是一个全球公共假期 API。
在这里插入图片描述
这是一个非常简单的 API,您可以通过输入以下 URL 在 Postman 中轻松测试此 API。
https://date.nager.at/api/v2/PublicHolidays/2020/US

该 API 的响应是 JSON 格式的公共假期列表,如下所示:
在这里插入图片描述

了解 HttpClient 对象
允许我们在 ASP.NET Core 应用程序中使用第三方 API 的最常见和众所周知的类是 HttpClient 类。此类使我们能够向第三方 API 发送 HTTP 请求并接收从这些 API 返回的 HTTP 响应。 HttpClient 的每个实例都维护着自己的连接池,这使得它可以将自己的请求与其他 HttpClient 实例执行的请求隔离开来。此类还充当更特定 HTTP 客户端的基类。例如,您可以创建 FacebookHttpClient 或 TwitterHttpClient 作为基本 HttpClient 的子类,并且可以使用这些特定的 HTTP 客户端与 Facebook 和 Twitter API 进行通信。

建议创建一个 HttpClient 实例并在整个应用程序生命周期中重复使用它。这是因为为每个请求实例化一个新的 HttpClient 实例很容易耗尽重负载下可用的套接字数量。这主要是因为当 HttpClient 对象被释放,底层套接字不会立即释放。 您可以阅读这篇精彩的博客文章您使用 HttpClient 错误,这会破坏您的软件的稳定性,以获取有关我刚刚提到的问题的更多信息。

在 ASP.NET Core 中使用 HttpClient
正如我上面提到的,我们将创建一个应用程序,允许用户查看任何国家/地区的公共假期列表。让我们创建一个 ASP.NET Core MVC Web 应用程序并创建以下接口。这个接口只有一个 GetHolidays 方法,它有两个参数 countryCode 和 year,我们很快就会从用户那里收到。

public interface IHolidaysApiService
{
    Task<List<HolidayModel>> GetHolidays(string countryCode, int year);
}
上面的 GetHolidays 方法返回一个 HolidayModel 列表,它是一个模型类,具有与 Nager.Date API 的响应映射的属性。

public class HolidayModel
{
    public string Name { get; set; }
    public string LocalName { get; set; }
    public DateTime? Date { get; set; }
    public string CountryCode { get; set; }
    public bool Global { get; set; }
}
接下来,我们需要实现一个 HolidaysApiService 类,该类将实现上面声明的 IHolidaysApiService。请注意我是如何在类中声明私有和静态 HttpClient 变量的,以及它是如何在类的静态构造函数中定义的。这是 Microsoft 官方文档中提到的创建 HttpClient 实例的推荐方法。

public class HolidaysApiService : IHolidaysApiService
{
    private static readonly HttpClient client;
 
    static HolidaysApiService()
    {
        client = new HttpClient()
        {
            BaseAddress = new Uri("https://date.nager.at")
        };
    }
}
接下来我们需要定义 GetHolidays 方法,如下所示:

public async Task<List<HolidayModel>> GetHolidays(string countryCode, int year)
{
    var url = string.Format("/api/v2/PublicHolidays/{0}/{1}", year, countryCode);
    var result = new List<HolidayModel>();
    var response = await client.GetAsync(url);
    if (response.IsSuccessStatusCode)
    {
        var stringResponse = await response.Content.ReadAsStringAsync();
 
        result = JsonSerializer.Deserialize<List<HolidayModel>>(stringResponse,
            new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
    }
    else
    {
        throw new HttpRequestException(response.ReasonPhrase);
    }
 
    return result;
}
上面的方法发生了很多事情,所以让我详细解释一下:

第一行是构建 Nager.Date API 的 URL 并使用 year 和 countryCode 参数
var url = string.Format("/api/v2/PublicHolidays/{0}/{1}", year, countryCode);
接下来,我们将使用 GetAsync 方法进行 API 调用,该方法将 GET 请求作为异步操作发送到指定的 Uri。该方法返回 System.Net.Http.HttpResponseMessage 对象,该对象表示包含状态代码和数据的 HTTP 响应消息。
var response = await client.GetAsync(url);
接下来,我们调用 ReadAsStringAsync 方法将 HTTP 内容序列化为字符串
var stringResponse = await response.Content.ReadAsStringAsync();
最后,我们使用 JsonSerializer 将 JSON 响应字符串反序列化为 HolidayModel 对象列表。
result = JsonSerializer.Deserialize<List<HolidayModel>>(stringResponse,
    new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
这就是我们使用第三方公共假期 API 所需的全部内容。要使用我们的 HolidaysApiService,我们需要首先在 Startup.cs 类中注册我们的服务。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddSingleton<IHolidaysApiService, HolidaysApiService>();
}
接下来,我们可以在 HomeController 中注入我们的 HolidaysApiService 并通过传递我们将在 Index action 方法中接收的 countryCode 和 year 参数来调用 GetHolidays 方法。

public class HomeController : Controller
{
    private readonly IHolidaysApiService _holidaysApiService;
     
    public HomeController(IHolidaysApiService holidaysApiService)
    {
        _holidaysApiService = holidaysApiService;
    } 
     
    public async Task<IActionResult> Index(string countryCode, int year)
    {
        List<HolidayModel> holidays = new List<HolidayModel>();
        holidays = await _holidaysApiService.GetHolidays(countryCode, year);
 
        return View(holidays);
    }
}
最后,我们需要一个 Razor 视图来创建一个表单,用户将在其中输入国家代码和年份。表单将提交给上述 Index 操作,然后该操作将调用 GetHolidays 方法。这是 Index.cshtml Razor 视图的代码,显示了一个 HTML 表单和一个用于显示公共假期的表格。

@model List<HolidayModel>
@{
    ViewData["Title"] = "Home Page";
}
 
<div>
    <h3 class="display-4">Public Holidays Finder</h3>
    <center>
        <form asp-controller="Home" asp-action="Index">
            <table>
                <tr>
                    <td>Country Code: </td>
                    <td><input type="text" id="txtCountryCode" name="CountryCode" /></td>
                    <td>Year: </td>
                    <td><input type="text" id="txtYear" name="Year" /></td>
                    <td><input type="submit" value="Submit" /></td>
                </tr>
            </table>
            <hr />
        </form>
    </center>
    @if (Model != null && Model.Count > 0)
    {
        <table class="table table-bordered table-striped table-sm">
            <thead>
            <tr>
                <th>Date</th>
                <th>Name</th>
                <th>Local Name</th>
                <th>Country Code</th>
                <th>Global</th>
            </tr>
            </thead>
            <tbody>
            @foreach (var item in Model)
            {
                <tr>
                    <td>@item.Date.Value.ToShortDateString()</td>
                    <td>@Html.DisplayFor(modelItem => item.Name)</td>
                    <td>@Html.DisplayFor(modelItem => item.LocalName)</td>
                    <td>@Html.DisplayFor(modelItem => item.CountryCode)</td>
                    <td>@Html.DisplayFor(modelItem => item.Global)</td>
                </tr>
            }
            </tbody>
        </table>
    }
     
</div>
现在是时候测试我们的应用程序,看看我们是否能够使用第三方 API。在 Visual Studio 中按 F5,您将看到类似于以下内容的页面。您可以输入国家代码,例如美国、德国等,以及一年,例如2021,然后单击“提交”按钮,如果一切顺利,您将看到我们的代码调用第三方 API,从 API 中获取公共假期列表并将其显示在页面上。
在这里插入图片描述

使用 IHttpClientFactory 管理 HttpClient 对象
为了使 HttpClient 实例易于管理,并避免上述套接字耗尽问题,.NET Core 2.1 引入了 IHttpClientFactory 接口,可用于通过依赖注入 (DI) 在应用程序中配置和创建 HttpClient 实例。为了使用 IHttpClientFactory,我们可以通过调用 AddHttpClient(IServiceCollection) 在 Startup.cs 文件中注册它。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
 
    services.AddSingleton<IHolidaysApiService, HolidaysApiService>();
 
    services.AddHttpClient("PublicHolidaysApi", c => c.BaseAddress = new Uri("https://date.nager.at"));
}
可以使用 AddHttpClient 方法注册多个具有不同名称的 HTTP 客户端。 AddHttpClient 方法的第一个参数是客户端的名称,第二个参数是将配置 HttpClient 的 Lamba 表达式。在上面的示例中,我使用要使用此特定 HTTP 客户端调用的第三方 API 的 URL 来设置 BaseAddress 属性。

一旦 HTTP 客户端被注册,我们就可以在我们的控制器和服务中注入 IHttpClientFactory 并调用它的 CreateClient 方法来创建我们想要在我们的代码中使用的特定 HTTP 客户端对象。 CreateClient 方法需要您要创建的 HTTP 客户端的名称,如下所示:

public class HolidaysApiService : IHolidaysApiService
{
    private readonly HttpClient client;
 
    public HolidaysApiService(IHttpClientFactory clientFactory)
    {
        client = clientFactory.CreateClient("PublicHolidaysApi");
    }
 
    public async Task<List<HolidayModel>> GetHolidays(string countryCode, int year)
    {
        var url = string.Format("/api/v2/PublicHolidays/{0}/{1}", year, countryCode);
        var result = new List<HolidayModel>();
        var response = await client.GetAsync(url);
        if (response.IsSuccessStatusCode)
        {
            var stringResponse = await response.Content.ReadAsStringAsync();
 
            result = JsonSerializer.Deserialize<List<HolidayModel>>(stringResponse,
                new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
        }
        else
        {
            throw new HttpRequestException(response.ReasonPhrase);
        }
 
        return result;
    }
}
总结概括
在本文中,我向您概述了 HttpClient,并提供了直接或使用 IHttpClientFactory 创建 HttpClient 对象的示例。我还向您展示了一个使用 HttpClient 调用第三方 Web API 的示例。希望您现在熟悉 HttpClient 对象及其用法,并且可以放心地开始在您的项目中使用它。

posted on 2022-04-24 17:29 青蛙學堂 阅读(1019) 评论(0)  编辑 收藏 引用 所属分类: c#

只有注册用户登录后才能发表评论。
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

常用链接

留言簿(8)

随笔分类

随笔档案

收藏夹

青蛙学堂

最新评论

阅读排行榜

评论排行榜