如何在 ASP.NET Core 中使用第三方 Web API


在這里插入圖片描述

在現代 Web 應用程序中,調用第三方 Web API 來增強應用程序的功能是很常見的。有數以千計的免費和商業 API 可用,如果您知道如何在 ASP.NET Core 應用程序中使用這些 API,您就可以構建非常強大的業務應用程序。在這篇文章中,我將解釋如何在 ASP.NET Core 應用程序中使用第三方 Web API。

下載:Download Source Code

第三方 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 對象及其用法,並且可以放心地開始在您的項目中使用它。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM