Anne,
First a correction, I meant to say Java2WSDL.
I looked for a bug and I can't find anything, do you know if there's a bug filed already? If not, I will file one.
I wonder if there's still enough time to get it fixed for the 1.2 release.
Can any of the Axis developers please comment on this?
Thanks.
Tim
Anne Thomas Manes wrote:
I think so.
On Fri, 18 Mar 2005 12:38:03 -0800, Tim K. (Gmane) <[EMAIL PROTECTED]> wrote:
Anne,
Would this then be an Axis bug? Shouldn't Axis generate the proper WSDL for custom exceptions when using WSDL2Java?
Thanks.
Tim
Anne Thomas Manes wrote:
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: [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!
