zoukankan      html  css  js  c++  java
  • 深入浅出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();
        }
       
    }

    ===================================
    开放的 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/

  • 相关阅读:
    在IIS上启用Gzip压缩(HTTP压缩)
    跨数据库服务器查询和跨表更新
    GOOGLE高级搜索的秘籍
    NET中的规范标准注释(二) -- 创建帮助文档入门篇
    NET中的规范标准注释(一) -- XML注释标签讲解
    如何取出word文档里的图片
    System帐户!我使用你登陆
    横竖两个数字塔的效果BAT批处理怎么写?
    用批处理修改日期,然后在改回来
    根据日期计算星期几----蔡勒(Zeller)公式推导
  • 原文地址:https://www.cnblogs.com/harrychinese/p/blazor_httpclient.html
Copyright © 2011-2022 走看看