我正在开发一个服务调用脚本,如下所示:
<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.*
它一个接一个地手动检查所有这些参数。这就是问题所在。
也许有人会使用某种技术来使这更容易。
我甚至考虑过某种解析器来自动进行比较。
会欣赏任何想法和想法。
谢谢。
P.S。抱歉我的英语 - 不是我的母语。请问我是否写了一些不够清楚的东西。
修改
澄清。问题不在于访问服务。我是它的拥有者,我肯定知道每个方法的所有参数和类型。
问题仅在于在创建请求时读取错误消息 - 填充方法参数容器。
例如,方法得到了10个参数,并且意外地我添加了9 - CF的本地实例抛出了无法找到方法的错误,并显示了我传递的字段的原始列表(上面的em')。我需要将它们与方法参数逐一进行比较,以找到我错过的内容。
真的,这是一个可用性和节省时间的问题。
答案 0 :(得分:2)
真的,这是一个可用性和节省时间的问题。
好的,所以如果我理解正确的话,你需要一种“调试”方式来比较你所拥有的东西。
让我们假设你有一个“这是它应该如何”--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
与此进行比较的函数。
<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>
答案 1 :(得分:0)
您的头痛源于仅接受传递到您的方法中的值而不验证输入。通过在方法中添加验证和重载可以轻松解决这个问题。
答案 2 :(得分:0)
最后,我完成了编写其他代码以帮助我测试我的服务。此外,我需要为我的API用户提供CFML中的示例并组合这些任务。
想分享代码示例,也许别人会觉得它们很有用。
我已经使用了验证结构方法(但是通过删除正则表达式来简化它,因为它们在我的情况下是开销 - 服务验证传入的参数并报告错误)。主要思想是提取WSDL并构建结构模板以与测试数据进行比较。此外,添加了带有界面的简单脚本来测试不同的方法,它可以帮助我更快地测试服务中的变化。
所以,这里是UDFs for fetching WSDL and comparing structures(我的XPath-fu可能不是完美:),这里是base testing code。
希望这种发布代码的方式不违反规则。认为在这里发布它不是一个好主意。
特别感谢Tomalak的想法。