1

我正在开发一个服务调用脚本,如下所示:

<cfinvoke webservice="#ServiceURL#" method="AddCustomer" returnvariable="ResponseData" argumentcollection="#stAguments#">
    <cfinvokeargument name="api_key" value="#ServiceKey#" />
</cfinvoke>

显然,在此调用之前填充了stAguments结构。想象一下,您忘记将参数之一添加到此容器中或使用了错误的参数类型,例如创建了无效请求。ColdFusion 抛出可以被捕获的异常,但不能(不是字面意思)被读取:

*Web service operation AddCustomer with parameters {postcode={12345},org_name={Terms test 7.79661762856},fax={},html={1},addr1={address1},firstname={sergey},city={Austin},country={},taxable={},notify={1},lastname={galashyn},addr2={},ssn={},api_key={8FE9AD0BCF2382D92A1080DB3AA62DB9},taxrate={0},terms={Net 15},active={},state={},salutation={Mr.},password={123},account_manager={1}} cannot be found.*

手动一一检查所有这些参数让我大吃一惊。这就是问题。

也许有人使用一些技术来使这更容易。

我什至考虑过某种解析器来自动进行这种比较。

将欣赏任何想法和想法。

谢谢你。

PS对不起我的英语——不是我的母语。请问我是不是写的不够清楚。

编辑:

澄清。问题不在于访问服务。我是它的所有者,我绝对知道每种方法的所有参数及其类型。

问题仅在于创建请求时读取错误消息——填充方法参数容器。

例如,方法有 10 个参数,但我不小心添加了 9 个 - CF 的本地实例抛出错误,该方法无法找到并显示我已传递的字段的原始列表(上面列出的)。我需要将它们与方法参数一一进行比较,以找到我错过的内容。

确实,这是一个可用性和节省时间的问题。

4

3 回答 3

2

确实,这是一个可用性和节省时间的问题。

好的,所以如果我对您的理解正确,您需要一种“调试”方式来比较您所拥有的与您需要的。

让我们假设你有一个“这就是它应该是这样”的结构:

<cfset WSargs = StructNew()>
<cfset WSargs.AddCustomer = StructNew()>
<cfset WSargs.AddCustomer.postcode  = "\d{5}">
<cfset WSargs.AddCustomer.org_name  = ".+">
<cfset WSargs.AddCustomer.fax       = ".*">
<cfset WSargs.AddCustomer.html      = "^[01]$">
<cfset WSargs.AddCustomer.addr1     = ".*">
<cfset WSargs.AddCustomer.firstname = ".*">
<cfset WSargs.AddCustomer.city      = ".*">
<cfset WSargs.AddCustomer.country   = ".*">
<cfset WSargs.AddCustomer.taxable   = ".*">
<cfset WSargs.AddCustomer.notify    = "^[01]$">
<cfset WSargs.AddCustomer.lastname  = ".*">
<cfset WSargs.AddCustomer.addr2     = ".*">
<cfset WSargs.AddCustomer.ssn       = ".*">
<cfset WSargs.AddCustomer.taxrate   = "^\d*$">
<cfset WSargs.AddCustomer.terms     = ".*">
<cfset WSargs.AddCustomer.active    = ".*">
<cfset WSargs.AddCustomer.state     = ".*">  
<cfset WSargs.AddCustomer.salutation= ".*">
<cfset WSargs.AddCustomer.password  = ".+">
<cfset WSargs.AddCustomer.account_manager = "^[01]$">

并且您需要一个与 this 进行比较的函数argumentcollection

<cffunction name="CompareStructs" returntype="array" output="no">
  <cfargument name="template" type="struct" required="yes">
  <cfargument name="data"     type="struct" required="yes">

  <cfset var errors = ArrayNew(1)>
  <cfset var key = "">

  <cfloop collection="#template#" item="key">
    <cfif StructKeyExists(data, key)>
      <cfif REFind(template[key], ToString(data[key])) eq 0> 
        <cfset ArrayAppend(errors, "Field '#key#' has an invalid value.")>
      </cfif>
    <cfelse>
      <cfset ArrayAppend(errors, "Field '#key#' is missing.")>
    </cfif>
  </cfloop>

  <cfloop collection="#data#" item="key">
    <cfif not StructKeyExists(template, key)>
      <cfset ArrayAppend(errors, "Field '#key#' is not allowed.")>
    </cfif>
  </cfloop>

  <cfreturn errors>
</cffunction>

像这样调用:

<cfset errors = CompareStructs(WSargs.AddCustomer, stAguments)>

<cfif ArrayLen(errors) eq 0>
  <cfinvoke 
    webservice="#ServiceURL#" 
    method="AddCustomer" 
    returnvariable="ResponseData" 
    argumentcollection="#stAguments#"
  >
    <cfinvokeargument name="api_key" value="#ServiceKey#" />
  </cfinvoke>
<cfelse>
  <cfdump var="#errors#" label="Errors calling AddCustomer()">
  <cfabort>
  <!--- or whatever --->
</cfif>
于 2009-02-05T17:48:14.257 回答
0

您的头痛源于仅接受传递给您的方法的值而没有验证输入。这很容易通过在您的方法中添加验证和重载来解决。

于 2009-02-05T15:31:36.140 回答
0

最后,我完成了编写额外的代码来帮助我测试我的服务。此外,我需要为我的 API 用户提供 CFML 中的示例并将这些任务结合起来。

想分享代码示例,也许其他人会发现它们有用。

我使用了验证结构方法(但通过删除正则表达式来简化它,因为它们在我的情况下是开销——服务验证传入的参数并报告错误)。主要思想是提取 WSDL 并构建结构模板以与测试数据进行比较。此外,添加了带有接口的简单脚本来测试不同的方法,它可以帮助我更快地测试服务的变化。

因此,这里是用于获取 WSDL 和比较结构的 UDF(我的 XPath-fu 可能并不完美:),这里是基本测试代码

希望这种发布代码的方式不会违反规则。认为在这里发布它不是一个好主意。

特别感谢Tomalak的想法。

于 2009-02-09T20:33:36.910 回答