I'm trying to write a SOAP server in Python that can interoperate with
Microsoft .Net 3.5 SOAP clients. I'm using the simple soaplib server
from the tutorials to do tests:
class HelloWorldService(SimpleWSGISoapApp):
@soapmethod(String, Integer, _returns=Array(String))
def say_hello(self, name, times):
results = []
for i in range(times):
results.append('Hello ' + name)
return results
I've installed that server on Apache. I can talk to it successfully
using a soaplib Python client, so I know that my install is not
broken. However, when we try to use WCF / DotNet 3.5 to talk to that
web service, things don't work so well. Pointing the WCFTestClient
Microsoft application at the WSDL of the server produces a client that
requires a say_hello structure which then contains "name" and "times"
parameters, instead of taking those two parameters directly as input.
And WCFTestClient fails to parse the response of the Python SOAP
service correctly, as it only shows "null" as the response.
Here are the XML of the request and response between WCFTestClient and
the Python soaplib service.
Request:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/
ws/2005/05/addressing/none">say_hello</Action>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<say_hello
xmlns="_mod_wsgi_409f19bd606ce6b2308041f28b7641c5.HelloWorldService">
<name xmlns="">bob</name>
<times xmlns="">2</times>
</say_hello>
</s:Body>
</s:Envelope>
Response:
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/1999/XMLSchema-
instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" />
<SOAP-ENV:Body>
<say_helloResponse>
<say_helloResult type="tns:stringArray">
<string xsi:type="xs:string">Hello bob</string>
<string xsi:type="xs:string">Hello bob</string>
</say_helloResult>
</say_helloResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
By comparison, here is the request and response produced when talking
to the equivalent service (implemented in DotNet 3.5):
Request:
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">http://tempuri.org/
HelloWorldService2/say_hello</a:Action>
<a:MessageID>urn:uuid:c92c467c-6307-48dc-9ffa-d037cafd2522</
a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</
a:Address>
</a:ReplyTo>
</s:Header>
<s:Body>
<say_hello xmlns="http://tempuri.org/">
<names>Bob</names>
<times>3</times>
</say_hello>
</s:Body>
</s:Envelope>
Response:
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">http://tempuri.org/
HelloWorldService2/say_helloResponse</a:Action>
<a:RelatesTo>urn:uuid:4f3e63ca-9f38-4126-90fc-c916b37d5cda</
a:RelatesTo>
<a:To s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/
anonymous</a:To>
</s:Header>
<s:Body>
<say_helloResponse xmlns="http://tempuri.org/">
<say_helloResult xmlns:b="http://schemas.microsoft.com/2003/10/
Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-
instance">
<b:string>Hello Bob</b:string>
<b:string>Hello Bob</b:string>
<b:string>Hello Bob</b:string>
</say_helloResult>
</say_helloResponse>
</s:Body>
</s:Envelope>
I'm using the latest version from the trunk. The last release
exhibited the same problems too. Am I doing anything wrong? Has anyone
succeeded in making a soaplib service talk to a DotNet 3.5 / WCF
client (which should be kind of common in the SOAP world)?
Any help would be much appreciated.
Christian
thanks for the detailed report. one thing though: what trunk are you
using? it should be from github, from either mine (plq) or cuker's repo
in github. some .net-related fixes were applied to that code.
regards,
burak
ps: this list has been migrated to so...@python.org, in an effort to
unite the fragmented soap effort around python.
I'm using this: git://github.com/jkp/soaplib.git
with a couple patches applied from looking through the bug reports.
Is that the best code to use, or should I try with another git branch?
Christian
hello,
please try:
git://github.com/cuker/soaplib.git
and let us know if you have any problems.
thanks
burak
This works better. Now the .Net client can parse the result of the
function (a list of strings) correctly. However, both the parameters
and results of the remote function call are seen as being wrapped in a
"say_hello" struct instead of simply being the paramters and return
value of the say_hello remote function.
Let me know what kind of additional information (if any) you need to
debug this.
Thank you,
Christian
hi,
this has been a known issue for some time now. the fix will break
backwards compatibility, so unless there's a strong community consensus
on changing this, i think it should stay as it is.
burak
Hm. I don't know how you were planning on gauging community consensus,
but my feel is that for people who are new to soaplib and want to
interoperate with other SOAP implementations (of which Microsoft's is
the most widespread), this problem is rather a deal-breaker. It's also
a deal-breaker if you're writing a SOAP server that implements an
existing interface and have no control over the format of the RPC
calls made by the client. Personally, if soaplib can't interoperate
correctly with Microsoft's SOAP stack, I'll have to use something
else.
I understand that just changing the existing behavior without
transition and breaking existing users is not an option. But it
doesn't make the bug into a feature, especially for people wanting to
use SOAP to interoperate with other systems.. How about making both
behaviors available and selectable with a function call? The first
releases can default to the old behavior. And after sufficient time
(and notices in advance in the release notes, etc.) the new behavior
can become the default.
Also, is there a patch or git branch that has that fix, so I can test
it?
Thanks,
Christian