十二、.net core(.NET 6)添加通用的访问webapi的方法(包括HttpClient和HttpWebRequest)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 开发通用的访问webapi方法。在common工具文件夹下,新建一个类库项目:Wsk.Core.WebHelper,并引用Package包项目,然后新建一个类HttpClientHelper,用于使用HttpClient方法进行访问webapi:


开发通用的访问webapi方法。

 

common工具文件夹下,新建一个类库项目:Wsk.Core.WebHelper,并引用Package包项目,然后新建一个类HttpClientHelper,用于使用HttpClient方法进行访问webapi:

1995789-20210606190523027-1881363596.png

 

新建一个接口IHttpClientHelper,用于HttpClientHelper继承该接口。然后接口内新增一个返回泛型类型的通用的POST访问webapi的方法:

1995789-20210606190552738-1803264386.png

 

接着,在HttpClientHelper类里面,进行对该方法的实现:

1995789-20210606190607859-2066938035.png


说明:虽然使用了using,可以自动释放资源;但是难免还是需要一点时间。在finally下面通过手动释放资源,比自动释放资源,资源释放率会更快,在并发场景下,性能会更好一点点。当然,此处可以不适用using,因为手动释放了,以上纯属个人喜好的风格写法。


再来一个使用Basic加密进行访问的通用方法,写法如上,具体请看代码示例。先新建带用户名和密码参数的接口:

1995789-20210606190726411-1206750832.png

 

然后,在HttpClientHelper里面进行对应的实现:

1995789-20210606190740123-855045588.png

 

以上为使用POST的方式进行,如果需要使用例如GETPUT等,可以自行尝试,写法类似。


接口代码:


public interface IHttpClientHelper
    {
        /// <summary>
        /// 通用访问webapi方法
        /// </summary>
        /// <param name="url"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        T Post<T>(string url, string data);
        /// <summary>
        /// 带用户名和密码的通用访问webapi方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url"></param>
        /// <param name="data"></param>
        /// <param name="account">用户名</param>
        /// <param name="pwd">密码</param>
        /// <returns></returns>
        T Post<T>(string url, string data, string account, string pwd);
    }


实现类代码:


public class HttpClientHelper:IHttpClientHelper
    {
        readonly ILogger<HttpClientHelper> _logger;
        public HttpClientHelper(ILogger<HttpClientHelper> logger)
        {
            _logger = logger;
        }
        public T Post<T>(string url, string data)
        {
            var result = default(T);
            using (HttpClient client = new HttpClient())
            {
                try
                {
                    client.Timeout = new TimeSpan(0, 0, 10); // 10是秒数,用于设置超时时长
                    HttpContent content = new StringContent(data);
                    content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
                    client.DefaultRequestHeaders.Connection.Add("keep-alive");
                    Task<HttpResponseMessage> res = client.PostAsync(url, content);
                    if (res.Result.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        result = JsonConvert.DeserializeObject<T>(res.Result.Content.ReadAsStringAsync().Result);
                    }
                    else
                    {
                        _logger.LogError($"访问webapi方法状态码错误:\r url:{url} \r data:{data} \r 状态码:{res.Result.StatusCode}");
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError($"访问webapi方法异常:\r url:{url} \r data:{data} \r 异常信息:{ex.Message}");
                }
                finally
                {
                    client.Dispose();
                }
            }
            return result;
        }
        public T Post<T>(string url, string data, string account, string pwd)
        {
            var result = default(T);
            using (HttpClient client = new HttpClient())
            {
                try
                {
                    string authorization = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(account + ":" + pwd));
                    client.DefaultRequestHeaders.Add("authorization", authorization);
                    client.Timeout = new TimeSpan(0, 0, 10);
                    HttpContent content = new StringContent(data);
                    content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
                    Task<HttpResponseMessage> res = client.PostAsync(url, content);
                    if (res.Result.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        result = JsonConvert.DeserializeObject<T>(res.Result.Content.ReadAsStringAsync().Result);
                    }
                    else
                    {
                        _logger.LogError($"访问带用户名参数的webapi方法状态码错误:\r url:{url} \r data:{data} \r 状态码:{res.Result.StatusCode}");
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError($"访问带用户名参数的webapi方法异常:\r url:{url} \r data:{data} \r 异常信息:{ex.Message}");
                }
                finally
                {
                    client.Dispose();
                }
            }
            return result;
        }
    }


现在再新建一个使用HttpWebRequest的通用访问webapi的方式。在WebHelper项目下面,新建 HttpWebRequestHelper类,以及IHttpWebRequestHelper接口:


1995789-20210606190921148-924208770.png


在接口里面,新建一个通用的泛型类型的访问webapi的请求接口:

1995789-20210606190933782-1025215566.png


然后,在HttpWebRequestHelper类里面,进行有关的实现:


1995789-20210606190952366-1159103896.png

HttpWebRequest没有Dispose方法,所以此处没有使用using写法,最后需要手动使用Abort方法进行释放资源。


接口代码:


public interface IHttpWebRequestHelper
    {
        /// <summary>
        /// 通用方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url"></param>
        /// <param name="data"></param>
        /// <param name="method">默认POST</param>
        /// <returns></returns>
        T Request<T>(string url, string data, string method = "POST");
    }


接口实现代码:


public class HttpWebRequestHelper:IHttpWebRequestHelper
    {
        readonly ILogger<HttpWebRequestHelper> _logger;
        public HttpWebRequestHelper(ILogger<HttpWebRequestHelper> logger)
        {
            _logger = logger;
        }
        public T Request<T>(string url, string data,string method="POST")
        {
            var result = default(T);
            HttpWebRequest request = null;
            try
            {
                request = (HttpWebRequest)WebRequest.Create(url);
                var byteData = Encoding.UTF8.GetBytes(data);
                request.Method = method;
                request.ContentType = "application/json"; 
                request.ContentLength = data.Length;
                request.Timeout = 10000; // 超时时间,毫秒单位
                using (var stream = request.GetRequestStream())
                {
                    stream.Write(byteData, 0, data.Length);
                }
                var response = (HttpWebResponse)request.GetResponse(); // 发送请求
                using (var resStream = response.GetResponseStream()) // 读取数据
                {
                    using (var reader = new StreamReader(resStream, Encoding.UTF8))
                    {
                        result = JsonConvert.DeserializeObject<T>(reader.ReadToEnd()); 
                    }
                }
            }
            catch (Exception ex)
            {
                  _logger.LogError($"使用HttpWebRequest访问webapi方法异常:\r url:{url} \r data:{data} \r 异常信息:{ex.Message}");
            }
            finally
            {
                if (request != null)
                {
                    request.Abort(); // 释放资源
                }
            }
            return result;
        }
    }


现在开发两个webapi进行测试。首先把该类库项目,添加到启动项目的项目引用里面。然后,在启动项目里面的AutofacRegister里面,添加对Wsk.Core.WebHelper类库项目的所有接口进行依赖注入注册:

1995789-20210606191315025-211510183.png


注册部分代码:


var assemblysWebhelper = Assembly.Load("Wsk.Core.WebHelper"); // 
            container.RegisterAssemblyTypes(assemblysWebhelper)
                .SingleInstance()
               .AsImplementedInterfaces() 
               .EnableInterfaceInterceptors();


新建一个实体类,用来当作参数和返回值的测试:


1995789-20210606191410614-1039858461.png

 

接着,在控制器里面写几个测试方法进行测试,测试内容如下:

1995789-20210606191423276-1887306644.png


控制器部分代码:


[Route("[controller]/[action]")]
    [ApiController]
    public class WSKController : ControllerBase
    {
        private readonly ITestAutofac _autofac;
        private readonly ILogger<WSKController> _logger;
        private readonly IRedisManage _redis;
        private readonly IHttpClientHelper _httpClient;
        private readonly IHttpWebRequestHelper _httpWebRequestHelper;
        public WSKController(ITestAutofac autofac, ILogger<WSKController> logger, IRedisManage redis, IHttpClientHelper httpClient, IHttpWebRequestHelper httpWebRequestHelper) {
            _autofac = autofac;
            _logger = logger;
            _redis = redis;
            _httpClient = httpClient;
            _httpWebRequestHelper = httpWebRequestHelper;
        }
        [HttpPost]
        public IActionResult HelloWorld(string url1,string url2)
        {
            TestWebHelperInfo info = new TestWebHelperInfo();
            info.name = "Hello";
            var value1 = _httpClient.Post<TestWebHelperInfo>(url1,JsonConvert.SerializeObject(info));
            info.name = "World";
            var value2 = _httpWebRequestHelper.Request<TestWebHelperInfo>(url2, JsonConvert.SerializeObject(info));
            return Ok($"value1:{value1.name} value2:{value2.name}");
        }
        [HttpPost]
        public IActionResult Test1([FromBody] TestWebHelperInfo info)
        {
            return Ok(info);
        }
        [HttpPost]
        public IActionResult Test2([FromBody] TestWebHelperInfo info)
        {
            return Ok(info);
        }
    }


运行,然后测试一下12接口是否可以使用,如果可以使用,拷贝对应的url地址,当作参数传给主测试api里面。

1995789-20210606191526921-676627913.png


获得到请求的url地址前缀是:http://localhost:35678/WSK/,带入参数进行验证:

1995789-20210606191547907-1589423717.png

 

由此可见,两个通用方法都可用。


备注:如果不适用泛型,也可以直接使用返回String即可,不需要进行类型转换。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
15天前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
37 5
|
2月前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
27天前
|
开发框架 .NET 程序员
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结
Autofac 是一个轻量级的依赖注入框架,专门为 .NET 应用程序量身定做,它就像是你代码中的 "魔法师",用它来管理对象的生命周期,让你的代码更加模块化、易于测试和维护
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结
|
1月前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
42 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
23天前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
26 3
|
2月前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
3月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
51 7
|
3月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
82 0
|
4月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
60 0
|
4月前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?