在ActionScript 3中向SOAP Web服务传递“Null”(真实姓氏)的方法
在ActionScript 3中向SOAP Web服务传递“Null”(真实姓氏)的方法
技术背景
在使用ActionScript 3向SOAP Web服务传递数据时,可能会遇到传递“Null”(作为真实姓氏)这样的特殊字符串的问题。由于SOAP编码器对null
值的处理存在一些潜在的错误,导致在传递特殊字符串时可能出现参数丢失或解析错误等情况。
实现步骤
追踪问题
最初以为是null
被强制转换为字符串"null"
,且"null" == null
的测试通过,但实际并非如此。通过在wonderfl.net
上进行调试,并跟踪mx.rpc.xml.*
中的代码,发现XMLEncoder
类(3.5版本源代码中的第1795行)的setValue
方法中,所有的XML编码最终归结为:
1 |
|
这本质上等同于:
1 |
|
根据最初的调试,这段代码返回一个空的XML元素。
找出原因
根据Bug报告FLEX - 33664上评论者Justin Mclean的说法,以下代码是问题的根源:
1 |
|
当currentChild.appendChild
接收到字符串"null"
时,它首先将其转换为文本为null
的根XML元素,然后将该元素与null
字面量进行比较。这是一个弱相等性测试,因此包含null
的XML可能被强制转换为null
类型,或者null
类型被强制转换为包含字符串"null"
的根XML元素,导致本应失败的测试通过。
解决方案
- 使用CDATA值:对字段进行“null”检查,并将其转义为CDATA值。CDATA值是处理整个文本值的最合适方式,可以避免编码/解码问题。
- 修改
XMLEncoder
类:修改mx.rpc.xml.XMLEncoder
文件(Flex 4.5.1 SDK中的第121行):
1 |
|
需要扩展这个类以移除验证,然后修改SOAPEncoder
使用修改后的XMLEncoder
,修改Operation
使用修改后的SOAPEncoder
,最后修改WebService
使用修改后的Operation
类。
3. 使用RemoteObject/AMF:如果切换到使用RemoteObject/AMF与ColdFusion,null
值可以正常传递。但在ColdFusion 10中,对象上具有null
值的属性会从服务器端对象中移除,因此在访问属性之前需要检查属性是否存在。
1 |
|
- 客户端特殊处理:在客户端对
'Null'
字符串进行特殊处理,将其转换为不会出现的字符串,例如XXNULLXX
,并在服务器端进行反向转换。 - 使用正式正确的
null
值传递方式:将null
值作为<childtag2 xsi:nil="true" />
传递。可以考虑在Apache Flex中修复这个问题,建议在Jira上提交问题或联系apache - flex邮件列表。 - 分割参数:如果
SEARCHSTRING
有最小长度要求,例如2个字符,可以将SEARCHSTRING
参数从第二个字符处分割为两个参数SEARCHSTRING1 ("Nu")
和SEARCHSTRING2 ("ll")
,在执行数据库查询时再将它们连接起来。
核心代码
测试字符串“null”与保留字null
的关系
1 |
|
最佳实践
- 在进行XML编码时,优先使用严格相等性测试(
===
)来检查“nullness”。 - 如果可能,尽量使用RemoteObject/AMF与ColdFusion进行通信,避免SOAP编码器的问题。
- 在处理特殊字符串时,使用CDATA值或对其进行特殊处理,以避免编码/解码问题。
常见问题
- ColdFusion 10中
null
属性的处理:在ColdFusion 10中,对象上具有null
值的属性会从服务器端对象中移除,需要在访问属性之前检查属性是否存在。 - SOAP编码器的序列化问题:Flex的SOAP编码器可能会错误地序列化
null
值,导致参数丢失或解析错误。可以通过修改相关类或使用其他通信方式来解决。