由于做到的项目需要跟别的系统交互,我们这边提供wsdl文档给其他系统的开发人员,今天测试的时候,用C#来根据wsdl生成的客户端调用 Java的Web Server时,连最简单的返回string类型获取的值都是null,但是如果直接根据Web服务产生的wsdl来生成C#客户端,就能正常返回值.对 比了下原wsdl文档与Web服务产生的wsdl文档,发现之间没有什么区别。
后来把利用wsdl.exe和wsdl文档生成的客户端代码与直接在项目中引用Java的Web服务产生的代码对比一下。发现只有一个地方不同,就是在调 用Web 服务的方法中返回值特性中存在差异:根据wsdl 工具生成的客户端代码的是 [return: System.Xml.Serialization.XmlElementAttribute("out", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)];直接引用Web服务的客户端代码是 [return: System.Xml.Serialization.XmlElementAttribute("out")],直接去掉Form = System.Xml.Schema.XmlSchemaForm.Unqualified这个属性,原来利用工具生成的客户端调用Java Web服务也能正确获取返回值了。
System.Xml.Schema.XmlSchemaForm这个枚举中有三个值:None,Qualified,Unqualified,代表的意 思是架构中不指定元素和属性窗体、必须用命名空间限定元素和属性、不要求用命名空间限定元素和属性。这个属性存在于跨平台调用时如果wsdl文档没有设计 好,可能就会会在返回值为null的问题了。例如wsdl中的<xsd:schema />元素中没有设定attributeFormDefault和elementFormDefault属性,则默认值是qualified。这样当 在Java中生成Web服务时,消息传送时会带上命名空间。而在C#里利用wsdl工具生成的客户端中,则会在schem声明的各个元素中默认加上 Form = System.Xml.Schema.XmlSchemaForm.Unqualified,当调用Java的web 服务获取返回值时,接收消息的时候不会带上命名空间,这样一来,双方的消息格式不一致,就造成了获取值为null。
除了在设计wsdl时在<xsd:schema />中设置attributeFormDefault和elementFormDefault属性来避免这个外,还可以修改客户端代码,例如直接在 C#的客户端代码中把Form = System.Xml.Schema.XmlSchemaForm.Unqualified取消或者设置Qualified。