當我們用web service對外提供介面服務的時候,可能很多介面會返回複雜類型,比如數組; 在此次利用.Net下面WCF和我們ASSP API【Alisoft SaaS Platform API】進行聯調的時候,就發現了問題;如果要想讓通過WSDL發布的web service具有最大化的相容性,最好是參考WS-I【Web Services Interoperability】標準,而不要僅僅局限於SOAP標準;以下就返回數組的問題進行下探討;
ASSP API介面之一為getUsingUser,返回的對象為數組,數組元素也為複雜物件SimpleUserInfo,其中包括兩個屬性userId和userName;在WSDL聲明此type的時候預設採用的是soapenc:Array的方式,這也是SOAP規範中的方式;其聲明部分如下:
<xs:complexType name="ArrayOfSimpleUserInfo">
<xs:complexContent>
<xs:restriction base="soapenc:Array">
<xs:attribute ref="soapenc:arrayType" wsdl:arrayType="ns1:SimpleUserInfo[]"></xs:attribute>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
該聲明方式在和大部分的用戶端語言聯調時沒有問題,比如Java、.Net WSE 2.0、.Net WSE 3.0、Php;但是在利用WCF進行聯調時就出現了問題,其表現為:1)在vs2008中通過Add Service Reference添加服務時不成功,產生的代理類為空白;2)若通過命令列工具Svcutil產生,提示不成功,但能看到錯誤資訊,提示如下:
System.ServiceModel.Description.XmlSerializerMessageContractImporter
錯誤: 參考型別“http://schemas.xmlsoap.org/soap/encoding/:Array”僅對編碼的SOAP 有效。
經查,出現以上問題就是由於soapenc:Array的聲明方式所導致,SOAP規範中的這種方式相容性很不好,這點在WS-I BP【WS-I Basic Profile】中有過重點說明;後修改成unbounded模式後測試通過,修改後的聲明方式為:
<xs:complexType name="ArrayOfSimpleUserInfo">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="SimpleUserInfo" nillable="true" type="ns1:SimpleUserInfo" />
</xs:sequence>
</xs:complexType>
soapenc:Array的問題解決之後,WCF環境下的聯調並沒有完全成功,還差一點點;WSDL聲明修改之後,vs2008中加入服務參考正常了,調用服務端ws也正常了,在responseXml中返回了正常的結果,但是WCF對responseXml解析出來的結果卻有問題,userId為null,userName正常,難道userId的資訊丟掉了!後經MS人員查證之後是由於WSDL中聲明SimpleUserInfo中屬性資訊和soap responseXml中屬性資訊的先後順序不一致所導致!為了不讓ISV修改用戶端產生的程式碼,所以只好修改了服務端WSDL中userId、userName兩者的順序,之後問題全部解決;
總結下,雖然說web service說是完全跨平台的,但在實際開發過程中還是會出現很多的不相容問題,這不僅僅是由於開發人員的代碼編寫上,連某些標準規範都是有瑕疵的,並不是說遵循了SOAP標準規範就沒有任何問題了,至於這點,大家可以多參考WS-I標準,他裡面指出了很多能夠保證最大化相容性的措施和方法,這會非常有用;
PS:以下列出相關參考串連
WS-I 基本概要中文版:http://www.ibm.com/developerworks/cn/webservices/ws-ibaseprof1.0/index.html
WS-I官網:http://www.ws-i.org/
WSDL:http://www.w3.org/TR/wsdl.html