如何传递“Null”(一个真正的姓氏!)到ActionScript3中的SOAPWeb服务

hs1rzwqc  于 2022-09-21  发布在  Apache
关注(0)|答案(9)|浏览(129)

我们有一位员工,他的姓氏是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)
  • Flex 3.5
  • ActionScrip 3
  • ColdFusion 8

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

erhoui1w

erhoui1w1#

好吧,我猜Flex的SOAP编码器实现似乎不正确地序列化空值。将它们序列化为字符串Null似乎不是一个好的解决方案。形式上正确的版本似乎是将空值传递为:

<childtag2 xsi:nil="true" />

因此,“Null”的值只是一个有效的字符串,这正是您要查找的。

我想在ApacheFlex中修复这个问题应该不是很难。我建议打开一期Jira,或者联系apache-flex邮件列表的人。然而,这只会修复客户端。我不能说ColdFusion是否能够使用这种编码的空值。

另见Radu Cotescu的博客文章*How to send null values in soapUI requests*。

57hvy0tb

57hvy0tb2#

这很麻烦,但假设SEARCHSTRING有一个最小长度,例如2个字符,则substring在第二个字符处使用SEARCHSTRING参数,并将其作为两个参数传递:SEARCHSTRING1 ("Nu")SEARCHSTRING2 ("ll").``Concatenate,在执行对数据库的查询时将它们放回一起。

ufj5ltwl

ufj5ltwl3#

追查

起初,我认为这是一个强制错误,其中null被强制为"null",而"null" == null的测试正在通过。不是的。我很接近,但却大错特错。很抱歉!

从那以后,我做了很多fiddling on wonderfl.net和跟踪mx.rpc.xml.*中的代码。在XMLEncoder(在3.5源代码中)的第1795行,在setValue中,所有的XMLEnding都归结为

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

它本质上与以下内容相同:

currentChild.appendChild("null");

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

原因

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

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的XML强制为NULL类型,要么将NULL类型强制为包含字符串“NULL”的根XML元素,并在可能失败的地方通过测试。一种修复方法可能是在检查XML(或任何东西,实际上)是否为“空”时始终使用严格的等价性测试。

解决方案

我能想到的唯一合理的解决办法,除了在每一个该死的ActionScript版本中修复这个错误之外,就是测试字段中的“空”,并将它们转义为CDATA values

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

vom3gejh

vom3gejh4#

xkcd note上,Bobby Tables website有很好的建议,可以避免在各种语言(包括ColdFusion)的SQL查询中错误解释用户数据(在本例中是字符串“Null”)。

从问题中不清楚这是否是问题的根源,根据第一个答案(将参数嵌入到结构中)的注解中提到的解决方案,似乎很可能是其他原因。

c90pui9n

c90pui9n5#

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

我的猜测是,它被作为NaN(不是数字)传递。这将在某个时候扰乱SOAP消息的解组过程(最明显的是在JBoss5服务器中...)。我记得扩展了SOAP编码器,并对NAN的处理方式进行了显式检查。

holgip5t

holgip5t6#

@Doc_180的概念是正确的,只是他关注的是数字,而最初的发帖人在字符串方面存在问题。

解决方案是更改mx.rpc.xml.XMLEncoder文件。这是第121行:

if (content != null)
        result += content;

(我查看了Flex 4.5.1 SDK;其他版本的行号可能不同。)

基本上,验证失败是因为‘Content is NULL’,因此您的参数不会添加到传出的SOAP包中;从而导致缺少参数错误。

您必须扩展此类以删除验证。然后是一个滚雪球,将SOAPEncode修改为使用修改后的XMLEncode,然后将Operation修改为使用修改后的SOAPEncode,然后修改WebService以使用Alternate Operation类。

我在上面花了几个小时,但我需要继续前进。可能需要一两天的时间。

您可以只修复XMLEncode行,然后执行一些monkey patching操作来使用您自己的类。

我还要补充的是,如果您将RemoteObject/AMF与ColdFusion结合使用,则传递空值时不会出现任何问题。

2013年11月16日更新

除了上一条关于RemoteObject/AMF的评论之外,我还有一个最新的补充。如果您使用的是ColdFusion 10,则会从服务器端对象中删除对象上具有空值的属性。因此,您必须在访问属性之前检查其是否存在,否则将出现运行时错误。

如下所示进行检查:

<cfif (structKeyExists(arguments.myObject,'propertyName')>
 <!--- no property code --->
<cfelse>
 <!--- handle property  normally --->
</cfif>

这是与ColdFusion第9版相比的行为变化;在ColdFusion第9版中,空属性将变成空字符串。

编辑2013年12月6日

因为有一个关于如何处理空值的问题,所以这里有一个快速示例应用程序来演示字符串“NULL”将如何与保留字NULL相关。

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" initialize="application1_initializeHandler(event)">
    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;

            protected function application1_initializeHandler(event:FlexEvent):void
            {
                var s :String = "null";
                if(s != null){
                    trace('null string is not equal to null reserved word using the != condition');
                } else {
                    trace('null string is equal to null reserved word using the != condition');
                }

                if(s == null){
                    trace('null string is equal to null reserved word using the == condition');
                } else {
                    trace('null string is not equal to null reserved word using the == condition');
                }

                if(s === null){
                    trace('null string is equal to null reserved word using the === condition');
                } else {
                    trace('null string is not equal to null reserved word using the === condition');
                }
            }
        ]]>
    </fx:Script>
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
</s:Application>

跟踪输出为:

空字符串不等于使用!=条件的空保留字

空字符串不等于使用==条件的空保留字

空字符串不等于使用=条件的空保留字

gywdnpxw

gywdnpxw7#

将所有字符转换为它们的十六进制实体等效项。在本例中,Null将转换为&#4E;&#75;&#6C;&#6C;

jmp7cifd

jmp7cifd8#

ActionScript中限定null值将得到字符串"NULL"。因此,我怀疑有人已经决定将字符串"NULL"解码为null是个好主意,从而导致了您在这里看到的中断--可能是因为他们正在传递null对象并在数据库中获取字符串,而他们并不想这样(所以一定要检查是否也有这种错误)。

bqf10yzr

bqf10yzr9#

作为黑客攻击,您可以考虑在客户端进行特殊处理,将‘Null’字符串转换为永远不会发生的内容,例如,XXNULLXX,然后在服务器上转换回来。

这不是很好,但它可以解决这样的边界情况的问题。

相关问题