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!

Reply via email to