[Mono-dev] wsdl to C#: generated stub raises exception on dynamic array casting

Lluis Sanchez lluis at ximian.com
Tue Jan 17 18:46:35 EST 2006


Hi,

You should file a bug report in bugzilla.ximian.com, and pleaso provide
the complete wsdl file, since snippets are not enough to reproduce the
code generation. The error you are getting could be due to several
causes:
1) gSOAP sending messages that do not conform the published WSDL.
2) wrongly generated stub class (does MS.NET generates the same?).
3) Mono failing to read a valid message.
4) Mono not supporting the provided schema document.

My vote would go to 1 or 2, but without a test case I can't tell.

Lluis.

El mar, 17-01-2006 a las 14:50 -0500, Julien MARBACH escribió:
> 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.
> 




More information about the Mono-devel-list mailing list