flex - ActionScript 3如何傳遞正確的"Null"字元串( 僱員合適的姓氏) 給SOAP web服務?

  显示原文与译文双语对照的内容

我們有一個姓為空的僱員。 當他的姓氏被用作搜索項( 現在經常是這樣) 時,他殺死了我們的僱員查找應用程序。 收到的錯誤( 感謝 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>

,哈哈?

參數的類型是字元串。

我用的是:

  • ( 肥皂) 。
  • Flex 3.5
  • ActionScript 3
  • ColdFusion 8

注意,當從ColdFusion頁面調用 web service作為對象時,錯誤不會發生。

时间:

跟蹤它

起初我認為這是一個強制 Bug,其中 null 被強制到 "null",而 "null" == null的測試正在通過。 不是的,我已經了,但非常嚴重。 抱歉 !

我已經做了很多擺弄 wonderfl.net,並通過 mx.rpc.xml.* 代碼跟蹤。 線 1795 XMLEncoder ( 在 3.5源中) setValue, 所有的XMLEncoding歸結為


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

這與下面的基本相同:


currentChild.appendChild("null");

根據我原來的fiddle,這個代碼返回一個空的XML元素。 但是為什麼?

原因

根據 Justin Mclean在 Bug 報告 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被強製為空類型,或者將空類型強製為包含字元串"空"的根XML元素,並且測試傳遞的結果應該失敗。 一種修復可能是總是使用嚴格平等當檢查xml( 或者什麼,真的)" nullness測試。"

解決方案

我能想到的唯一合理的解決方案,缺乏解決這個 Bug actionscript的在每一個該死的版本,是測試領域"空"和逃脫 cdata值。

CDATA值是變異整個文本值的最合適的方式,否則會導致編碼/解碼問題。 例如十六進位編碼用於單個字元。 當轉義元素的整個文本時,CDATA值是首選的。 最大的原因是它維護了人類的可讀性。

問題可能在flex編碼器的SOAP中。 嘗試在你的Flex應用程序中擴展SOAP編碼器並調試程序以查看如何處理空值。 我的猜測是,它作為 NaN ( 不是數字) 傳遞。 這將在一段時間內搞亂SOAP消息編解碼過程。 我記得擴展了SOAP編碼器並對如何處理NaN進行了顯式檢查。

( 順便說一句,如果員工標識是空的,你期望做一些有用的事情,這不是一個驗證問題? 我可能是錯誤的,因為我不知道需求。。

xkcd注意, 鮑比表網站好的建議避免不當的解釋用戶數據( 在本例中,字元串"零") 在各種語言的sql查詢,包括 ColdFusion

目前尚不清楚的問題,這是問題的根源,並給予解決方案在評論指出第一個答案( 在結構中嵌入參數) 似乎是別的東西。

@doc_180 有正確的概念,除了他專註于數字,而原始的海報有問題。

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


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

[I looked at Flex yf_num_ea2c4njoge888888_yf_num SDK; line numbers may differ in other versions ]

基本上,驗證失敗,因為'內容為空'和你的參數沒有被添加到傳出的SOAP數據包;因此導致丟失的參數錯誤。

你必須擴展該類以刪除驗證。 然後在鏈上有一個大的雪球,修改SOAPEncoder來使用你修改的XMLEncoder,然後修改操作以使用你修改的SOAPEncoder,然後 moidfying web service使用你的替代操作類。

我花了幾個小時的時間,但是需要繼續。 這可能需要一天或者兩天。

你可以修復XMLEncoder行並做一些小改動來使用你自己的類。

我也將增加,如果你使用 remoteobject switch/amfcoldfusion,零是通過沒有問題。


11/16/2013 更新:

最近我在關於 remoteobject/amf的評論中還添加了一個新的評論。 如果使用的是 CF10 ;則從伺服器端對象刪除具有空值的屬性。 因此,在訪問屬性之前,你必須檢查屬性是否存在,否則會得到一個運行時錯誤。 檢查如下:


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

這是來自CF9的行為更改;空屬性將變成空字元串。


編輯 12/6/2013

由於這裡有一個關於空值的問題,這裡是一個快速示例應用程序,用來演示字元串"空"如何與保留字相關。


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

跟蹤輸出為:

空字元串不等於使用!= 條件的空保留字

空字元串不等於使用==條件的空保留字

空字元串不等於使用===條件的空保留字

將所有字元轉換為它們的hex-entity等價。 在這種情況下,Null 將被轉換為 &#4E;&#75;&#6C;&#6C;

Stringifying null 值在 ActionScript"NULL" 將字元串。 我懷疑有人決定,因此,一個好主意解碼字元串 "NULL"null, 導致破損你看到--可能是因為他們通過 null 對象和資料庫中獲取字元串,當他們不希望( 所以,一定要檢查那種 Bug ) 。

作為一個 hack,你可以考慮在客戶端進行特殊處理,將'空'字元串轉換為永遠不會發生的事情,例如XXNULLXX和在伺服器上轉換。

它並不漂亮,但它可以解決這樣一個邊界案例的問題。

好吧,我猜,flex的soap編碼的實現似乎序列化null值不正確。 將它們序列化為字元串空似乎並不是一個好的解決方案。 正式正確的版本似乎是傳遞空值為:


<childtag2 xsi:nil="true"/>

So value of"空"whenever nothing else than a valid string, which is exactly what you are & for.

我想在 Apache Flex中解決這個問題不應該那麼難完成。 我建議打開一個Jira問題或者與apache-flex郵件伺服器的人聯繫。 但是這將只修復客戶端。 我不能說如果coldfusion將能夠使用null值編碼。

參見 Radu cotescu博客帖子 如何發送null值在soapui請求

組裝機,但如果有一個最小長度searchstring,例如 2字元,字元串searchstring參數在第二個字元並傳遞兩個參數: SEARCHSTRING1 ("nu") 和 SEARCHSTRING2 ("將") 。 在執行查詢到資料庫時將它們連接起來。

...