ASP.NET Core 2.1 中的 HttpClientFactory (Part 2) 定義命名化和類型化的客戶端

来源:https://www.cnblogs.com/lookerblue/archive/2019/07/02/11120361.html
-Advertisement-
Play Games

原文:https://www.stevejgordon.co.uk/httpclientfactory-named-typed-clients-aspnetcore 發表於:2018年1月 原文:https://www.stevejgordon.co.uk/httpclientfactory-nam ...


原文:https://www.stevejgordon.co.uk/httpclientfactory-named-typed-clients-aspnetcore  
發表於:2018年1月

      上一篇文章《HttpClientFactory簡介》我解釋了創建該功能的原因。我們知道了它可以解決的問題,然後例舉了一個非常基本的示例展示瞭如何在WebAPI應用程式中使用它。在這篇文章中,我想深入探討另外兩種可以使用它的方法:命名化客戶端(named clients)和類型化客戶端(typed clients)。

命名化客戶端(Name Clients)

      在第一篇文章中,我演示瞭如何使用HttpClientFactory來獲取基本的HttpClient實例。當您只需要從單一位置發出快速請求時,這很好。但通常,您可能希望從代碼中的多個位置向同一服務發出多個請求。
      通過命名化客戶端的概念,HttpClientFactory使這一點變得更容易。使用命名化客戶端,您可以創建一個註冊,其中包含在創建HttpClient時的一些特定配置。您可以註冊多個命名化客戶端,每個客戶端都可以預先配置不同的設置。
      為了讓這個概念更具體一些,讓我們看一個例子。在我的Startup.ConfigureServices方法中,使用AddHttpClient的不同重載方法,該方法接受兩個附加參數。把一個名稱和一個Action委托“告訴”HttpClient。ConfigureServices代碼:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient("GitHubClient", client =>
    {
        client.BaseAddress = new Uri("https://api.github.com/");
        client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
        client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactoryTesting");
    });

    services.AddMvc();
}

      第一個字元串參數是用於此客戶端註冊的名稱。Action <HttpClient>委托允許我們在為我們構造HttpClient時配置它們。這非常方便,因為我們可以預先定義一個基地址和一些已知的請求頭。當我們請求命名化客戶端時,會為我們創建一個新客戶端,並且每次都會應用此配置。
      使用的時候,CreateClient根據名稱來請求一個客戶端:

[Route("api/[controller]")]
public class ValuesController : Controller
{
    private readonly IHttpClientFactory _httpClientFactory;

    public ValuesController(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    [HttpGet]
    public async Task<ActionResult> Get()
    {
        var client = _httpClientFactory.CreateClient("GitHubClient");
        var result = await client.GetStringAsync("/");

        return Ok(result);
    }
}

      在這個例子中,我們創建的HttpClient實例已經有基本地址集(base address set),所以我們的GetStringAsync方法傳入對應的URI即可。

      這種命名化的方式使我們能夠控制應用於HttpClient的配置。我不是“魔力字元串”的忠實粉絲,所以如果我使用命名客戶端,我可能會有一個靜態類,其中包含客戶端名稱的字元串常量。像這樣:

public static class NamedHttpClients
{
    public const string GitHubClient = "GitHubClient";
}

      註冊(或請求)客戶端時,我們可以使用靜態類值,而不是“魔力字元串”:

services.AddHttpClient(NamedHttpClients.GitHubClient, client =>
{
    client.BaseAddress = new Uri("https://api.github.com/");
    client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
    client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactoryTesting");
});

      這非常好,但我們可以更進一步,來看看如何使用自定義的類型化客戶端。

類型化客戶端(Typed Clients)

      類型化客戶端允許我們定義一個通過構造函數註入HttpClient的自定義類。這樣我們可以使用IHttpClientBuilder的擴展方法鏈接DI系統,或者使用泛型AddHttpClient方法來接收自定義類型。一旦我們有了自定義類,我們就可以直接公開HttpClient,也可以將Http calls封裝在特定方法中,從而更好地定義外部服務的使用。這種方法也意味著我們不再需要“魔術字元串”,並且看起來更加合理。
      讓我們看一個自定義類型化客戶端的基本例子:

public class MyGitHubClient
{
    public MyGitHubClient(HttpClient client)
    {
        Client = client;
    }

    public HttpClient Client { get; }
}

      這個類需要在構造函數中接受作為參數的HttpClient。現在,我們已經為HttpClient的實例設置了一個公共屬性。
      然後,我們需要在ConfigureServices中註冊:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient<MyGitHubClient>(client =>
    {
        client.BaseAddress = new Uri("https://api.github.com/");
        client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
        client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactoryTesting");
    });

    services.AddMvc();
}

      我們將MyGitHubClient作為泛型參數傳遞給AddHttpClient。它在DI系統中被註冊為transient scope。由於我們的自定義類接受HttpClient,因此相關聯的“工廠”會創建一個適當配置的HttpClient實例,並註入它。現在可以更新控制器以接受我們的類型化客戶端而不是IHttpClientFactory:

[Route("api/[controller]")]
public class ValuesController : Controller
{
    private readonly MyGitHubClient _gitHubClient;

    public ValuesController(MyGitHubClient gitGitHubClient)
    {
        _gitHubClient = gitGitHubClient;
    }

    [HttpGet]
    public async Task<ActionResult> Get()
    {
        var result = await _gitHubClient.Client.GetStringAsync("/");
        return Ok(result);
    }
}

      由於我們自定義的類型化客戶端通過屬性公開了HttpClient,因此我們可以直接使用它進行HTTP調用。

封裝HttpClient(Encapsulating the HttpClient)

      最後一個例子是我們想要完全封裝HttpClient的情況。當我們想要定義處理對端點的特定調用的方法時,最有可能使用此方法。此時,我們還可以在每個方法中封裝響應和反序列化的驗證,以便在單一位置處理它。

public interface IMyGitHubClient
{
    Task<int> GetRootDataLength();
}

public class MyGitHubClient : IMyGitHubClient
{
    private readonly HttpClient _client;

    public MyGitHubClient(HttpClient client)
    {
        _client = client;
    }

    public async Task<int> GetRootDataLength()
    {
        var data = await _client.GetStringAsync("/");
        return data.Length;
    }
}

      這種情況下,我們通過private readonly欄位存儲了在構造中註入的HttpClient。與直接通過此類(class)獲得HttpClient不同,我們提供了一個GetRootDataLength方法來執行Http調用並返回請求長度。一個簡單的例子,但你應該已經明白了!
      我們現在可以更新控制器以接受和使用介面,如下所示:

[Route("api/[controller]")]
public class ValuesController : Controller
{
    private readonly IMyGitHubClient _gitHubClient;

    public ValuesController(IMyGitHubClient gitHubClient)
    {
        _gitHubClient = gitHubClient;
    }

    [HttpGet]
    public async Task<ActionResult> Get()
    {
        var result = await _gitHubClient.GetRootDataLength();
        return Ok(result);
    }
}

      我們現在可以調用介面上定義的GetRootDataLength方法,而無需直接與HttpClient交互。這對測試非常有用,現在可以在我們想要測試這個控制器時輕鬆模擬IMyGitHubClient。過去測試HttpClient有點痛苦,按照我通常習慣的方式會有更多代碼。
      在DI容器中註冊,ConfigureServices變為:

services.AddHttpClient<IMyGitHubClient, MyGitHubClient>(client =>
{
    client.BaseAddress = new Uri("https://api.github.com/");
    client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
    client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactoryTesting");
});

      AddHttpClient有一個接受兩個泛型參數的簽名,對應DI中的簽名。

總結

      在這篇文章中,我們探討了HttpClientFactory一些更高級的方法,它允許我們使用特定的命名配置創建不同的HttpClient實例。然後我們討論了使用類型化客戶端,通過擴展實現了我們自己的類,它接受HttpClient實例。我們可以直接公開HttpClient,也可以將調用封裝到此類中來訪問遠程端點。
      下一篇文章,我們將討論使用DelegatingHandlers來實現“傳出請求中間件”( outgoing request middleware)的另一種模式。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 自己用的番茄鐘自己做 在PC上我一直使用“小番茄”作為我的番茄鐘軟體,我把它打開後放在副顯示器最大化,這樣不僅可以讓它盡到本分,而且還可以告訴我的同事“我正在專心工作”。可是我總是嫌棄它的手感不夠愉悅,總想自己寫一個番茄鐘軟體,正好最近很久沒寫UWP應用了很手癢,於是就抽空寫了個自用的番茄鐘並 ...
  • 本文包括兩個部分: WebApi中使用swagger 項目打開之後,選擇 引用,右鍵,管理NuGet程式包 瀏覽,搜索swagger,選擇第一個swashbuckle,安裝 安裝好之後,右鍵項目,選擇屬性,生成,在下麵的輸出那裡勾選:XML文檔文件,如果沒有自動填充好路徑,需要自己填寫一下,文件名可 ...
  • ARR是應用級別的負載均衡方案,ARR只能做請求入口的分發服務,而NLB則是伺服器級別的負載均衡方案。我們將二者結合起來,形成高可用最佳方案。 ...
  • C#中的這個幾個關鍵字:explicit、implicit與operator,估計好多人的用不上,什麼情況,這是什麼?字面解釋:explicit:清楚明白的;易於理解的;(說話)清晰的,明確的;直言的;坦率的;直截了當的;不隱晦的;不含糊的。implicit:含蓄的;不直接言明的;成為一部分的;內含 ...
  • 使用ItemContainerGenerator.ContainerFromItem方法可以獲取對應數據的UIElement 。 但是如果使用了虛擬化技術,超出可見區域的UIElement就獲取不到了。 參考微軟的文檔《如何:在 TreeView 中查找 TreeViewItem》,去掉一些不必要的 ...
  • 本文分別說明.NET CORE與Spring Boot 編寫控制台程式應有的“正確”方法,以便.NET程式員、JAVA程式員可以相互學習與加深瞭解,註意本文只介紹用法,不會刻意強調哪種語言或哪種框架寫的控制台程式要好。 本文所說的編寫控制台程式應有的“正確”方法,我把正確二字加上引號,因為沒有絕對的 ...
  • C# 單例模式 1、定義:單例模式就是保證在整個應用程式的生命周期中,在任何時刻,被指定的類只有一個實例,併為客戶程式提供一個獲取該實例的全局訪問點。 2、單例模式的優點有: (1)實例控制:單例模式會阻止其他對象實例化其自己的單例對象的副本,從而確保所有對象都訪問唯一實例。 (2)靈活性:因為類控 ...
  • DES(Data Encryption Standard)的加密與MD5不同,DES可以解密,而MD5的加密是不可逆的;用於數字簽名和數據加密,對稱加密-即加密秘鑰和解密秘鑰相同。標準的DES密鑰長度為64bit,密鑰每個字元占7bit,外加1bit的奇偶校驗,64/(7+1)=8;所以必須是8個字 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...