深入淺出Blazor webassembly之HttpClient使用


===================================
參考
===================================

https://www.cnblogs.com/deepthought/p/11303015.html

https://www.cnblogs.com/willick/p/net-core-httpclient.html

技術譯民翻譯的博客  https://www.cnblogs.com/ittranslator/p/making-http-requests-in-blazor-webassembly-apps.html

 

===================================
直接使用 HttpClient 的問題
===================================

HttpClient 類所在庫為 System.Net.Http,

Blazor webassembly 默認模版已經自動將HttpClient 注冊到DI 容器中了, 使用起來非常方便. Program.Main 函數注冊DI容器代碼:

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

 

直接使用 HttpClient 問題有:

  • HttpClient 主要問題是, 即使 Dispose 之后, 也不能即時關閉 socket 連接, 在 windows 下, 默認需要等 240秒之后才能關閉 socket. 短時大量使用 HttpClient, 會將客戶端和服務器端 socket 連接消耗殆盡, 詳見參考文檔1的分析.  所以, 客戶端應用程序一般使用單例模式使用 HttpClient 類.   Blazor webassembly 也是如此.
  • 如果使用單例模式,  如要為 不同url 設置不同的 header, 就很不方便.
  • HttpClient 還會緩存 IP, 如果 DNS 之后有更新, HttpClient 仍會使用老的 IP

Net Core2.1 提供的 IHttpClientFactory 解決了直接使用HttpClient的所有問題, IHttpClientFactory 提供了更優雅 Http  Client 功能.

 

===================================
IHttpClientFactory 簡單方法生成 HttpClient
===================================

IHttpClientFactory 所在的類庫是 Microsoft.Extensions.Http ,   將它加到blazor wasm 項目的依賴中,

Program.Main 函數必須使用 AddHttpClient 完成DI容器注冊,  這樣DI容器就能為我們注入 IHttpClientFactory 實例.

builder.Services.AddHttpClient();

 

Razor 頁面使用 IHttpClientFactory 的實例生成 HttpClient 對象. 

@page "/hello"
@inject IHttpClientFactory HttpClientFactory
<div>
    _statusCode: @_statusCode
</div>

@code{

    private string _statusCode = "";
    protected override async Task   OnInitializedAsync()
    {
        var httpClient = HttpClientFactory.CreateClient();

        //gorest.co.in 網站已經開啟 CORS 共享, 所以我們用它來測試, 而不是 https://www.baidu.com
        httpClient.BaseAddress=new Uri("https://gorest.co.in");
        var result = await httpClient.GetAsync("/public/v1/users");
        _statusCode = result.StatusCode.ToString();
    }
}

使用這個簡單的方式,  IHttpClientFactory 注入的實例未經任何初始化, 比如未設置BaseAddress參數,  需要在使用該實例時候, 進行各種設置,  代碼復用性較差.

 

===================================
IHttpClientFactory 采用命名方式生成 HttpClient
===================================

命名方式在使用友好性方面比簡單方式好很多.

注冊DI容器時, AddHttpClient()傳入名稱, 同時還可以為將來的HttpClient對象設置各種參數.

使用時, 先獲取注入的 IHttpClientFactory HttpClient實例, 然后CreateClient()傳入命名值即可得到經過預設的HttpClient對象對象 , 不需要再進行參數設置.

builder.Services.AddHttpClient(name: "gorest", c =>
    {
        c.BaseAddress = new Uri("https://gorest.co.in");
    }
);

 

@page "/hello"
@inject IHttpClientFactory HttpClientFactory
<div>
    _statusCode: @_statusCode
</div>

@code{

    private string _statusCode = "";
    protected override async Task   OnInitializedAsync()
    {
        var httpClient = HttpClientFactory.CreateClient(name: "gorest");  
        var result = await httpClient.GetAsync("/public/v1/users");
        _statusCode = result.StatusCode.ToString();
    }
}

 

===================================
IHttpClientFactory 采用類型化方式生成 HttpClient
===================================

類型化方式比命名方式更進一步, 注冊DI容器時, AddHttpClient()傳入一個泛型類型, 將HttpClient的各種設置轉移到泛型類中

這樣的好處時, AddHttpClient() 方法更簡單, 代碼內聚性更好.

 

包裝了 HttpClient 的泛型類:

  public class GorestHttpService
    {
        private readonly HttpClient _httpClient;
        public GorestHttpService(HttpClient httpClient)
        {
            _httpClient = httpClient;
            _httpClient.BaseAddress = new Uri("https://gorest.co.in"); 
        }

        public  async Task<string> GetStatusCodeAsync()
        {
            var result = await _httpClient.GetAsync("/public/v1/users");
            return result.StatusCode.ToString();
        }
       
    }

 

Program.Main 函數 AddHttpClient 完成DI容器注冊

builder.Services.AddHttpClient<GorestHttpService>();

 

Razor 代碼:

@page "/hello"
@inject GorestHttpService gorestHttpService
<div>
    _statusCode: @_statusCode
</div>

@code{

    private string _statusCode = "";
    protected override async Task   OnInitializedAsync()
    {
        var result = await gorestHttpService.GetStatusCodeAsync();
        _statusCode = result;
    }
}

 

 

===================================
 為 HttpClient 增加 Header
===================================

如需要增加 Bearer Header, 可以通過為 httpClient.DefaultRequestHeaders.Authorization 屬性賦值.

public class GorestHttpService
{
    private readonly HttpClient _httpClient;
    public GorestHttpService(HttpClient httpClient)
    {
        _httpClient = httpClient;
        _httpClient.BaseAddress = new Uri("https://gorest.co.in");
        string token = "changeMe";  
        _httpClient.DefaultRequestHeaders.Authorization= new AuthenticationHeaderValue("Bearer", token);
    }

    public  async Task<string> GetStatusCodeAsync()
    {
        var result = await _httpClient.GetAsync("/public/v1/users");
        return result.StatusCode.ToString();
    }
   
}

 

Jwt token 使用 Bearer head, Basic 驗證使用:

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "base64 user:pwd")

或者加Header 文本:

HttpClient.DefaultRequestHeaders.Add("Authorization", "Bearer <token>");

HttpClient.DefaultRequestHeaders.Add("Authorization", "Basic "+"base64 user:pwd")

 

 

 

===================================
開放的 Rest api 服務
===================================

示例中使用了 GoRest 網站, 它是 Online REST API for Testing and Prototyping  https://gorest.co.in/

一些簡單的api網站 https://mixedanalytics.com/blog/list-actually-free-open-no-auth-needed-apis/

 


免責聲明!

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



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