[Mono-dev] wsdl to C#: generated stub raises exception on dynamic array casting
Julien MARBACH
jmarbach at quelisid.com
Tue Jan 17 14:50:38 EST 2006
Hello,
I've generated a C# client stub from a wsdl file with Mono "wsdl"
command. The stub works great for most of the remote methods but one is
not functioning.
The problematic method consist in transferring a dynamic array of struct
from the server to the client.
When returning its result, the stub function that calls the remote
method makes a cast form Object[] to TagIdArray (my custom type : array
of TagID, see attached code snippets) and an invalid cast exception is
generated :
Unhandled Exception: System.InvalidCastException: Cannot cast from
source type to destination type.
in <0x000f1> quelisapi:getTagIdList (Boolean blocking, Int64 timeout,
System.Boolean scanning)
in (wrapper remoting-invoke-with-check) quelisapi:getTagIdList
(bool,long,bool&)
in [0x00018]
(at /home/jmarbach/workspace/cvs/SmartReader/warehouse_demo/quelisapiclient/quelisapiclient/Main.cs:40) QuelisapiClient:getIDList ()
in [0x00039]
(at /home/jmarbach/workspace/cvs/SmartReader/warehouse_demo/quelisapiclient/quelisapiclient/Main.cs:25) QuelisapiClient:Main (System.String[] args)
The exception is raised by the cast on the return statement of this
function :
public TagIdArray getTagIdList(bool blocking, long timeout, out bool
scanning) {
object[] results = this.Invoke("getTagIdList", new object[] {
blocking,
timeout});
scanning = ((bool)(results[1]));
return ((TagIdArray)(results[0]));
}
Does this means that Mono SOAP implementation is not compatible with the
one I use on the server side (gSOAP) ?
And/or does this means that Mono SOAP implementation does not support
the serialization/deserialization of this kind of structure?
What kind of table could I use that would be supported by Mono?
Thanks,
Julien
PS1 : Here are the code snippets ( "[...]" stands for non relevant
omitted code) :
[************************** wsdl file end ***************************]
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="quelisapi"
targetNamespace="urn:QuelisReader"
xmlns:tns="urn:QuelisReader"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:api="urn:QuelisReader"
xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:MIME="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:DIME="http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/"
xmlns:WSDL="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<schema targetNamespace="urn:QuelisReader"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:api="urn:QuelisReader"
xmlns="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
[...]
<complexType name="TagId">
<sequence>
<element name="uid" type="xsd:string" minOccurs="0" maxOccurs="1"
nillable="true"/>
<element name="readings" type="xsd:int" minOccurs="1"
maxOccurs="1"/>
</sequence>
</complexType>
<simpleType name="TagIdArray">
<restriction base="xsd:base64Binary">
</restriction>
</simpleType>
</schema>
</types>
[...]
<message name="getTagIdList">
<part name="blocking" type="xsd:boolean"/>
<part name="timeout" type="xsd:long"/>
</message>
<message name="TagIdList">
<part name="tagIdArray" type="api:TagIdArray"/>
<part name="scanning" type="xsd:boolean"/>
</message>
<portType name="quelisapiPortType">
[...]
<operation name="getTagIdList">
<documentation>Service definition of function
api__getTagIdList</documentation>
<input message="tns:getTagIdList"/>
<output message="tns:TagIdList"/>
</operation>
</portType>
<binding name="quelisapi" type="tns:quelisapiPortType">
<SOAP:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
[...]
<operation name="getTagIdList">
<SOAP:operation style="rpc" soapAction=""/>
<input>
<SOAP:body use="encoded" namespace="urn:QuelisReader"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<SOAP:body use="encoded" namespace="urn:QuelisReader"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="quelisapi">
<documentation>gSOAP 2.7.6c generated service
definition</documentation>
<port name="quelisapi" binding="tns:quelisapi">
<SOAP:address location="http://api.quelisid.com"/>
</port>
</service>
</definitions>
[************************** wsdl file end ***************************]
[************************ generated stub ****************************]
//
------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Mono Runtime Version: 1.1.4322.573
//
// Changes to this file may cause incorrect behavior and will be
lost if
// the code is regenerated.
// </autogenerated>
//
------------------------------------------------------------------------------
//
// This source code was auto-generated by Mono Web Services Description
Language Utility
//
using System;
/// <remarks/>
/// <remarks>
///gSOAP 2.7.6c generated service definition
///</remarks>
[System.Web.Services.WebServiceBinding(Name="quelisapi",Namespace="urn:QuelisReader"),
System.Diagnostics.DebuggerStepThroughAttribute(),
System.ComponentModel.DesignerCategoryAttribute("code")]
public class quelisapi:
System.Web.Services.Protocols.SoapHttpClientProtocol {
public quelisapi () {
this.Url = "http://api.quelisid.com";
}
[...]
/// <remarks>
///Service definition of function api__getTagIdList
///</remarks>
[System.Web.Services.Protocols.SoapRpcMethodAttribute("",RequestNamespace="urn:QuelisReader",ResponseNamespace="urn:QuelisReader")]
[return: System.Xml.Serialization.SoapElement("tagIdArray")]
public TagIdArray getTagIdList(bool blocking, long timeout, out bool
scanning) {
object[] results = this.Invoke("getTagIdList", new object[] {
blocking,
timeout});
scanning = ((bool)(results[1]));
return ((TagIdArray)(results[0]));
}
public System.IAsyncResult BegingetTagIdList(bool blocking, long
timeout, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("getTagIdList", new object[] {
blocking,
timeout}, callback, asyncState);
}
public TagIdArray EndgetTagIdList(System.IAsyncResult asyncResult,
out bool scanning) {
object[] results = this.EndInvoke(asyncResult);
scanning = ((bool)(results[1]));
return ((TagIdArray)(results[0]));
}
}
/// <remarks/>
[System.Xml.Serialization.SoapType(Namespace="urn:QuelisReader")]
public class TagIdArray {
/// <remarks/>
[System.Xml.Serialization.SoapElement()]
public TagId[] item;
}
/// <remarks/>
[System.Xml.Serialization.SoapType(Namespace="urn:QuelisReader")]
public class TagId {
/// <remarks/>
public string uid;
/// <remarks/>
public int readings;
}
[******************** generated stub end **************************]
[********* My code, used to call the getTagIdList function ********]
TagIdArray tagIdArray;// = new TagIdArray();
bool nonBlocking = false;
long timeout = 10000;
bool scanning = false;
tagIdArray = Service.getTagIdList(nonBlocking , timeout, out scanning);
[********* End ********]
PS2 : on mono irc channel I've discussed about it with "jonp" who made
me some suggestions :
(09:48:07) jonp: as a test, change the C# method argument accepting the
array to a System.Xml.XmlNode (iirc)
(09:48:18) jonp: this should give you direct access to the underlying XML, without any unmarshaling
(09:49:26) jonp: sadly this was reported on mono-devel-list sep-2004, but there were no replies
I'm working on it.
He also pointed out some compatibility info between gSOAP and other SOAP implementations :
http://www.cs.fsu.edu/~engelen/interop11/interop2results.html
This page shows that arrays support (and mostly struct arrays) seems to be a big compatibility challenge between the existing SOAP implementations.
--
MARBACH Julien
Embedded software engineer
Quelis ID Systems
11845 Irenee-Vachon
J7N 1G2 Mirabel (QC)
Canada
Phone : +1 (450) 476-1930 - x230
Fax : +1 (450) 476-0246
--- www.quelisid.com ---
More information about the Mono-devel-list
mailing list