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!

Reply via email to