【问题标题】:Get readable WSDL service method arguments error in ColdFusion在 ColdFusion 中获取可读的 WSDL 服务方法参数错误
【发布时间】:2009-02-05 14:23:33
【问题描述】:

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

<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.*

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

也许有人会使用一些技术来简化此操作。

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

将欣赏任何想法和想法。

谢谢。

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

编辑:

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

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

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

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

【问题讨论】:

  • 网络服务是否使用复杂的输入参数?
  • @Tomalak 不,只有简单的值。但这不是问题。请参阅帖子编辑。
  • @Sergii Galashyn:如果您在某处发布 WSDL,我想我可以创建一个小函数将其解析为合适的 CF 结构。
  • 如果真的需要,我可以自己制作。对于这个问题,想法比实施更重要。感谢任何方式:)
  • 好。我只是想我会提供我的 XPath-fu,以防你的 XPath-fu 很弱。 ;-)

标签: web-services coldfusion error-handling wsdl


【解决方案1】:

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

好的,如果我理解正确的话,你需要一种“调试”方式来比较你所拥有的和你需要的。

假设你有一个“应该是这样的”-struct:

<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]$">

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

<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>

【讨论】:

  • 是的,这就是制作它的方法。这里唯一的问题是创建 WSargs 模式,但是当你这样做时——剩下的就很容易了。谢谢!
  • 不客气。 ;-) 我不确定是否有一种简单的方法可以自动生成 WSargs 结构。至少在您想要使用正则表达式进行基本有效性检查时不会。但是您总是可以放弃评估 WSDL ——它最终只是 XML。这样你至少可以得到参数的数字+名称。
  • 为了避免正则表达式,在 CF 中进行类型比较会很酷。比如说,JavaScript 中的某种 typeof。
  • 嗯...你可以,在某种程度上。有 IsBoolean() 和 IsNumeric() 等。但是您可以使用正则表达式来查看变量的实际值,将其限制为不仅仅是“数字”。不知道你想把整个“验证”业务走多远。 ;-)
【解决方案2】:

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

【讨论】:

  • 好吧,对我来说问题似乎出在客户端(服务客户端)方面。看,这样的请求甚至不会被发送到服务,它在客户端 CF 实例上尝试构建请求时失败。
【解决方案3】:

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

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

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

所以,这里是 UDFs for fetching WSDL and comparing structures(我的 XPath-fu 可能并不完美:)这里是 base testing code

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

特别感谢Tomalak 的想法。

【讨论】:

    猜你喜欢
    • 2012-04-09
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多