9 题: 如何在ActionScript 3中将“Null”(真正的姓氏!)传递给SOAP Web服务?

在...创建的问题 Fri, Sep 7, 2018 12:00 AM

我们有一名姓氏为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
  • ActionScript 3
  • ColdFusion 8

请注意,从ColdFusion页面调用Web服务作为对象时,会出现错误

    
4564
  1. 对于特定问题,它可能无法帮助您,但SOAP 1.2允许可为空的值,请参阅 w3.org/TR/2001/WD-soap12-20010709 /#_ Toc478383513
    2014-04-07 21:04:17Z
  2. 我觉得它涉及Dave Null。
    2016-08-01 11:16:20Z
  3. 至少它不涉及Chuck Norris。这就是为什么要在代码中远离他: codesqueeze的.com /...
    2017-06-03 18:12:55Z
  4. 员工是否考虑过改名?
    2017-06-30 06:24:47Z
  5. 他应该考虑购买指针狗并称他为NullPointer。
    2018-11-22 08:09:53Z
  6. 醇>
    9答案                              9 跨度>                         

    追踪

    起初我认为这是一个强制性的错误,null被强制转向"null"并且"null" == null的测试正在通过。不是。 我很亲密,但非常非常错。对此感到抱歉!

    我已经完成了很多摆弄wonderfl.net 并追踪代码mx.rpc.xml.*XMLEncoder的第1795行(在3.5源文件中),在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的XML强制转换为null类型,要么将null类型强制转换为包含字符串“null”的根xml元素,并且测试通过它可能失败的地方。一个修复可能是始终使用严格平等检查XML(或其他任何东西,实际上)是否为“nullness”。

    解决方案

    我能想到的唯一合理的解决方法,就是在每个该死的ActionScript版本中修复这个错误,就是测试字段为“null”,将它们转义为 CDATA值

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

        
    1083
    2017-05-23 12:18:30Z

    xkcd note 上, Bobby Tables网站对于避免在各种语言的SQL查询中对用户数据(在本例中为字符串”Null“)的不正确解释提出了很好的建议,包括 ColdFusion

    从问题中不清楚这是问题的根源,并且考虑到对第一个答案的评论中指出的解决方案(将参数嵌入到结构中),似乎它可能是其他东西。

        
    294
    2013-08-10 13:04:23Z

    问题可能出在Flex的SOAP编码器中。尝试在Flex应用程序中扩展SOAP编码器并调试程序以查看如何处理null值。我的猜测是,它是以 NaN (非数字)传递的。这有时会弄乱SOAP消息解组过程(最明显的是在 JBoss 服务器......)。我记得扩展了SOAP编码器并对NaN的处理方式进行了明确的检查。

    (旁注,如果员工ID为Null,您是否希望做一些有用的事情,这不是验证问题吗?我可能错了,因为我几乎不知道要求......)

        
    236
    2013-11-15 13:29:58Z
    1. name =“Null”当然很有用,我也不知道它应该如何与NaN相关。
      2013-11-15 21:01:05Z
    2. 醇>

    @ doc_180有正确的概念,除了他专注于数字,而原始海报有字符串的问题。

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

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

    [我查看了Flex 4.5.1 SDK;其他版本的行号可能有所不同]

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

    您必须扩展此类才能删除验证。然后链上有一个大雪球,修改SOAPEncoder以使用修改后的XMLEncoder,然后修改Operation以使用修改后的SOAPEncoder,然后对WebService进行moidfying以使用备用Operation类。

    我花了几个小时,但需要继续前进。这可能需要一两天。

    您可以修复XMLEncoder行并进行一些猴子修补以使用您自己的类。

    我还要补充一点,如果你切换到使用带有ColdFusion的RemoteObject /AMF,则会毫无问题地传递null。


    2013年11月16日更新

    我最近添加了一篇关于RemoteObject /AMF的评论。如果您使用的是CF10;然后从服务器端对象中删除对象上具有空值的属性。因此,您必须在访问之前检查属性是否存在,否则您将收到运行时错误。像这样检查:

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

    这是CF9的行为变化;其中null属性将变为空字符串。


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

    跟踪输出为:

      

    使用!= condition

    ,null string不等于null保留字      

    使用== condition

    ,null string不等于null保留字      

    使用=== condition

        
    126
    2013-12-06 17:16:27Z
    1. @ Reboog711员工的姓氏实际上是字符串“Null”,如“我的名字是Pat Null”你的答案未能传递员工的姓氏。你回答的只是隐藏了这样一个事实:“Null”被Ben Burns所描述的appendChild()方法强制转换为null的语言概念。结果仍然是系统未能与Null先生或Null女士打交道。
      2013-11-21 21:19:29Z
    2. @ MaxxDaymon我觉得你误解了我的答案实际上是什么。它没有提出解决方案;而是对问题发生原因的解释;并引用Flex Framework的相关代码。我最近的编辑可能是错误的;因为它讨论了另一种方法,并没有与原始问题直接相关。
      2013-11-21 22:01:48Z
    3. 你在正确的轨道上,但在代码content的那一点是字符串"null",而“null”== null返回false,所以测试表现如预期。相反,我认为问题是XML.appendChild如何处理字符串参数,以及如何将仅包含字符串“null”的根XML元素强制转换为文字null
      2013-12-06 16:57:39Z
    4. @ Reboog711看看我的小提琴。返回true的“null”!= null`是这里所希望的行为。如果相反的情况发生,这将丢弃编码过程中的字符串“null”,这实际上是问题的原因。但是,由于此测试成功,编码器继续运行,直到XML.appendChild由于强制错误而丢弃它。
      2013-12-06 17:19:46Z
    5. 不用担心。如果你想看到真正的问题,请在代码示例中添加var xml:XML = <root>null</root>; var s:String = (xml == null) ? "wtf? xml coerced to null?!!" : "xml not coerced to null."; trace(s);
      2013-12-06 17:28:16Z
    6. 醇>

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

        
    63
    2012-04-30 19:03:25Z
    1. 请不要这样做。创建CDATA是为了在需要转义整个文本块的情况下使用。
      2013-12-06 17:46:45Z
    2. 我可能是错的,但我不认为只是因为它不是你的解决方案是如何工作的。此外,您必须记住问题需要一个启发式解决方案,因为没有一种明显的方法,正如所发布的各种解决方案所表明的那样。最后,请记住我不知道CF,解码器不会仅仅等同于&lt; message&gt;&lt;![CDATA [NULL]]&gt;&lt; /message&gt;的内部文本了。到&lt; message&gt; NULL&lt; /message&gt;的内部文本?如果是这样,那么CDATA真的是一个解决方案吗?
      2013-12-06 19:38:06Z
    3. 我贬低了因为这是一个反模式。这种情况下的错误不在CF中,而是在ActionScript中。但是,你提出了一个好的观点。我将为我的小提琴添加一个测试CDATA编码。
      2013-12-19 15:54:03Z
    4. 醇>

    ActionScript 中对null值进行字符串化将得到字符串"NULL"。我怀疑有人已经决定解码字符串"NULL"是个好主意作为null,导致你在这里看到的破损 - 可能是因为他们传递null个对象并在数据库中获取字符串,当他们不想要那样时(所以一定要检查那种bug)。

        
    50
    2014-10-19 10:48:20Z
    1. 是的,这里有许多可能性需要更多的调试来缩小范围。 1)这里使用的WSDL是否足以区分“NULL”作为字符串值和实际的null(或省略)值? 2)如果是这样,客户端是否正确编码了姓氏(作为字符串而不是空文字)3)如果是,服务是否正确地将“NULL”解释为字符串,或者将其强制转换为空值?
      2013-11-17 21:24:32Z
    2. 醇>

    作为一个hack,你可以考虑在客户端进行特殊处理,将'Null'字符串转换为永远不会发生的字符串,例如,XXNULLXX并在服务器上转换回来。

    它不漂亮,但它可以解决这种边界情况的问题。

        
    37
    2013-08-10 13:09:27Z
    1. XXNULLXX也可能是一个名字。你不知道。也许印度尼西亚的人没有姓氏,并在需要时使用XXX的姓氏作为姓氏。
      2013-08-02 08:42:45Z
    2. 或者,yanno,总有CDATA ......
      2013-08-02 14:30:28Z
    3. 相同的概念,但更新数据库中的所有名称,然后更新一些字符(1Null,1Smith)。在客户端中删除该角色。当然,这可能比Reboog的解决方案更轻松。
      2013-11-16 04:30:38Z
    4. @BenBurns是的,但如果我想给孩子命名&#78;&#117;&#108;&#108;怎么办?
      2015-05-11 23:22:42Z
    5. @Sirens这不是问题所在。如果我的名字是“&lt;&amp; quot;&gt;”,那么我希望它可以正确转义为&amp; quot;&amp; lt;&amp; amp; quot;&amp; gt;&amp; quot;话说。真正的问题是应用程序的行为就像它使用黑名单一样。
      2017-04-17 11:04:55Z
    6. 醇>

    好吧,我猜Flex的SOAP编码器实现似乎错误地序列化了空值。将它们序列化为String Null似乎不是一个好的解决方案。正式版本似乎是将null值传递为:

     
    <childtag2 xsi:nil="true" />
    

    所以“Null”的值只不过是一个有效的字符串,这正是你要找的。​​ p>

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

    另见Radu Cotescu的博客文章 如何发送空值在soapUI请求

        
    30
    2014-02-22 21:20:46Z
    1. 这里有很好的信息,所以我不会投票,但我认为这值得评论。默认情况下,XMLEncoder.as实际上会通过在元素上设置null来正确编码真正的xsi:nil="true"值。问题实际上似乎与ActionScript有关XML类型本身(不是编码器)处理字符串"null"
      2013-08-02 14:55:35Z
    2. 醇>

    这是一个kludge,但假设SEARCHSTRING的最小长度,例如2个字符,substring第二个字符的SEARCHSTRING参数,并将其作为两个参数传递:SEARCHSTRING1 ("Nu")SEARCHSTRING2 ("ll"). Concatenate它们在执行查询时返回到数据库中。

        
    21
    2015-06-18 10:52:48Z
    1. CDATA被添加到XML规范中以避免这些类型的kludges。
      2013-08-02 14:31:04Z
    2. 没有必要使用CDATA转义“Null”,XML中没有null关键字。
      2015-04-18 19:20:04Z
    3. 同意@eckes。我不明白为什么会有关于CDATA的所有这些话题。 CDATA仅用于转义在XML中具有特殊含义的字符。无:n,u,l在XML中有特殊的语义。 “NULL”和“&lt;![CDATA [NULL]]&gt;”与XML解析器相同。
      2015-04-18 19:46:53Z
    4. @ jasonkarns - 我同意100%应该对字符串/文本节点NULL没什么特别的,但要迂腐,<blah>null</blah><blah><![CDATA[null]]>与XML解析器不同。它们应该产生相同的结果,但是处理它们的逻辑流程是不同的。我们正在利用这种效果来解决flex XML实现中的错误。我主张其他方法,因为它保留了文本的可读性,并且没有其他解析器的副作用。
      2015-09-08 07:39:52Z
    5. 醇>
来源放置 这里