.NET Forum / ASP.NET / Web Services / December 2006
Problem deserializing XML (I think) from remote SOAP service
|
|
Thread rating:  |
googlegroups@wirespring.com - 11 Dec 2006 20:21 GMT 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!
RYoung - 11 Dec 2006 21:53 GMT 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, > [quoted text clipped - 90 lines] > At this point we're about out of ideas, so I'd appreciate any insight > that you .NET experts may have! googlegroups@wirespring.com - 11 Dec 2006 22:45 GMT 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. [quoted text clipped - 17 lines] > > Ron RYoung - 12 Dec 2006 20:17 GMT 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&rele ase_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, > [quoted text clipped - 89 lines] >> >> Ron googlegroups@wirespring.com - 13 Dec 2006 16:40 GMT 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 :)
> 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 [quoted text clipped - 18 lines] > > Ron RYoung - 15 Dec 2006 01:25 GMT 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
> Hi Ron, > [quoted text clipped - 39 lines] >> >> Ron
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|