Problem deserializing XML (I think) from remote SOAP service


G

googlegroups

Hi,

My company has developed a series of SOAP services using SOAP::Lite on
Linux. We've successfully had other Perl, PHP, Ruby and Java clients
access the services, but no luck with .NET yet. I've created a simple
service to try and identify the problem, which hopefully somebody will
be able to help with. I think it's a problem with how the server is
serializing the data, or more specifically, how .NET expects it to be
serialized...

I consume the following document literal (wrapped) WSDL file:
http://alpha.wirespring.net/web_services/Endpoints/SOAP/Demo?WSDL,
generate a dll using wsdl.exe and csc. You can re-generate it if you
like, but the method call for return_chars() looks like this:

public string
return_chars([System.Xml.Serialization.XmlElementAttribute(
"return_chars",
Namespace="urn:Endpoints/SOAP/Demo"
)] return_chars return_chars1) {
object[] results = this.Invoke("return_chars", new object[] {
return_chars1});
return ((string)(results[0]));
}

We then compile a C# client against Demo.dll (the Security section is
optional, since we've disabled the authentication to try and work this
bug out):

using System;
using System.Diagnostics;
using System.Net;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;

class Example1 {

public static void Main(string[] args) {
// Set parameters
return_chars x = new return_chars();
x.input_string = "NET SOAP test string";
x.second_string = "";

//Security auth_info = new Security();
//auth_info.Account = "ACCOUNTNAME";
//auth_info.Username = "username";
//auth_info.Password = "password";

Demo myDemo = new Demo();
//myDemo.SecurityValue = auth_info;
Console.WriteLine("Got return value: " +
myDemo.return_chars(x));
}
}

When we execute the client, it hits the server, which returns back
valid-looking XML, however myDemo.return_chars(x) is null. I used .NET
Webservice Studio to examine the response content. This is what the
server is sending back:

ResponseCode: 200 (OK)
Pragma:no-cache
SOAPAction:"Endpoints/SOAP/Demo#return_chars"
X-Cache:MISS from alpha.wirespring.net
Transfer-Encoding:chunked
Cache-Control:no-cache
Content-Type:text/xml
Date:Fri, 08 Dec 2006 18:58:43 GMT
Expires:Fri, 08 Dec 2006 18:58:43 GMT
Server:Apache/1.3.34 (Unix) mod_perl/1.29

<?xml version="1.0" encoding="utf-16"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<return_charsResponse
soap:encodingStyle="http://xml.apache.org/xml-soap/literalxml">
<s-gensym18 xsi:type="xsd:string">N.E.T. .S.O.A.P .t.e.s.t.
..s.t.r.i.n.g</s-gensym18>
</return_charsResponse>
</soap:Body>
</soap:Envelope>

The visual tool in .NET WebService Studio also indicates that the
result string is null. Oddly, though, when I use the Java-based
StrikeIron Web Service Analyzer, I get the exact same return content,
but it does correctly grab the return string.

At this point we're about out of ideas, so I'd appreciate any insight
that you .NET experts may have!
 
Ad

Advertisements

R

RYoung

I generated client side proxy using wsdl.exe pointed at the WSDL you
specified.

In the proxy class, I commented out the SoapDocumentMethodAttribute on the
return_chars() method and added the following:

[System.Web.Services.Protocols.SoapRpcMethod("",
RequestNamespace="urn:Endpoints/SOAP/Demo",
ResponseNamespace="urn:Endpoints/SOAP/Demo")]

When I ran the client app, I got the following result:

r.e.t.u.r.n._.c.h.a.r.s.=.H.A.S.H

followed by a period-delimited hash code. Did you alter your service to
return that by chance?

Anyways, the SOAP message capture from Colasoft Capsa resembles the capture
you mentioned, except of course with the hash data in it.

Ron
Hi,

My company has developed a series of SOAP services using SOAP::Lite on
Linux. We've successfully had other Perl, PHP, Ruby and Java clients
access the services, but no luck with .NET yet. I've created a simple
service to try and identify the problem, which hopefully somebody will
be able to help with. I think it's a problem with how the server is
serializing the data, or more specifically, how .NET expects it to be
serialized...

I consume the following document literal (wrapped) WSDL file:
http://alpha.wirespring.net/web_services/Endpoints/SOAP/Demo?WSDL,
generate a dll using wsdl.exe and csc. You can re-generate it if you
like, but the method call for return_chars() looks like this:

public string
return_chars([System.Xml.Serialization.XmlElementAttribute(
"return_chars",
Namespace="urn:Endpoints/SOAP/Demo"
)] return_chars return_chars1) {
object[] results = this.Invoke("return_chars", new object[] {
return_chars1});
return ((string)(results[0]));
}

We then compile a C# client against Demo.dll (the Security section is
optional, since we've disabled the authentication to try and work this
bug out):

using System;
using System.Diagnostics;
using System.Net;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;

class Example1 {

public static void Main(string[] args) {
// Set parameters
return_chars x = new return_chars();
x.input_string = "NET SOAP test string";
x.second_string = "";

//Security auth_info = new Security();
//auth_info.Account = "ACCOUNTNAME";
//auth_info.Username = "username";
//auth_info.Password = "password";

Demo myDemo = new Demo();
//myDemo.SecurityValue = auth_info;
Console.WriteLine("Got return value: " +
myDemo.return_chars(x));
}
}

When we execute the client, it hits the server, which returns back
valid-looking XML, however myDemo.return_chars(x) is null. I used .NET
Webservice Studio to examine the response content. This is what the
server is sending back:

ResponseCode: 200 (OK)
Pragma:no-cache
SOAPAction:"Endpoints/SOAP/Demo#return_chars"
X-Cache:MISS from alpha.wirespring.net
Transfer-Encoding:chunked
Cache-Control:no-cache
Content-Type:text/xml
Date:Fri, 08 Dec 2006 18:58:43 GMT
Expires:Fri, 08 Dec 2006 18:58:43 GMT
Server:Apache/1.3.34 (Unix) mod_perl/1.29

<?xml version="1.0" encoding="utf-16"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<return_charsResponse
soap:encodingStyle="http://xml.apache.org/xml-soap/literalxml">
<s-gensym18 xsi:type="xsd:string">N.E.T. .S.O.A.P .t.e.s.t.
.s.t.r.i.n.g</s-gensym18>
</return_charsResponse>
</soap:Body>
</soap:Envelope>

The visual tool in .NET WebService Studio also indicates that the
result string is null. Oddly, though, when I use the Java-based
StrikeIron Web Service Analyzer, I get the exact same return content,
but it does correctly grab the return string.

At this point we're about out of ideas, so I'd appreciate any insight
that you .NET experts may have!
 
G

googlegroups

Hi Ron,

Interesting response. We did actually modify the service, and from
what I can tell requests from the .NET client either don't include the
SOAPAction handler (which is where we get our class/method name from by
default), or send XML that deserializes in such a way that our server
passes in a reference to the method in as its first parameter (which in
Perl would just read out as garbage like the HASH(0x8c419c8) that you
saw.

Here's what we have now:
--------------------
Case 1: System.Web.Services.Protocols.SoapParameterStyle.Bare
--------------------

[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"Endpoints/SOAP/Demo#return_chars",
Use=System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare
)]

Server gets: well-formed data, deserialized into method call from
SOAPAction header and data payload from SOAP envelope.
Server returns: returning 'N.E.T. .S.O.A.P. .t.e.s.t. .2' (correct
response).
C# client returns: null


--------------------
Case 2: SoapRpcMethod instead of SoapDocumentMethodAttribute
--------------------

[System.Web.Services.Protocols.SoapRpcMethod("",
RequestNamespace="urn:Endpoints/SOAP/Demo",
ResponseNamespace="urn:Endpoints/SOAP/Demo")]

Server gets: No SOAPAction header, consequently deserializes data
improperly (which I'm trying to investigate with the SOAP::Lite guys
now)
Server returns: r.e.t.u.r.n._.c.h.a.r.s.=.H.A.S.H (garbage)
C# client returns: r.e.t.u.r.n._.c.h.a.r.s.=.H.A.S.H (correct, since
it is technically what the server is returning)


--------------------
Case 3: System.Web.Services.Protocols.SoapParameterStyle.Wrapped
--------------------

[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"Endpoints/SOAP/Demo#return_chars",
Use=System.Web.Services.Description.SoapBindingUse.Literal,

ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped
)]

Server gets: SOAPAction comes through OK, but data deserializes
improperly anyway (the same way that it breaks in Case 2 above, in
fact.
Server returns: r.e.t.u.r.n._.c.h.a.r.s.=.H.A.S.H (garbage)
C# client returns: null


We're generating what I believe is valid Document/literal/wrapped WSDL,
however setting SoapParameterStyle to wrapped produces broken results
in and out. Obviously, what I'd like is to be able to send like we do
in Case 1, but receive like we do in Case 2.

As a related question, is there a way to look at the XML coming and
going from the c# client? I've been relying on .NET WebServiceStudio,
but I can't test different permutations of my c# code with that.

Thanks again!


I generated client side proxy using wsdl.exe pointed at the WSDL you
specified.

In the proxy class, I commented out the SoapDocumentMethodAttribute on the
return_chars() method and added the following:

[System.Web.Services.Protocols.SoapRpcMethod("",
RequestNamespace="urn:Endpoints/SOAP/Demo",
ResponseNamespace="urn:Endpoints/SOAP/Demo")]

When I ran the client app, I got the following result:

r.e.t.u.r.n._.c.h.a.r.s.=.H.A.S.H

followed by a period-delimited hash code. Did you alter your service to
return that by chance?

Anyways, the SOAP message capture from Colasoft Capsa resembles the capture
you mentioned, except of course with the hash data in it.

Ron
 
R

RYoung

In regards to your last question, I've been using ColaSoft Capsa trial
version, but the trial doesn't let you save the data being presented (or
even copy to clipboard).

I've downloaded Wireshark (Ethereal) and it shows all info that Capsa does,
so you may want to try that if you want to observe the network packets being
communicated. The following link is Wireshark on sourceforge which offers
better download speeds than on the ethereal site:

http://sourceforge.net/project/showfiles.php?group_id=255&package_id=193847&release_id=460013

I'm almost sure your aware of this, but I have to ask: Are you aware that
wsdl.exe pointed at the .wsdl file for the service and with the /si option
will generate a service class interface, that when implemented and hosted on
IIS will return a valid string result?

In other words - the same service description, and one implementation on
Apache, the other on IIS - and the one on IIS returns the desired result,
where "desired result" is the result which the .NET consumer seems to be
expecting.

Ron
Hi Ron,

Interesting response. We did actually modify the service, and from
what I can tell requests from the .NET client either don't include the
SOAPAction handler (which is where we get our class/method name from by
default), or send XML that deserializes in such a way that our server
passes in a reference to the method in as its first parameter (which in
Perl would just read out as garbage like the HASH(0x8c419c8) that you
saw.

Here's what we have now:
--------------------
Case 1: System.Web.Services.Protocols.SoapParameterStyle.Bare
--------------------

[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"Endpoints/SOAP/Demo#return_chars",
Use=System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare
)]

Server gets: well-formed data, deserialized into method call from
SOAPAction header and data payload from SOAP envelope.
Server returns: returning 'N.E.T. .S.O.A.P. .t.e.s.t. .2' (correct
response).
C# client returns: null


--------------------
Case 2: SoapRpcMethod instead of SoapDocumentMethodAttribute
--------------------

[System.Web.Services.Protocols.SoapRpcMethod("",
RequestNamespace="urn:Endpoints/SOAP/Demo",
ResponseNamespace="urn:Endpoints/SOAP/Demo")]

Server gets: No SOAPAction header, consequently deserializes data
improperly (which I'm trying to investigate with the SOAP::Lite guys
now)
Server returns: r.e.t.u.r.n._.c.h.a.r.s.=.H.A.S.H (garbage)
C# client returns: r.e.t.u.r.n._.c.h.a.r.s.=.H.A.S.H (correct, since
it is technically what the server is returning)


--------------------
Case 3: System.Web.Services.Protocols.SoapParameterStyle.Wrapped
--------------------

[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"Endpoints/SOAP/Demo#return_chars",
Use=System.Web.Services.Description.SoapBindingUse.Literal,

ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped
)]

Server gets: SOAPAction comes through OK, but data deserializes
improperly anyway (the same way that it breaks in Case 2 above, in
fact.
Server returns: r.e.t.u.r.n._.c.h.a.r.s.=.H.A.S.H (garbage)
C# client returns: null


We're generating what I believe is valid Document/literal/wrapped WSDL,
however setting SoapParameterStyle to wrapped produces broken results
in and out. Obviously, what I'd like is to be able to send like we do
in Case 1, but receive like we do in Case 2.

As a related question, is there a way to look at the XML coming and
going from the c# client? I've been relying on .NET WebServiceStudio,
but I can't test different permutations of my c# code with that.

Thanks again!


I generated client side proxy using wsdl.exe pointed at the WSDL you
specified.

In the proxy class, I commented out the SoapDocumentMethodAttribute on
the
return_chars() method and added the following:

[System.Web.Services.Protocols.SoapRpcMethod("",
RequestNamespace="urn:Endpoints/SOAP/Demo",
ResponseNamespace="urn:Endpoints/SOAP/Demo")]

When I ran the client app, I got the following result:

r.e.t.u.r.n._.c.h.a.r.s.=.H.A.S.H

followed by a period-delimited hash code. Did you alter your service to
return that by chance?

Anyways, the SOAP message capture from Colasoft Capsa resembles the
capture
you mentioned, except of course with the hash data in it.

Ron
 
G

googlegroups

Hi Ron,

I wasn't actually aware of the /is switch, but after reading the
documentation I'm not sure how it helps, either. We're a Linux shop,
so we don't have IIS servers at all, nor do we typically use .NET

Basically, though, I think the problem is more on our SOAP server's
side (we use Perl and SOAP::Lite) than with Apache vs. IIS. We've
experimented with mono, the open-source .NET project that will run on
Linux, and were able to generate services that a Win32 .NET client
could consume, so I don't think Apache is the problem. Unfortunately,
though, that also doesn't help us much, since all of our existing
services are written in Perl (and would be somewhat unwieldy to port)

Thanks for the tip on Wireshark, btw. It actually helped identify
another (different) problem. It never rains, but it pours :)
 
Ad

Advertisements

R

RYoung

Hi,
Glad Wireshark offered some insight. In regards to the /si switch and
wsdl.exe, I was just wondering why the same wsdl, when implemented on IIS
seemingly returns the desired result. I won't say when implemented on
Apache/SOAP::Lite that the result is incorrect though.

Basically, the wsdl being the abstract definition of the service, and the
contract by which the implementation will fullfill, it is strange (and
unacceptable) that a .NET implementation returns different results than the
SOAP::Lite version.

Ron
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top