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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...