如果创建基于K3Cloud的独立WebService站点
金蝶云社区-战斗车
战斗车
1人赞赏了该文章 648次浏览 未经作者许可,禁止转载编辑于2017年04月14日 17:24:28

之前分享过一个帖子,如何从零开始创建基于K3Cloud的个性化WebService,详见:{{{/article/3290692}}}。这个帖子对掌握在K3Cloud基础上开发WebService接口直到较有效的帮助。
但是,该帖子因为是快速,所以使用了WebService站点与K3Cloud站点共用的方式,这种方式的优点是免部署,将WebService服务类库组件拷到K3Cloud站点目录下的Bin文件夹并重启IIS即可用。注意到最后那个重启IIS的环节,正是因为需要重启IIS,这样势必影响K3Cloud站点,有时会造成不便。

因此,本贴主要就是说明,如果创建基于K3Cloud的独立WebService站点。本贴的原理就是基于BOS推荐的WebAPI进行访问K3Cloud,而WebService站点扮演的角色主要是将WebAPI接口包装成WebService接口,使终端设备更加通用。

首先,在需要在VS中创建一个网站,添加一个WebService文件,如:

一、把所需的配置信息写在Web.config中,下面举例是把数据中心ID,用户名和用户密码放在配置文件中,也可以在登录接口中提供参数供调用方传递这些信息,里面的WebApiUrl节点值就是K3Cloud所在的站点地址:
<?xml version="1.0" encoding="utf-8"?>

<configuration>
<system.web>
<compilation targetFramework="4.0" />
<httpRuntime executionTimeout="30000"/>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
<appSettings>
<add key="WebApiUrl" value="http://localhost:1650/K3Cloud" />
<add key="DBCenterId" value="56d3e48c02f227" />
<add key="UserName" value="demo" />
<add key="PassWord" value="888888" />
<add key="Language" value="2052" />
</appSettings>
</configuration>

二、以下是接口后台代码WebService.asmx.cs的主要片断:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using Kingdee.BOS.WebApi.Client;
using System.Configuration;
using System.Xml.Serialization;
using Kingdee.BOS.JSON;
using System.Collections.Concurrent;
using Kingdee.BOS.Util;
namespace BuKeWebService
{
/// <summary>
/// BuKeWebService 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
// [System.Web.Script.Services.ScriptService]
public class BuKeWebService : System.Web.Services.WebService
{
// 用户名-SessionId
private static ConcurrentDictionary<string, string> dicUserSession = new ConcurrentDictionary<string, string>();
// SessionId-ApiClient
private static ConcurrentDictionary<string, ApiClient> dicApiClient = new ConcurrentDictionary<string, ApiClient>();
string webApiUrl = ConfigurationManager.AppSettings["WebApiUrl"].ToString();
string dbCenterId = ConfigurationManager.AppSettings["DBCenterId"].ToString();
string userName = ConfigurationManager.AppSettings["UserName"].ToString();
string passWord = ConfigurationManager.AppSettings["PassWord"].ToString();
int localId = Convert.ToInt16(ConfigurationManager.AppSettings["Language"]);
string strError1 = "User is invalid, please log in again";
string strError2 = "User or Password is invalid";
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod(Description = "登录到Cloud系统")]
[XmlInclude(typeof(ReturnLogin))]
public ReturnLogin Login(string UserName, string PassWord, string LocaleId)
{
ReturnLogin returnData = new ReturnLogin(); //ReturnLogin为独立类,下面会有该类定义
ApiClient apiClient = new ApiClient(webApiUrl); //ApiClient需引用Kingdee.BOS.WebApi.Client.dll并using Kingdee.BOS.WebApi.Client;
userName = UserName;
passWord = PassWord;
if (!LocaleId.IsNullOrEmptyOrWhiteSpace())
localId = Convert.ToInt16(LocaleId);
bool loginResult = apiClient.Login(dbCenterId, UserName, PassWord, localId); //此处借用BOS的WebApi登录接口登录到K3Cloud系统
string sessionId = string.Empty;
if (loginResult)
{
// 生成GUID
sessionId = string.Format("{0}{1}", UserName, System.DateTime.Now.Ticks);
returnData.UserName = UserName;
returnData.SessionId = sessionId;
returnData.IsSuccess = true;
// 删除原有的SessionID
string oldSessionId = string.Empty;
if (dicUserSession.TryGetValue(UserName, out oldSessionId))
{
ApiClient oldApiClient;
dicApiClient.TryRemove(oldSessionId, out oldApiClient);
}
dicUserSession.AddOrUpdate(UserName, sessionId, (k, v) =>
{
return v;
});
dicApiClient.AddOrUpdate(sessionId, apiClient, (k, v) =>
{
return v;
});
}
else
{
returnData = new ReturnLogin()
{
IsSuccess = false,
ErrorMsg = strError2
};
}
return returnData;
}

三、ReturnLogin结构体定义:
[Serializable]
public struct ReturnLogin
{
//成功标识
public bool IsSuccess { get; set; }
//界面提示信息
public string ErrorMsg{ get; set; }
//sessionid
public string SessionId { get; set; }
//用户名称
public string UserName{ get; set; }
}

四、至此,创建的独立WebService站点就已经完成登录动作,注意到登录成功后得到的SessionId,这个正是后续实现业务服务接口的重要标识,举个栗子:
/// <summary>
/// 根据物料编码找到特定物料
/// </summary>
/// <param name="SessionId">登录成功得到的标识</param>
/// <param name="MtrlNumber">物料编码</param>
/// <returns></returns>
[WebMethod(Description = "根据物料编码找到特定物料")]
[XmlInclude(typeof(ReturnMtrlList))]
[XmlInclude(typeof(List<MtrlData>))]
[XmlInclude(typeof(MtrlData))]
public ReturnMtrlList MtrlList(string SessionId, string MtrlNumber) //ReturnMtrlList是该接口返回值类型,下面会有该结构体定义
{
ReturnMtrlList returnData;
ApiClient apiClient; //ApiClient需引用Kingdee.BOS.WebApi.Client.dll并using Kingdee.BOS.WebApi.Client;
if (dicApiClient.TryGetValue(SessionId, out apiClient))
{
QueryOption option = new QueryOption() //参数包定义,主要是指WebAPI方法所需要的参数构建成包
{
param1 = MtrlNumber,
};
object[] obj = new object[] { option };
//由API反射实现的方法,BUKE.Kingdee.K3.MFG.WebApi.Services.Stub.MtrlListService.Execute表示被服服务的方法名,BUKE.Kingdee.K3.MFG.WebApi.Services.Stub表示组件名,下面会有这个方法实现的伪代码
string result = apiClient.Execute<string>("BUKE.Kingdee.K3.MFG.WebApi.Services.Stub.MtrlListService.Execute,BUKE.Kingdee.K3.MFG.WebApi.Services.Stub", obj);
returnData = KDObjectConverter.DeserializeObject<ReturnMtrlList>(result);
}
else
{
returnData = new ReturnMtrlList()
{
IsSuccess = false,
ErrorMsg = "登录失效,请重新登录!"
};
}

return returnData;
}

五、ReturnMtrlList 结构体定义:
[Serializable]
public struct ReturnMtrlList
{
public int Count { get; set; }
public string ErrorMsg { get; set; }
public bool IsSuccess { get; set; }
public List<MtrlData> Result { get; set; } //下面会定义MtrlData结构体
}

六、MtrlData结构体定义:
[Serializable]
public struct MtrlData
{
public long MaterialId { get; set; }
public string MaterialModel { get; set; }
public string MaterialName { get; set; }
public string MaterialNumber { get; set; }
}

七、QueryOption结构体定义:
[Serializable]
public struct QueryOption
{
public string param1 { get; set; }
public string param2 { get; set; }
public string param3 { get; set; }
public string param4 { get; set; }
public string param5 { get; set; }
public string param6 { get; set; }
}

八、BUKE.Kingdee.K3.MFG.WebApi.Services.Stub.MtrlListService.Execute表示被服服务的方法实现举例
using Kingdee.BOS;
using Kingdee.BOS.JSON;
using Kingdee.BOS.ServiceFacade.KDServiceFx;
using Kingdee.BOS.Util;
using Kingdee.BOS.WebApi.ServicesStub;
namespace BUKE.Kingdee.K3.MFG.WebApi.Services.Stub
{
/// <summary>
/// 获取物料信息
/// </summary>
public class MtrlListService : AbstractWebApiBusinessService
{
public MtrlListService(KDServiceContext context)
: base(context)
{
}
public Context Ctx
{
get
{
return this.KDContext.Session.AppContext;
}
}
public string Execute(string parameter)
{
//以下代码注释部分是实际业务逻辑,本示例不再详述。
//重点是注意,本类的实现继承自WebAPI服务:AbstractWebApiBusinessService,并得到登录成功后的上下面this.Ctx,或 this.KDContext.Session.AppContext;因此剩余的业务实现就是与普通Cloud二开一致
//QueryOption queryOption = KDObjectConverter.DeserializeObject<QueryOption>(parameter);
ReturnMtrlList returnData = //BuKeMFGServiceFactory.GetService<IBuKeMFGService>(Ctx).GetMaterialData(Ctx, queryOption);
return KDObjectConverter.SerializeObject(returnData);
}
}
}

以上,关于独立站点WebService的搭建已经完成,如有不明之处,欢迎跟帖讨论。