Hi All,
I switched the server over to utilize (Wrapped) Doc / Literal (using java2wsdl) and created new Web Reference in .NET.
Once I did this, I was able to successfully deserialize using XmlSerializer after I put in an XmlRootAttribute setting on the generated FdkException class.
For the life of me, I could not get the damn SoapFormatter to decode RPC/Encoded - kept complaining about missing top object or something along those lines.
For those curious, the code I used was:
FdkException fe =
null;
XmlReader reader = null;
XmlWriter writer = null;
MemoryStream mem = new MemoryStream();
reader = new XmlNodeReader(se.Detail.FirstChild);
writer = new XmlTextWriter(mem, System.Text.Encoding.UTF8);
writer.WriteNode(reader,true);
writer.Flush();
mem.Position = 0;
XmlSerializer serializer = new XmlSerializer(typeof(FdkException));
fe = (FdkException) serializer.Deserialize(mem);
The crazy thing is that .NET was working perfectly with RPC / Encoded for everything other than my manual deserialization efforts.
It would seem Doc / Literal is the way of the future anyway.
thanks,
Matt.
>From: Anne Thomas Manes <[EMAIL PROTECTED]>
>Reply-To: Anne Thomas Manes <[EMAIL PROTECTED]>
>To:
[email protected]
>Subject: Re: Using .NET how to deserialize obj from detail element of SOAP fault sentby AXIS?
>Date: Wed, 16 Mar 2005 10:50:23 -0500
>
>Per both the SOAP 1.1 spec and the WS-I BP, faults must be described
>as document/literal -- even if the input and output messages are
>rpc/encoded. Perhaps that's why .NET is having so much trouble.
>
>Anne
>
>
>On Tue, 15 Mar 2005 20:11:45 -0800, Dino Chiesa <[EMAIL PROTECTED]> wrote:
> >
> > > Does .NET uses XMLSerializer behind the scenes to perform
> > serialization/deserialization of SOAP messages?
> >
> > Yes, it can, but not SOAP Section-5 encoded messages. In .NET, that is done
> > by the SOAP serializer.
> >
> > > Is there an alternative preferred/standard mechanism to define array types
> > in the WSDL?
> >
> > Yes, see
> > http://wiki.apache.org/ws/DotNetInteropArrays?action=""
> >
> > > Assuming I was not using the funky array stuff, and just trying to
> > deserialize a standard object with xsd string/int attributes etc by using
> > the detail element inside a SoapException, do you know how you would go
> > about doing this?
> >
> > Like this?
> >
> > catch (System.Web.Services.Protocols.SoapException ex1) {
> > Console.WriteLine("SOAP Exception: '{0}'", ex1.ToString());
> > if (ex1.Detail != null) {
> >
> > System.Xml.Serialization.XmlSerializer ser= new
> > System.Xml.Serialization.XmlSerializer(typeof(FdkException));
> >
> > System.IO.StringReader sr= new
> > System.IO.StringReader(ex1.Detail.InnerXml);
> > FdkException fault= (FdkException) ser.Deserialize(new
> > System.Xml.XmlTextReader(sr));
> >
> > Console.WriteLine("fault.errorCode: '{0}'", fault.errorCode);
> > Console.WriteLine("fault.stack: '{0}'", fault.serverStackTraceId);
> > // etc
> > }
> > else
> > Console.WriteLine("detail is null!");
> > }
> >
> >
> > The FdkException has to be exposed into the WSDL, so that it gets generated
> > into the client-side proxy class. or it must otherwise be known to the
> > client.
> >
> >
> > ________________________________
> > From: M S [mailto:[EMAIL PROTECTED]
> > Sent: Tuesday, March 15, 2005 9:23 PM
> > To:
[email protected]
> > Subject: RE: Using .NET how to deserialize obj from detail element of SOAP
> > fault sentby AXIS?
> >
> >
> >
> >
> >
> >
> > Hi Dino,
> >
> > Thanks for your reply.
> >
> > Does .NET uses XMLSerializer behind the scenes to perform
> > serialization/deserialization of SOAP messages?
> >
> > If so, it seems to support these complex array types (defined in the same
> > .WSDL file) fine - and I didn't do anything tricky to make this happen
> > either. I just used the web reference tool to point to the WSDL file and
> > woila!
> >
> >
> > For example, on a successful login, the server returns a loginResponse
> > message that is defined as following:
> >
> > <wsdl:message name="loginResponse">
> > <wsdl:part name="loginReturn" type="impl:ArrayOfNamedValue" />
> > </wsdl:message>
> >
> > <complexType name="NamedValue">
> > <sequence>
> > <element name="name" nillable="true" type="xsd:string" />
> > <element name="value" nillable="true" type="xsd:anyType" />
> > </sequence>
> > </complexType>
> >
> > <complexType name="ArrayOfNamedValue">
> > <complexContent>
> > <restriction base="soapenc:Array">
> > <attribute ref="soapenc:arrayType" wsdl:arrayType="impl:NamedValue[]" />
> > </restriction>
> > </complexContent>
> > </complexType>
> >
> > <complexType name="Item">
> > <sequence>
> > <element name="id" type="xsd:long" />
> > <element name="name" nillable="true" type="xsd:string" />
> > <element name="requestedAttributes" nillable="true"
> > type="impl:ArrayOfNamedValue" />
> > <element name="type" nillable="true" type="xsd:string" />
> > </sequence>
> > </complexType>
> >
> >
> > Where: xmlns:impl="http://xmlns.mycompany.com/app/ws"
> > and: xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
> > and: xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> >
> >
> > In my code, the following works perfectly:
> >
> > int sessionTimeout = -1, transactionTimeout = -1;
> > Item user = null;
> > NamedValue[] nvArray = null;
> > try
> > {
> > nvArray = rlManager.login(username,password);
> > }
> > catch(System.Web.Services.Protocols.SoapException e)
> > {
> > throw;
> > }
> > for (int i=0; i <nvArray.Length; i++)
> > {
> > switch (nvArray[i].name)
> > {
> > case WebServiceConstants.LOGIN_USER:
> > if (!(nvArray[i].value is Item))
> > throw new
> > exception.UnexpectedTypeException(WebServiceConstants.LOGIN_USER + " not an
> > Item.");
> > user = (Item) nvArray[i].value;
> > if (user.type != ItemTypes.USER)
> > throw new
> > exception.UnexpectedTypeException(WebServiceConstants.LOGIN_USER + " not an
> > Item of type " + ItemTypes.USER);
> > break;
> > case WebServiceConstants.SESSION_TIMEOUT:
> > if (!(nvArray[i].value is Int32))
> > throw new
> > exception.UnexpectedTypeException(WebServiceConstants.SESSION_TIMEOUT + "
> > not an Int32.");
> > sessionTimeout = (Int32) nvArray[i].value;
> > break;
> > case WebServiceConstants.TRANSACTION_TIMEOUT:
> > if (!(nvArray[i].value is Int32))
> > throw new
> > exception.UnexpectedTypeException(WebServiceConstants.TRANSACTION_TIMEOUT +
> > " not an Int32.");
> > transactionTimeout = (Int32) nvArray[i].value;
> > break;
> > default:
> > break;
> > }
> > }
> > if (user == null)
> > {
> > throw new exception.AccessDeniedException();
> > }
> >
> > Is there an alternative preferred/standard mechanism to define array types
> > in the WSDL?
> >
> > Assuming I was not using the funky array stuff, and just trying to
> > deserialize a standard object with xsd string/int attributes etc by using
> > the detail element inside a SoapException, do you know how you would go
> > about doing this?
> >
> > many thanks,
> >
> > Matt.
> >
> >
> >
> >
> >
> > >From: "Dino Chiesa" <[EMAIL PROTECTED]>
> > >Reply-To:
[email protected]
> > >To: <
[email protected]>
> > >Subject: RE: Using .NET how to deserialize obj from detail element of SOAP
> > fault sentby AXIS?
> > >Date: Tue, 15 Mar 2005 17:32:05 -0800
> > >
> > >first,
> > >get rid of that
> > >soapenc:Array
> > >stuff.
> > >
> > >.NET's XML Serializer won't handle that !
> > >
> > >The SOAP serializer might, but ....
> > >I can't help you there.
> > >
> > >
> > >
> > >
> > >
> > >________________________________
> > >
> > >From: M S [mailto:[EMAIL PROTECTED]
> > >Sent: Tuesday, March 15, 2005 6:53 PM
> > >To:
[email protected]
> > >Subject: Using .NET how to deserialize obj from detail element of SOAP
> > >fault sentby AXIS?
> > >
> > >
> > >
> > >Hello,
> > >
> > >I'm trying to build a C# client to consume an AXIS Web Service (running
> > >SOAP over HTTP). The Web Service encodes full server-side exception
> > >traces in the Soap Fault > Detail element using complex type structures
> > >declared in the WSDL file.
> > >
> > >
> > >
> > >I have had absolutely no luck working out how I can deserialize the
> > >custom server exception object out of the detail element using .NET
> > >(C#). I' wondering if anyone in the AXIS community has done this
> > >before?
> > >
> > >
> > >
> > >I have tried both SoapFormatter, and XmlSerializer with absolutely no
> > >luck.
> > >
> > >
> > >
> > >try
> > >
> > >{
> > >
> > > <<<< e.g. login operation >>>>
> > >
> > >}
> > >
> > >catch (System.Web.Services.Protocols.SoapException e)
> > >
> > >{
> > >
> > > XmlReader reader = null;
> > >
> > > XmlWriter writer = null;
> > >
> > > MemoryStream mem = new MemoryStream();
> > >
> > > FdkException fe = null;
> > >
> > >
> > >
> > > try
> > >
> > > {
> > >
> > > reader = new XmlNodeReader(e.Detail.FirstChild);
> > >
> > > writer = new XmlTextWriter(mem, System.Text.Encoding.UTF8);
> > >
> > > writer.WriteNode(reader,true);
> > >
> > > writer.Flush();
> > >
> > > mem.Position = 0;
> > >
> > >
> > >
> > > <<<< Add deserialization code here >>>>
> > >
> > > fe = (FdkException) ....
> > >
> > > }
> > >
> > > catch (Exception ex)
> > >
> > > {
> > >
> > > System.Console.WriteLine(ex.toString());
> > >
> > > throw;
> > >
> > > }
> > >
> > >}
> > >
> > >
> > >
> > >The first deserialization mechansim I tried was using
> > >System.Runtime.Serialization.Formatters.Soap.SoapFormatter
> > >
> > >
> > >
> > >SoapFormatter sf = new SoapFormatter();
> > >
> > >sf.Binder = new FdkExceptionDeserializationBinder();
> > >
> > >fe = (FdkException) sf.Deserialize(mem);
> > >
> > >
> > >
> > >With FdkExceptionDeserializationBinder.cs looking like the following:
> > >
> > >
> > >
> > >public class FdkExceptionDeserializationBinder :
> > >System.Runtime.Serialization.SerializationBinder
> > >
> > >{
> > >
> > > public override Type BindToType(string assemblyName, string typeName)
> > >
> > > {
> > >
> > > if (assemblyName.Equals("http://xmlns.mycompany.com/app/ws"))
> > >
> > > {
> > >
> > > switch (typeName)
> > >
> > > {
> > >
> > > case "FdkException" : return typeof(FdkException); break;
> > >
> > > case "ArrayOfFdkExceptionEntry" : return
> > >typeof(FdkExceptionEntry[]); break;
> > >
> > > }
> > >
> > > }
> > >
> > > return Type.GetType(String.Format("{0}, {1}", typeName,
> > >assemblyName));
> > >
> > > }
> > >
> > >}
> > >
> > >
> > >
> > >This deserialization approach resulted in an exception:
> > >
> > >Exception Type: System.Runtime.Serialization.SerializationException
> > >
> > >Message: No Top Object
> > >
> > >Source: System.Runtime.Serialization.Formatters.Soap
> > >
> > >
> > >
> > >
> > >
> > >The second deserialization mechanism I tried was using XmlSerializer:
> > >
> > >XmlTypeMapping myMapping = (new
> > >SoapReflectionImporter().ImportTypeMapping(typeof(FdkException)));
> > >
> > >XmlSerializer serializer = new XmlSerializer(myMapping);
> > >
> > >fe = (FdkException) serializer.Deserialize(mem);
> > >
> > >
> > >
> > >I set Soap options in the FdkException class:
> > >
> > >
> > >
> > >using System;
> > >
> > >using System.Xml.Serialization;
> > >
> > >...
> > >
> > >[Serializable]
> > >
> > >[SoapTypeAttribute(Namespace="http://xmlns.mycompany.com/app/ws",
> > >TypeName="fault")]
> > >
> > >public class FdkException
> > >
> > >{
> > >
> > > public string errorCode;
> > >
> > > public FdkExceptionEntry[] exceptionEntries;
> > >
> > > public string serverStackTraceId;
> > >
> > >}
> > >
> > >
> > >
> > >using System;
> > >
> > >using System.Xml.Serialization;
> > >
> > >[Serializable]
> > >
> > >[SoapTypeAttribute(Namespace="http://xmlns.mycompany.com/app/ws",
> > >TypeName="FdkExceptionEntry")]
> > >
> > >public class FdkExceptionEntry
> > >
> > >{
> > >
> > > public string errorCode;
> > >
> > > public long id;
> > >
> > > public string serverStackTraceId;
> > >
> > >}
> > >
> > >
> > >
> > >
> > >
> > >I got the following exception:
> > >
> > >Message: There is an error in XML Document (1,541).
> > >
> > >Exception Type: System.InvalidOperationException
> > >
> > >Source: System.Xml
> > >
> > >
> > >
> > >Inner Exception:
> > >
> > >Message: Cannot assign object of type System.Xml.XmlNode[] to an object
> > >of type FdkException
> > >
> > >Exception Type: System.InvalidCastException
> > >
> > >
> > >
> > >
> > >
> > >Below is the SOAP message returned from the server on an invalid logon
> > >attempt (including Fault):-
> > >
> > >
> > >
> > >
> > >
> > ><soapenv:Envelope
> > >xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
> > >xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> > >xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
> > >
> > > <soapenv:Body>
> > >
> > > <soapenv:Fault>
> > >
> > > <faultcode>soapenv:Server.userException</faultcode>
> > >
> > > <faultstring>AccessDenied</faultstring>
> > >
> > > <detail>
> > >
> > > <ns1:fault xsi:type="ns1:FdkException"
> > >xmlns:ns1="http://xmlns.mycompany.com/app/ws">
> > >
> > > <errorCode xsi:type="soapenc:string"
> > >xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">AccessDenied -
> > >Invalid Credentials</errorCode>
> > >
> > > <exceptionEntries xsi:type="ns1:ArrayOfFdkExceptionEntry"
> > >xsi:nil="true"/>
> > >
> > > <serverStackTraceId xsi:type="soapenc:string"
> > >xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"/>
> > >
> > > </ns1:fault>
> > >
> > > </detail>
> > >
> > > </soapenv:Fault>
> > >
> > > </soapenv:Body>
> > >
> > ></soapenv:Envelope>
> > >
> > >
> > >
> > >
> > >
> > >Below is relevant pieces of the WSDL file relating to the FdkException
> > >object:
> > >
> > >
> > >
> > ><wsdl:types>
> > >
> > > <schema xmlns="http://www.w3.org/2001/XMLSchema"
> > >targetNamespace="http://xmlns.mycompany.com/app/ws">
> > >
> > > <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
> > >
> > > <complexType name="FdkExceptionEntry">
> > >
> > > <sequence>
> > >
> > > <element name="errorCode" nillable="true" type="xsd:string"/>
> > >
> > > <element name="id" type="xsd:long"/>
> > >
> > > <element name="serverStackTraceId" nillable="true"
> > >type="xsd:string"/>
> > >
> > > </sequence>
> > >
> > > </complexType>
> > >
> > > <complexType name="ArrayOfFdkExceptionEntry">
> > >
> > > <complexContent>
> > >
> > > <restriction base="soapenc:Array">
> > >
> > > <attribute ref="soapenc:arrayType"
> > >wsdl:arrayType="impl:FdkExceptionEntry[]"/>
> > >
> > > </restriction>
> > >
> > > </complexContent>
> > >
> > > </complexType>
> > >
> > > <complexType name="FdkException">
> > >
> > > <sequence>
> > >
> > > <element name="errorCode" nillable="true" type="xsd:string"/>
> > >
> > > <element name="exceptionEntries" nillable="true"
> > >type="impl:ArrayOfFdkExceptionEntry"/>
> > >
> > > <element name="serverStackTraceId" nillable="true"
> > >type="xsd:string"/>
> > >
> > > </sequence>
> > >
> > > </complexType>
> > >
> > > </schema>
> > >
> > ></wsdl:types>
> > >
> > >
> > >
> > ><wsdl:message name="FdkException">
> > >
> > > <wsdl:part name="fault" type="impl:FdkException"/>
> > >
> > ></wsdl:message>
> > >
> > >
> > >
> > ><wsdl:portType name="RemoteLoginManager">
> > >
> > > <wsdl:operation name="login" parameterOrder="username password">
> > >
> > > <wsdl:input name="loginRequest" message="impl:loginRequest"/>
> > >
> > > <wsdl:output name="loginResponse" message="impl:loginResponse"/>
> > >
> > > <wsdl:fault name="FdkException" message="impl:FdkException"/>
> > >
> > > </wsdl:operation>
> > >
> > ></wsdl:portType>
> > >
> > >
> > >
> > ><wsdl:binding name="RemoteLoginManagerSoapBinding"
> > >type="impl:RemoteLoginManager">
> > >
> > > <wsdlsoap:binding style="rpc"
> > >transport="http://schemas.xmlsoap.org/soap/http"/>
> > >
> > > <wsdl:operation name="login">
> > >
> > > <wsdlsoap:operation/>
> > >
> > > <wsdl:input>
> > >
> > > <wsdlsoap:body use="encoded"
> > >encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
> > >namespace="http://xmlns.mycompany.com/app/ws"/>
> > >
> > > </wsdl:input>
> > >
> > > <wsdl:output>
> > >
> > > <wsdlsoap:body use="encoded"
> > >encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
> > >namespace="http://xmlns.mycompany.com/app/ws"/>
> > >
> > > </wsdl:output>
> > >
> > > <wsdl:fault name="FdkException">
> > >
> > > <wsdlsoap:fault name="FdkException" use="encoded"
> > >encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
> > >namespace="http://xmlns.mycompany.com/app/ws"/>
> > >
> > > </wsdl:fault>
> > >
> > > </wsdl:operation>
> > >
> > ></wsdl:binding>
> > >
> > >
> > >
> > >
> > >
> > >Has anyone out there been able to deserialize from SOAP fault detail
> > >element using C#?
> > >
> > >
> > >
> > >many thanks,
> > >
> > >
> > >
> > >Matt.
> > >
> > >
> > >________________________________
> > >
> > >Try the new Beta version of MSN Messenger - it's FREE!
> > ><http://g.msn.com/8HMBENUS/2752??PS=47575>
> >
> > ________________________________
> > Try the new Beta version of MSN Messenger - it's FREE!