WinForm应用界面开发实战 - 如何在混合框架中整合外部API接口调用
在我们常规的业务处理中一般内部处理的接口多数都是以数据库相关的基于混合式开发的Winform开发框架虽然在客户端调用的时候一般选择也是基于Web API的调用不过后端我们可能不仅仅是针对我们业务数据库的处理也可以能是调用其他外部接口如物流、供应商接口等接口本文主要介绍基于混合式开发框架如何整合外部API接口的调用。PS给大家推荐一个C#开发可以用到的界面组件——DevExpress WinForms它能完美构建流畅、美观且易于使用的应用程序无论是Office风格的界面还是分析处理大批量的业务数据它都能轻松胜任DevExpress新旧版本帮助文档获取可点击这篇文章查看——《界面控件DevExpress v26.1帮助文档大全CHM版本》1. 混合式框架的结构介绍混合式的框架是可以在客户端访问Web API服务、WCF服务或者直接连接数据库几种方式的综合而尤以Web API为最广泛的应用它的整个框架的结构如下所示。在客户端中通过统一的工厂类CallerFactoryT对相应的接口进行访问这里主要就是服务器端Web API服务接口的处理以及客户端对Web API接口的封装两部分通过一些基类进行简化处理可以极大提高开发效率。对于外部第三方的Web API接口我们也可以在自己的Web API接口中进行包装使得客户端通过相应的接口进行交互即可不需要理会内部还是外部的接口从而实现透明的接口调用。2. RFID外部接口的整合处理在一个客户的应用案例中需要整合服务商RFID接口实现相应的数据交互本文也是基于这个案例进行整个过程的分析和操作使得我们了解在混合框架中如何整合第三方Web API接口为我们内部框架所用。一般来说Web API接口需要明确API的URL、数据提交方式POST/GET、提交参数、返回集合以及一些特殊的数据等而一般接口的操作也是需要一个访问令牌的这些都是Web API接口调用的关键。基本上我们有了上面Web API的1/2/3步骤的信息就可以进行接口编程了这些是Web API开发非常重要的信息。我们需要特别主要到步骤1中的信息这里面的token是额外的接口信息是需要设置Http Request请求的头部信息里面的是用户身份的重要信息所以我们一般需要先通过指定的授权接口获取这个token信息。在这个外部的接口集合里面我们找到统一登录验证的接口定义如下所示。通过上面的分析我们首先需要需要处理好登录验证接口然后通过接口传递令牌token给其他接口进行数据处理的。结合我们的混合框架结构这里我以测试项目TestProject项目为例进行介绍我们调整WHC.TestProject.Caller项目的对应类如下所示。其中Facade层接口类IRFIDService.cs代码如下所示。/// summary /// RFID服务外部接口 /// /summary [ServiceContract] public interface IRFIDService { /// summary /// 终端用户统一登录验证 /// /summary [OperationContract] CheckinResult CheckIn(string username, string password, string device_uuid, string device_type, string last_app_version, string app_id); /// summary /// 获取标签发货通知单批量 /// /summary [OperationContract] TagOrderAsnResult TagOrderAsn(int brand_id, string factcode, string start_time, string end_time, PagerInfo pagerInfo, string token); /// summary /// 标签订单出库物流信息回写 /// /summary [OperationContract] CommonResult TagOutPost(string docno_asn, string factcode, string dest_factcode, ListFreightInfo freight, string token); }这里面的接口定义我们是根据输入参数、输出参数进行定义的另外token是额外增加的令牌参数用于请求头部写入信息的。这个接口的定义其实和我们常规的Web API接口定义没有太多的不同如下是一个内部客户信息接口定义。/// summary /// 客户信息的服务接口 /// /summary [ServiceContract] public interface ICustomerService : IBaseServiceCustomerInfo { /// summary /// 根据客户名称获取客户列表 /// /summary /// param namename客户名称/param /// returns/returns [OperationContract] ListCustomerInfo FindByName(string name); }差别就是它们接口继承类有所不同外部接口由于不需要和数据库打交道我们不需要继承IBaseService接口。根据这些接口的定义我们还需要实现我们具体的Web API 服务逻辑上它是对外部Web API接口的封装但是对于客户端来说并不需要知道是内部还是外部接口客户端只需要知道如果提交参数或者结果即可。由于Web API涉及多个参数的数据提交一般来说这种情况都是以POST方式处理的数据参数则统一在Web API端通过定义一个JObject对象来传递即可登录认证的Web API接口定义如下所示。/// summary /// 基于RFID的应用接口 /// /summary public class RFIDController : BaseApiController { /// summary /// 终端用户统一登录验证 /// /summary /// param nameparam包含多个属性的对象/param /// param nametoken访问令牌/param [HttpPost] public CheckinResult CheckIn(JObject param) { CheckinResult result null; dynamic obj param; if (obj ! null) { //使用POST数据 var postData param.ToJson(); //使用具体的URL var queryUrl https://***.***.***/api/v6/rfid/terminal/checkin/post; var helper new HttpHelper(); helper.ContentType application/json; var content helper.GetHtml(queryUrl, postData, true); RFIDBaseDataCheckinResult jsonResult JsonConvert.DeserializeObjectRFIDBaseDataCheckinResult(content); if (jsonResult ! null jsonResult.code 0) { result jsonResult.data; } return result; } else { throw new MyApiException(传递参数错误); } }其中输入的参数这里用了JObject param的参数我们提交给外部Web API接口的时候我们把这个参数再次序列号为JSON格式的字符串即可var postData param.ToJson();其中CheckinResult和RFIDBaseData是根据输入参数、输出结果进行的实体类定义目的是序列化为强类型的实体类方便数据处理操作。在客户端我们只需要对接好和Web API服务端的接口那么调用起来就非常方便其中对应的Web API接口客户端封装类 RFIDCaller 如下所示。/// summary /// 对RFID控制的接口调用封装 /// /summary public class RFIDCaller : NormalApiService, IRFIDService { public RFIDCaller() { this.ConfigurationPath ApiConfig.ConfigFileName; //Web API配置文件 this.configurationName ApiConfig.RFID; } public CheckinResult CheckIn(string username, string password, string device_uuid, string device_type, string last_app_version, string app_id) { var action System.Reflection.MethodBase.GetCurrentMethod().Name; string url GetNormalUrl(action); var postData new { username username, password password, device_uuid device_uuid, device_type device_type, last_app_version last_app_version, app_id app_id, }.ToJson(); var result JsonHelperCheckinResult.ConvertJson(url, postData); return result; }有了这些我们直接在客户端的界面里面就可以通过调用CallerFactoryT进行处理操作了如下是客户端窗体获取验证身份令牌数据的代码private string token null;//访问RFID接口的token /// summary /// 根据终端用户统一登录验证获取相关访问token /// /summary /// returns/returns private string GetRFIDToken() { string username wuhuacong; string password 123456; string device_uuid aaaaaaa; string device_type iphone; string last_app_version xxxxxxx; string app_id ntdf5543581a2f066e74cf2fe456; var result CallerFactoryIRFIDService.Instance.CheckIn(username, password, device_uuid, device_type, last_app_version, app_id); if(result ! null) { token result.token; } return token; }上面是认证身份的接口其他类型的接口类似的处理方式如增加了一个获取标签发货通知单批量操作后对应的客户端封装类如下所示。/// summary /// 对RFID控制的接口调用封装 /// /summary public class RFIDCaller : NormalApiService, IRFIDService { public RFIDCaller() { this.ConfigurationPath ApiConfig.ConfigFileName; //Web API配置文件 this.configurationName ApiConfig.RFID; } public CheckinResult CheckIn(string username, string password, string device_uuid, string device_type, string last_app_version, string app_id) { var action System.Reflection.MethodBase.GetCurrentMethod().Name; string url GetNormalUrl(action); var postData new { username username, password password, device_uuid device_uuid, device_type device_type, last_app_version last_app_version, app_id app_id, }.ToJson(); var result JsonHelperCheckinResult.ConvertJson(url, postData); return result; } public TagOrderAsnResult TagOrderAsn(int brand_id, string factcode, string start_time, string end_time, Pager.Entity.PagerInfo pagerInfo, string token) { var action System.Reflection.MethodBase.GetCurrentMethod().Name; string url GetNormalUrl(action) string.Format(?token{0}, token); var postData new { page pagerInfo.CurrenetPageIndex, pagesize pagerInfo.PageSize, brand_id brand_id, factcode factcode, start_time start_time, end_time end_time, }.ToJson(); var result JsonHelperTagOrderAsnResult.ConvertJson(url, postData); return result; }获取标签发货通知单批量的Web API接口如下代码定义/// summary /// 获取标签发货通知单批量 /// /summary /// param nameparam/param /// param nametoken/param /// returns/returns [HttpPost] public TagOrderAsnResult TagOrderAsn(JObject param, string token) { TagOrderAsnResult result null; dynamic obj param; if (obj ! null) { //使用POST方式 var postData param.ToJson(); var queryUrl https://***.***.***/api/v6/rfid/tag/tag_order_asn/get; var helper new HttpHelper(); helper.ContentType application/json; helper.Header.Add(token, token); var content helper.GetHtml(queryUrl, postData, true); RFIDBaseDataTagOrderAsnResult jsonResult JsonConvert.DeserializeObjectRFIDBaseDataTagOrderAsnResult(content); if (jsonResult ! null jsonResult.code 0) { result jsonResult.data; } return result; } else { throw new MyApiException(传递参数错误); }其中表头信息我们通过下面的代码指定设置特殊的token表头信息。var helper new HttpHelper(); helper.ContentType application/json; helper.Header.Add(token, token);而在客户端的调用窗体里面我们调用对应的接口就可以获取该接口的数据了。private TagOrderAsnResult asnResult; /// summary /// 根据参数获取标签生产订单批量信息 /// /summary /// returns/returns private TagOrderAsnResult GetResult() { PagerInfo pagerInfo new PagerInfo() { PageSize 50, CurrenetPageIndex 1 };//初始化一个分页条件 var brand_id this.txtbrand_id.Text.ToInt32(); var factcode this.txtfactcode.Text; var start_time this.txtstart_time.DateTime.ToString(yyyy-MM-dd HH:mm:ss); var end_time this.txtend_time.DateTime.ToString(yyyy-MM-dd HH:mm:ss); asnResult CallerFactoryIRFIDService.Instance.TagOrderAsn(brand_id, factcode, start_time, end_time, pagerInfo, Token); return asnResult; }通过上面的代码演示我们了解了在混合框架基础上增加外部Web API接口的方法通过增加Facade层接口增加Web API接口以及对应的客户端封装类具体处理参数根据Web API接口的输入参数、输出数据等信息进行综合处理即可。最后我们来看看数据的展示界面。本文转载自博客园 - 伍华聪

相关新闻

界面控件DevExpress WPF Splash Screen,让应用启动画面更酷炫!

界面控件DevExpress WPF Splash Screen,让应用启动画面更酷炫!

DevExpress WPF的Splash Screen组件可以为应用程序创建十分酷炫的启动屏幕,提高用户在漫长的启动操作期间的体验! P.S:DevExpress WPF拥有120个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress …

2026/10/17 4:03:24 阅读更多 →
PiliPlus:跨平台B站客户端终极指南 - 5大平台一致的纯净体验

PiliPlus:跨平台B站客户端终极指南 - 5大平台一致的纯净体验

PiliPlus:跨平台B站客户端终极指南 - 5大平台一致的纯净体验 【免费下载链接】PiliPlus PiliPlus 项目地址: https://gitcode.com/gh_mirrors/pi/PiliPlus 你是否渴望一个无广告、功能全面且跨平台一致的B站观看体验?PiliPlus正是你寻找的答案。作…

2026/10/15 19:00:43 阅读更多 →
C++实现互相关与自相关算法:从原理到高性能工程实践

C++实现互相关与自相关算法:从原理到高性能工程实践

1. 项目概述:从信号处理到C实现在信号处理、图像识别、音频分析乃至金融时间序列预测等领域,我们常常需要量化两个信号序列之间的相似性,或者探究一个信号自身在不同时间点上的内在关联。这背后有两个核心的数学工具:互相关和自相…

2026/10/15 19:27:23 阅读更多 →

最新新闻

如何用 Rufus 制作 U 盘启动盘:免安装完整指南

如何用 Rufus 制作 U 盘启动盘:免安装完整指南

如何用 Rufus 制作 U 盘启动盘:免安装完整指南 【免费下载链接】rufus The Reliable USB Formatting Utility 项目地址: https://gitcode.com/GitHub_Trending/ru/rufus 重装系统卡在"用 U 盘启动"这一步?镜像点不亮、老机器进不了安装…

2026/10/17 6:26:52 阅读更多 →
lol-skins 仓库 Battle Bunny Riven 幻彩皮肤包(Chroma Pack)完全指南

lol-skins 仓库 Battle Bunny Riven 幻彩皮肤包(Chroma Pack)完全指南

【免费下载链接】lol-skins Comprehensive collection of League of Legends skins available for custom use. 项目地址: https://gitcode.com/gh_mirrors/lo/lol-skins 点击查看 免费下载 本文围绕 lol-skins 开源仓库中 skins/Riven/chromas/Battle Bunny Riven…

2026/10/17 6:26:52 阅读更多 →
Surprise Party Amumu 炫彩包全解析:lol-skins 仓库 8 款 Chroma 的 ID 清单、文件结构与安装使用指南

Surprise Party Amumu 炫彩包全解析:lol-skins 仓库 8 款 Chroma 的 ID 清单、文件结构与安装使用指南

【免费下载链接】lol-skins Comprehensive collection of League of Legends skins available for custom use. 项目地址: https://gitcode.com/gh_mirrors/lo/lol-skins 点击查看 免费下载 本指南围绕 lol-skins 仓库中 skins/Amumu/chromas/Surprise Party Amumu…

2026/10/17 6:26:52 阅读更多 →
C/C++语言基础知识

C/C++语言基础知识

static成员变量什么时候分配内存static成员变量在程序运行时进行分配,static成员变量只是声明在类定义中,而他们的定义必须在类外定义。例如:class myClass {public:static int score;//声明 };需要在类外提供这个成员变量的定义int myClass:…

2026/10/17 6:26:52 阅读更多 →
XERJ 全文检索速查:ES 查询家族(match / term / bool / range / prefix / wildcard / exists)实战指南

XERJ 全文检索速查:ES 查询家族(match / term / bool / range / prefix / wildcard / exists)实战指南

【免费下载链接】xerj XERJ is the new way for AI to search data. Its autoindex capability activates agents to know your data without the token waste of grep and sed. One command indexes code, docs, logs and PDFs for search, RAG, security audits and agent me…

2026/10/17 6:26:52 阅读更多 →
CST软件案例:加载扼流环的电磁透明基站天线仿真研究

CST软件案例:加载扼流环的电磁透明基站天线仿真研究

无线移动通信最初始于上世纪 50 年代的军事应用,随后关于移动通信蜂窝网概念的提出,加速了其民用化的发展。所以从 1995 年到 2010 年左右,全球无线移动通信行业经历了井喷式的增长。市场竞争推动了计算机软硬件技术的更新换代和互联网技术的…

2026/10/17 6:25:52 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →