钉钉旧版服务端SDK支持异步方法的升级改造
最近项目中需要对接钉钉,有些钉钉 API 的访问需要使用旧版服务端 SDK 才能搞定,但是这个 SDK 使用的还是 .NET Framework 2.0 框架,不能跨平台部署,也不支持 async\await 的异步操作方法,Nuget 上也有其它用户改造的 .NET Core 版本,但是都不支持异步方法,于是就想自己改造一下,经过若干小时的改造,最终发现完全可行,这篇文章就把改造的结果分享给大家。
主要包括两项改造:调整框架为 .netstandard 2.0;支持异步的Get/Post方法。
代码已经上传到了公共仓库,需要的请自取。
GitHub - bosima/TopSdk: 钉钉旧版服务端SDK改造版:项目框架调整为 .netstandard 2.0;增加异步请求接口。
TopSdk: 钉钉旧版服务端SDK改造版:项目框架调整为 .netstandard 2.0;增加异步请求接口。
安装方法
两种方法:
- 直接下载源代码,然后编译安装。
- 通过 Nuget 公共仓库安装:FireflySoft.TopSdk
使用方法
所有业务类的定义都没有改变,而且原来的同步方法可以继续使用。
这里重点看下异步方法的使用,只需要替换几个名字:
- IDingTalkClient 替换为 IAsyncDingTalkClient。
- DefaultDingTalkClient 替换为 AsyncDefaultDingTalkClient 。
- Execute 替换为 ExecuteAsync。
下面是代码示例:
IAsyncDingTalkClient client = new AsyncDefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
OapiUserGetRequest req = new OapiUserGetRequest();
req.Userid = "userid1";
req.SetHttpMethod("GET");
OapiUserGetResponse rsp = await client.ExecuteAsync(req, accessToken)
相关改造
给大家分享下具体怎么做的。
修改框架
修改框架为 .netstandard 2.0 ,这个网上有很多介绍,基本上没有什么难度。
我用了一个 Visual Studio 的插件升级的,有兴趣的可以看看:.NET Upgrade Assistant – Visual Studio Marketplace
支持异步
这个部分比较麻烦一些,因为要支持 async/await 的编写方式。
SDK原来的网络请求都是通过 HttpWebRequest 实现的,这个类十分基础,虽然也支持异步,但还是比较老旧的异步回调方式。所以我使用了 HttpClient这个新的 HTTP 操作类来替换它。
原来的 HTTP 操作都封装在 Util/WebUtils.cs 这个文件中,我模仿这个类创建了一个新的 Util/AsyncWebUtils.cs 。相关的属性和公开方法都保留了下来,只是方法改成了异步方法,方法名后边都加上了 Async。
这里有一点很重要的问题:HttpClient 存在DNS缓存的问题,也就是使用它访问某个域名的时候,它会把这个域名对应的IP缓存下来,默认情况下永远不更新,如果网站更换了DNS解析,原来的IP可能就访问不了了。
为了解决这个问题,微软官方在 HttpHandler 中新增了一个属性设置 PooledConnectionLifetime,它的本来意思是设置连接池中连接的生命周期,然后通过它也可以解决DNS缓存的问题,因为重新连接就要重新解析域名,就可以缓解上面这个问题。
同时为了兼容原来的一些网络超时和代理的设置,我这里选择的 HttpHandler 是 SocketsHttpHandler。但是但是又有新的问题了,.netstandard 2.0 不支持 SocketsHttpHandler,这个要到 .NET Core 2.1才支持。不过也有解决办法,有开发者将这个类单独提了出来:GitHub - TalAloni/StandardSocketsHttpHandler: StandardSocketsHttpHandler is a backport of SocketsHttpHandler to .NET Standard 2.0
到这里 HTTP 的基本异步操作问题就都解决了,看看 HttpClient 的初始化方法,这里用了一个双检索来实现单例,因为 HttpClient 内部会创建一个连接池,所以我们没必要每次new一个,每次new还会导致底层网络端口释放不及时的问题。
private HttpClient GetHttpClient()
{if (_httpClient == null){lock (_lock){if (_httpClient == null){// https://github.com/TalAloni/StandardSocketsHttpHandlervar handler = new StandardSocketsHttpHandler{PooledConnectionLifetime = TimeSpan.FromMinutes(3), // Recreate every 3 minutesConnectTimeout = TimeSpan.FromMilliseconds(_timeout),ResponseDrainTimeout = TimeSpan.FromMilliseconds(_readWriteTimeout),UseProxy = _disableWebProxy,};if (this._ignoreSSLCheck){handler.SslOptions.RemoteCertificateValidationCallback = new RemoteCertificateValidationCallback(TrustAllValidationCallback);}_httpClient = new HttpClient(handler);}}}return _httpClient;
}
其它就是异步Get、Post的实现,Post的实现又需要实现Json请求和上传文件的处理,最后是返回值的解码处理,这些比较繁琐,但是没什么大问题,大家有兴趣的看代码就可以了。
注意
1、源代码是从钉钉开放平台页面公开下载的(点此前往),其中没有 License 文件,但是从公开下载的行为看,应该是允许修改的,且本人也没有售卖此代码。如有侵权,请联系删除此仓库。
2、虽然本人使用正常,但未做全面测试,正式使用前请谨慎测试评估,因使用此仓库代码造成的损失,本人概不负责。
相关文章:
钉钉旧版服务端SDK支持异步方法的升级改造
最近项目中需要对接钉钉,有些钉钉 API 的访问需要使用旧版服务端 SDK 才能搞定,但是这个 SDK 使用的还是 .NET Framework 2.0 框架,不能跨平台部署,也不支持 async\await 的异步操作方法,Nuget 上也有其它用户改造的 .…...

【C语言】【数据存储】用%d打印char类型数据,猜结果是啥
题目代码如下: #include <stdio.h> int main() {char a -1;signed char b-1;unsigned char c-1;printf("a%d,b%d,c%d",a,b,c);return 0; }解题关键: 1.二进制存储:原码,反码,补码 互换 2.截断 3.整型…...

算法——双指针
1658. 将 x 减到 0 的最小操作数 - 力扣(LeetCode) 这道题的重点是,如何用最小的操作数,来使其x变为0——也可以看作是用最少的数据个数,来求和得到x。 ——但是我们可以知道,由于数据是从两端向中间取的…...

【PowerQuery】Excel的PowerQuery按需刷新
将数据通过PowerQuery 导入进来后,这里将进行数据分组运算,最终的数据计算结果将保存在Excel 表格中,图为销售统计结果。 在Excel中,如果我们希望进行销售统计的手动更新可以使用几种不同的方法来进行刷新: 刷新单一数据连接如果仅仅需要刷新单一数据连接的话我们可以通过…...
Django REST Farmowork初探
1.简介 Django REST framework (简称:DRF)是一个强大而灵活的 Web API 工具。 遵循RESTFullAPI风格,功能完善,可快速开发API平台。 官网文档:https://www.django-rest-framework.org 2. framwork的安装 …...
【flink进阶】-- Flink kubernetes operator 版本升级
目录 1、检查当前 flink kubernetes operator 版本 2、停止生产上正在运行的 flink job 3、升级 CRD...
Linux Ubuntu20.04深度学习环境快速配置命令记录
一、驱动安装 1、更新系统包 sudo apt-get updatesudo apt-get upgrade 2、安装显卡驱动 使用apt方式安装驱动,多数情况不容易成功, 使用一下方法更佳: 1.查看合适显卡的驱动版本 ubuntu-drivers devices NVIDIA GeForce 驱动程序 - …...

信息安全三级真题一
目录 一、单选题 二、填空题 三、综合题 一、单选题 二、填空题 三、综合题 知法懂法,请各位网络安全从业者遵守《网络安全法》、《个人信息保护法》 业%$务*$&联&#系 XHU3ZjUxXHU3ZWRjXHU4ZmQwXHU3ZWY0XHU2ZTE3XHU5MDBmXHU1NmUyXHU5NjFmXHUyMDBiXHU2M…...
RK3568-tftp更新设备树和内核nfs挂载文件系统
1. 注意:需要设备树和内核按以下修改才能支持tftp和nfs。 1.1 修改设备树: diff --git a/arch/arm64/boot/dts/rockchip/OK3568-C-linux.dts b/arch/arm64/boot/dts/rockchip/OK3568-C-linux.dts index 178b4d831..34cb57ffd 100644 --- a/arch/arm64/boot/dts/rockchip/OK…...

FIR滤波器简述及FPGA仿真验证
数字滤波器的设计,本项目做的数字滤波器准确来说是FIR滤波器。 FIR滤波器(有限冲激响应滤波器),与另一种基本类型的数字滤波器——IIR滤波器(无限冲击响应滤波器)相对应,其实就是将所输入的信号…...

高速信号处理板资料保存:383-基于kintex UltraScale XCKU060的双路QSFP+光纤PCIe 卡设计原理图
基于kintex UltraScale XCKU060的双路QSFP光纤PCIe 卡 一、板卡概述 本板卡系我司自主研发,基于Xilinx UltraScale Kintex系列FPGA XCKU060-FFVA1156-2-I架构,支持PCIE Gen3 x8模式的高速信号处理板卡,搭配两路40G QSFP接口…...

QT:使用分组框、单选按钮、普通按钮、标签、行编辑器、垂直分布、水平分布做一个小项目
widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QRadioButton> //单选按钮 #include <QGroupBox> //分组框 #include <QHBoxLayout> //水平布局 #include <QVBoxLayout> //垂直布局 #include <QPushButton>…...
封装微信小程序隐私信息授权
隐私 代码 html (modal 组件再后面封装有提供) <modal isShow"{{show}}"><view class"privacy-auth-dialog"><view class"title">温馨提示</view><view class"content"><vi…...

【C#】FileInfo类 对文件进行操作
提示:使用FileInfo类时,要引用System.IO命名空间。 using System.IO; FileInfo类 生成文件删除文件移动文件复制文件获取文件名判断文件是否存在属性列表其它常用方法 生成文件 Create():在指定路径上创建文件。 FileInfo myFile new FileIn…...
python中的字符串也是可迭代对象吗?
python中的字符串也是可迭代对象吗? ━━━━━━━━━━━━━━━━━━━━━━ 是的,Python中的字符串是可迭代对象。这意味着你可以像处理列表或元组那样处理字符串。例如,你可以使用for循环遍历字符串中的每个字符,或…...
C++ 图像线特征提取【HoughLinesP算法】
目录 一、函数介绍二、实现步骤三、代码示例一、函数介绍 HoughLinesP:是一种基于Hough变换的直线检测算法。它可以识别图像中的直线,并返回它们的端点坐标。其函数接口如下: cv::HoughLinesP( InputArray src, // 输入图像,必须 8-bit 的灰度图像 OutputArray…...
Stable Diffusion WebUI内存不够爆CUDA Out of memory怎么办?
在我们运行SD的时候,我们经常会爆CUDA Out of memory。 我们应该怎么办呢? 这是因为我们的显存或者内存不够了。 如果你是用cpu来跑图的则表示内存不够,这个时候就需要换个大点的内存了。 如果你是用gpu来跑图的就说明你显存不够用咯,这时候咋办呢? 下面我将一一述说…...

模板学堂|数据可视化仪表板大屏设计流程梳理
DataEase开源数据可视化分析平台于2022年6月正式发布模板市场(https://dataease.io/templates/)。模板市场旨在为DataEase用户提供专业、美观、拿来即用的仪表板模板,方便用户根据自身的业务需求和使用场景选择对应的仪表板模板&a…...

基于Xml方式Bean的配置-Bean的延时加载
SpringBean的配置详解 Bean的延时加载 当lazy-init设置为true时为延时加载,也就是当Spring容器创建的时候,不会立即创建Bean实例,等待用到时再创建Bean实例并储存到单例池中,后续使用该Bean时直接从单例池中获取即可,…...

python之pyQt5实例:Matplotlib的应用
1、显示逻辑 1.1MatplotlibWidget.py import sys import random import matplotlibmatplotlib.use("Qt5Agg") from PyQt5 import QtCore from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QSizePolicy, QWidget from numpy import arange, si…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...

Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
信息系统分析与设计复习
2024试卷 单选题(20) 1、在一个聊天系统(类似ChatGPT)中,属于控制类的是()。 A. 话语者类 B.聊天文字输入界面类 C. 聊天主题辨别类 D. 聊天历史类 解析 B-C-E备选架构中分析类分为边界类、控制类和实体类。 边界…...

第2篇:BLE 广播与扫描机制详解
本文是《BLE 协议从入门到专家》专栏第二篇,专注于解析 BLE 广播(Advertising)与扫描(Scanning)机制。我们将从协议层结构、广播包格式、设备发现流程、控制器行为、开发者 API、广播冲突与多设备调度等方面,全面拆解这一 BLE 最基础也是最关键的通信机制。 一、什么是 B…...
MongoDB $type 操作符详解
MongoDB $type 操作符详解 引言 MongoDB 是一款流行的开源文档型数据库,它提供了丰富的查询操作符来满足不同的数据查询需求。在 MongoDB 中,$type 操作符是一个非常有用的查询操作符,它允许用户根据文档中字段的类型来查询文档。本文将详细介绍 MongoDB 的 $type 操作符,…...

基于python大数据的水文数据分析可视化系统
博主介绍:高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了多年的设计程序开发,开发过上千套设计程序,没有什么华丽的语言,只有实实在…...