在Winform混合式框架中整合外部API接口的调用
在我们常规的业务处理中,一般内部处理的接口多数都是以数据库相关的,基于混合式开发的Winform开发框架,虽然在客户端调用的时候,一般选择也是基于Web API的调用,不过后端我们可能不仅仅是针对我们业务数据库的处理,也可以能是调用其他外部接口,如物流、供应商接口等接口,本随笔就是主要介绍基于混合式开发框架如何整合外部API接口的调用。
1、混合式框架的结构介绍
我们知道,混合式的框架是可以在客户端访问Web API服务、WCF服务或者直接连接数据库几种方式的综合,而尤以Web API为最广泛的应用,它的整个框架的结构如下所示。
在客户端中,通过统一的工厂类CallerFactory<T>对相应的接口进行访问,这里主要就是服务器端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, List<FreightInfo> freight, string token);
}
这里面的接口定义,我们是根据输入参数、输出参数进行定义的,另外token是额外增加的令牌参数,用于请求头部写入信息的。
这个接口的定义其实和我们常规的Web API接口定义没有太多的不同,如下是一个内部客户信息接口定义。
/// <summary>
/// 客户信息的服务接口
/// </summary>
[ServiceContract]
public interface ICustomerService : IBaseService<CustomerInfo>
{
/// <summary>
/// 根据客户名称获取客户列表
/// </summary>
/// <param name="name">客户名称</param>
/// <returns></returns>
[OperationContract]
List<CustomerInfo> 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 name="param">包含多个属性的对象</param>
/// <param name="token">访问令牌</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);
RFIDBaseData<CheckinResult> jsonResult = JsonConvert.DeserializeObject<RFIDBaseData<CheckinResult>>(content);
if (jsonResult != null && jsonResult.code == )
{
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 = JsonHelper<CheckinResult>.ConvertJson(url, postData);
return result;
}
有了这些,我们直接在客户端的界面里面,就可以通过调用CallerFactory<T>进行处理操作了,如下是客户端窗体获取验证身份令牌数据的代码
private string token = null;//访问RFID接口的token
/// <summary>
/// 根据终端用户统一登录验证获取相关访问token
/// </summary>
/// <returns></returns>
private string GetRFIDToken()
{
string username = "wuhuacong";
string password = "";
string device_uuid = "aaaaaaa";
string device_type = "iphone";
string last_app_version = "xxxxxxx";
string app_id = "ntdf5543581a2f066e74cf2fe456"; var result = CallerFactory<IRFIDService>.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 = JsonHelper<CheckinResult>.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 = JsonHelper<TagOrderAsnResult>.ConvertJson(url, postData);
return result;
}
获取标签发货通知单批量
的Web API接口如下代码定义
/// <summary>
/// 获取标签发货通知单批量
/// </summary>
/// <param name="param"></param>
/// <param name="token"></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); RFIDBaseData<TagOrderAsnResult> jsonResult = JsonConvert.DeserializeObject<RFIDBaseData<TagOrderAsnResult>>(content);
if (jsonResult != null && jsonResult.code == )
{
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 = , CurrenetPageIndex = };//初始化一个分页条件
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 = CallerFactory<IRFIDService>.Instance.TagOrderAsn(brand_id, factcode, start_time, end_time, pagerInfo, Token);
return asnResult;
}
通过上面的代码演示,我们了解了在混合框架基础上增加外部Web API接口的方法,通过增加Facade层接口,增加Web API接口,以及对应的客户端封装类,具体处理参数根据Web API接口的输入参数、输出数据等信息进行综合处理即可。
最后我们来看看数据的展示界面。
在Winform混合式框架中整合外部API接口的调用的更多相关文章
- Web API应用架构在Winform混合框架中的应用(1)
在<Web API应用架构设计分析(1)>和<Web API应用架构设计分析(2)>中对WebAPI的架构进行了一定的剖析,在当今移动优先的口号下,传统平台都纷纷开发了属于自己 ...
- Web API应用架构在Winform混合框架中的应用(4)--利用代码生成工具快速开发整套应用
前面几篇介绍了Web API的基础信息,以及如何基于混合框架的方式在WInform界面里面整合了Web API的接入方式,虽然我们看似调用过程比较复杂,但是基于整个框架的支持和考虑,我们提供了代码生成 ...
- Web API应用架构在Winform混合框架中的应用(3)--Winfrom界面调用WebAPI的过程分解
最近一直在整合WebAPI.Winform界面.手机短信.微信公众号.企业号等功能,希望把它构建成一个大的应用平台,把我所有的产品线完美连接起来,同时也在探索.攻克更多的技术问题,并抽空写写博客,把相 ...
- Web API应用架构在Winform混合框架中的应用(2)--自定义异常结果的处理
在上篇随笔<Web API应用架构在Winform混合框架中的应用(1)>中我介绍了关于如何在Winfrom里面整合WebAPI,作为一个新型数据源的接入方式,从而形成了三种不同的数据提供 ...
- Web API应用架构在Winform混合框架中的应用(5)--系统级别字典和公司级别字典并存的处理方式
在我这个系列中,我主要以我正在开发的云会员管理系统为例进行介绍Web API的应用,由于云会员的数据设计是支持多个商家公司,而每个公司又可以包含多个店铺的,因此一些字典型的数据需要考虑这方面的不同.如 ...
- C#开发微信门户及应用(48) - 在微信框架中整合CacheManager 缓存框架
在我们的很多框架或者项目应用中,缓存在一定程度上可以提高程序的响应速度,以及减轻服务器的承载压力,因此在一些地方我们都考虑引入缓存模块,这篇随笔介绍使用开源缓存框架CacheManager来实现数据的 ...
- 在DWZ框架中整合kindeditor复文本框控件
今天上午在DWZ框架中整合kindeditor复文本框控件,发现上传图片是老是提示 “上传中,请稍候...”,上网查看别人说可能是文件路径问题,在想以前在其他项目中用这个控件一直没问题,到这里怎么会出 ...
- Spring框架中整合JUnit单元测试的方法
一. 步骤: 1. 拷贝jar包: 1. JUnit-4.9.jar和spring-test-4.2.4.RELEASE.jar ; 2. 替换原来的main函数: 1. 在测试类上使用注解方式替换: ...
- Flask框架学习笔记(API接口管理平台 V1.0)
今天博主终于完成了API接口管理平台,最后差的就是数据库的维护, 博主这里介绍下平台的设计原理,首先基于python,利用flask的web框架+bootstrap前端框架完成,先阶段完成了前台展示页 ...
随机推荐
- C# 文件copy和文件删除
C# 文件copy和文件删除 public bool CopyFile(string SourcePath, string CopyPathFoder) { bool bfg = false; if ...
- CentOS恢复系统启动grub1.5,2阶段
1.模拟CentOS7系统/boot下文件全丢失 rm -rf /boot/* 2.重启系统,并进入救援模式 3.将救援光盘路径切换回原来的系统磁盘根路径 chroot /mnt/sysimage ...
- CF Educational Round 23 F.MEX Queries
写了3小时 = =.这两天堕落了,昨天也刷了一晚上hihocoder比赛,还爆了零.之后得节制点了,好好准备考研.. 首先很容易想到 压缩数据 + 线段树 然后对于Pushdown真很难写..需要牵涉 ...
- Error Curves HDU - 3714
Josephina is a clever girl and addicted to Machine Learning recently. She pays much attention to a m ...
- EntityFramework Core 2.0 Explicitly Compiled Query(显式编译查询)
前言 EntityFramework Core 2.0引入了显式编译查询,在查询数据时预先编译好LINQ查询便于在请求数据时能够立即响应.显式编译查询提供了高可用场景,通过使用显式编译的查询可以提高查 ...
- php sprintf用法
sprintf用来格式化字符串 说明 string sprintf ( string $format [, mixed $args [, mixed $... ]] 参数 $format 可能的格式值 ...
- [清华集训]小 Y 和恐怖的奴隶主
题面在这里 题意 有一个\(Boss\)和他血量为\(m\)的随从奴隶主,每当奴隶主受到攻击且不死,并且\(Boss\)的随从个数\(<k\)时,就会新召唤一个血量为\(m\)的奴隶主.每次攻击 ...
- [BZOJ1058][ZJOJ2007]报表统计
BZOJ Luogu 题目描述 Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一. 经过仔细观察,小Q发现统计一张报表实际上是维 ...
- java.lang.OutOfMemoryError: PermGen space有效解决方法
PermGen space的全称是Permanent Generation space,是指内存的永久保存区域OutOfMemoryError: PermGen space从表面上看就是内存益出,解决 ...
- Win10下用Anaconda安装TensorFlow
什么是Anaconda anaconda指的是一个开源的Python发行版本,其包含了conda.Python等180多个科学包及其依赖项.它是一个用python开发机器学习的必备工具. 什么是ten ...