.NET向webService傳double、int、DateTime 服務器得到的數據時null的問題
最近被一個 c#調用 Java web service的問題困擾,查詢了一些資料,但都不詳盡,於是自己動手做了個示例,發現問題,總結下。。。煩大家拍磚。。
問題現象:
用C#.NET調用Java(使用xfire)開發的WebService時,先在客戶端封裝的帶有int屬性的對象,當將該對象傳到服務器端時,服務器端可以得到string類型的屬性值,卻不能得到int類型、double和DateTime類型的值(在服務端得到的均為null)
問題結症:
簡單說一下WebService的工作原理。客戶端調用一個WebService的方法,首先需要將方法名和需要傳遞的參數包裝成XML(也就是SOAP包),通常是通過HTTP傳遞到服務器端,然后服務器端解析這段XML,得到被調用方法名稱和傳遞來的參數,進而調用WebService實例的相應方法。方法執行完成之后,將返回的結果再包裝成XML(SOAP響應)發送到客戶端,客戶端解析這段XML,進而得到返回結果。這里關鍵的地方在於中間加入了對象和XML相互轉換的過程。
由於服務端通過aegis方式對對象的非String屬性(int,double,DateTime..)設置了可以為空(nillable="true"),在客戶端調用服務方法saveUser(JafUser user)的時候傳遞一個User對象, 設置了可以為空的非String屬性在服務端接收到相對應的NULL值(int類型為0,double類型為0.0,DateTime為NULL)。
以int和double為例 :
服務端程序:ExampleService對外提供saveUser(JafUser user)方法。返回User屬性拼接的串。其中User有3個屬性: userId ( int類型 ) ,userName(String類型),weight(double類型)。
問題解決(分2步):
1.web服務端Xfire的aegis綁定方式配置。
JafUser.aegis.xml對對象JafUser通過XML傳輸的設置
<mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xfire.codehaus.org/schemas/1.0/mapping.xsd">
<mapping>
<property name="userId" style="element" minOccurs="0" maxOccurs="1" nillable="true" />
<property name="userName" style="element" minOccurs="1" maxOccurs="1" nillable="false" />
<property name="weight" style="element" minOccurs="1" maxOccurs="1" nillable="false" />
</mapping>
</mappings>
2.在客戶端調用時進行設置。
VS2008封裝WebService引用時,如果WebService發布的是一個基本數據類型組成的對象:(以JafUser為例)
a. 該對象中非string屬性為minOccurs="0" nillable="true"設置時(表示該屬性可以為空)), 則會對該對象的非string屬性同時生成兩個屬性,一般是這樣的"屬性Field"、"屬性××Specified"。而"屬性名Specified"是一個bool類型,只有這個屬性被設置成true時,"屬性Field"的值才會被序列化成xml傳遞。否則,服務端接收到的值為0(int的話,接收到0)或0.0(double接收到0.0)。
b. 該對象中非string屬性為minOccurs="1" maxOccurs="1" nillable="false"設置時(表示該屬性不能為空,為必填項),如果該屬性不賦值,則服務端則接收到的值為0.0
附:
附件中為示例,客戶端為VS2008應用程序。服務端為編譯后的程序,解壓后直接將里面的xfireService文件夾扔到tomcat的webapps目錄中,啟動服務后,瀏覽器中輸入http://localhost:8080/xfireService/services/exampleService?wsdl就可看到服務描述文件了,之后,就可以通過VS2008的客戶端調試了。。如有問題,留言。。
