我们有一位姓Null的员工。当使用姓氏作为搜索词时,我们的员工查找应用程序将被终止(现在这种情况很常见)。收到的错误(感谢Fiddler!)是:

<soapenv:Fault>
   <faultcode>soapenv:Server.userException</faultcode>
   <faultstring>coldfusion.xml.rpc.CFCInvocationException: [coldfusion.runtime.MissingArgumentException : The SEARCHSTRING parameter to the getFacultyNames function is required but was not passed in.]</faultstring>

可爱,嗯?

参数类型为string。

我正在使用:

WSDL(SOAP)柔性3.5动作脚本3冷聚变8

请注意,当从ColdFusion页面作为对象调用Web服务时,不会发生错误。


当前回答

追踪它

起初,我认为这是一个强制错误,其中null被强制为“null”,并且通过了“null”==null的测试。事实并非如此。我很接近,但非常非常错误。抱歉!

此后,我在wonderfl.net上做了很多手脚,并在mx.rpc.xml.*中跟踪代码。在XMLEncoder(在3.5源代码中)的1795行,在setValue中,所有XMLEncoding归结为

currentChild.appendChild(xmlSpecialCharsFilter(Object(value)));

其基本上与:

currentChild.appendChild("null");

根据我最初的想法,这段代码返回一个空的XML元素。但为什么?

原因

根据评论者贾斯汀·麦克林(Justin Mclean)对错误报告FLEX-33664的评论,以下是罪魁祸首(见我小提琴中最后两个测试,验证了这一点):

var thisIsNotNull:XML = <root>null</root>;
if(thisIsNotNull == null){
    // always branches here, as (thisIsNotNull == null) strangely returns true
    // despite the fact that thisIsNotNull is a valid instance of type XML
}

当currentChild.appendChild传递字符串“null”时,它首先将其转换为文本为null的根XML元素,然后根据null文本测试该元素。这是一个弱相等测试,因此,要么将包含null的XML强制为null类型,要么将null类型强制为包含字符串“null”的根XML元素,然后测试在可能失败的地方通过。一个解决办法可能是在检查XML(或任何东西)是否为“空”时始终使用严格的相等测试

解决方案除了在每个该死的ActionScript版本中修复这个bug之外,我能想到的唯一合理的解决方法是测试字段是否为“null”,并将其转义为CDATA值。

CDATA值是变异整个文本值的最合适方法,否则会导致编码/解码问题。例如,十六进制编码用于单个字符。当您转义元素的整个文本时,首选CDATA值。最大的原因是它保持了人类的可读性。

其他回答

关于xkcd,Bobby Tables网站有很好的建议,可以避免在各种语言(包括ColdFusion)的SQL查询中对用户数据(在本例中为字符串“Null”)进行不正确的解释。

从这个问题中还不清楚这是问题的根源,并且考虑到第一个答案的注释中提到的解决方案(将参数嵌入到结构中),这很可能是其他问题。

问题可能在Flex的SOAP编码器中。尝试在Flex应用程序中扩展SOAP编码器,并调试程序以查看如何处理空值。

我猜,它是以NaN(不是数字)的形式传递的。这有时会打乱SOAP消息解组过程(尤其是在JBoss 5服务器中…)。我记得扩展了SOAP编码器,并对NaN的处理方式进行了显式检查。

这是一个杂烩,但假设SEARCHSRING有一个最小长度,例如2个字符,在第二个字符处对SEARCHSTRING参数进行子串,并将其作为两个参数传递:SEARCHSSTRING1(“Nu”)和SEARCHSTRING2(“ll”)。在对数据库执行查询时,将它们重新连接在一起。

追踪它

起初,我认为这是一个强制错误,其中null被强制为“null”,并且通过了“null”==null的测试。事实并非如此。我很接近,但非常非常错误。抱歉!

此后,我在wonderfl.net上做了很多手脚,并在mx.rpc.xml.*中跟踪代码。在XMLEncoder(在3.5源代码中)的1795行,在setValue中,所有XMLEncoding归结为

currentChild.appendChild(xmlSpecialCharsFilter(Object(value)));

其基本上与:

currentChild.appendChild("null");

根据我最初的想法,这段代码返回一个空的XML元素。但为什么?

原因

根据评论者贾斯汀·麦克林(Justin Mclean)对错误报告FLEX-33664的评论,以下是罪魁祸首(见我小提琴中最后两个测试,验证了这一点):

var thisIsNotNull:XML = <root>null</root>;
if(thisIsNotNull == null){
    // always branches here, as (thisIsNotNull == null) strangely returns true
    // despite the fact that thisIsNotNull is a valid instance of type XML
}

当currentChild.appendChild传递字符串“null”时,它首先将其转换为文本为null的根XML元素,然后根据null文本测试该元素。这是一个弱相等测试,因此,要么将包含null的XML强制为null类型,要么将null类型强制为包含字符串“null”的根XML元素,然后测试在可能失败的地方通过。一个解决办法可能是在检查XML(或任何东西)是否为“空”时始终使用严格的相等测试

解决方案除了在每个该死的ActionScript版本中修复这个bug之外,我能想到的唯一合理的解决方法是测试字段是否为“null”,并将其转义为CDATA值。

CDATA值是变异整个文本值的最合适方法,否则会导致编码/解码问题。例如,十六进制编码用于单个字符。当您转义元素的整个文本时,首选CDATA值。最大的原因是它保持了人类的可读性。

将所有字符转换为其十六进制实体等效字符。在这种情况下,Null将被转换为&#4E&#75;&#6C中&#6C中;