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=show > > > 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: axis-user@ws.apache.org > 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: axis-user@ws.apache.org > >To: <axis-user@ws.apache.org> > >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: axis-user@ws.apache.org > >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!