Consuming .Net Web Service using Perl and SOAP Lite
I'm trying to consume a .Net Web Service using perl and SOAP Lite.
When I consume the web service in a .Net client - it posts to the .asmx endpoint the following:
<?xml version="1.0" encoding="utf-8"?>
<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/"
xmlns:tns="http://mysoapnamespace.com/"
xmlns:types="http://mysoapnamespace.com/encodedTypes">
<soap:Body>
<tns:HellowWorld />
</soap:Body>
</soap:Envelope>
How can I generate that same request using SOAP Lite? I've been through a variety of SOAP Lite docs and articles with no luck. So far I have the following:
#!/usr/bin/perl
use SOAP::Lite 'trace', 'debug' ;
$api_ns = "https://mysoapnamespace.com";
$api_url = "http://mysoapnamespace/api.asmx";
$action = "HelloWorld";
my $soap = SOAP::Lite
-> readable(1)
-> uri($api_ns)
-> proxy($api_url)
-> on_action(sub { return "\"$action\"" }) ;
return $soap->HellowWorld();
开发者_如何学运维This generates this, incorrect XML:
<?xml version="1.0" encoding="UTF-8"?>
<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>
<HellowWorld xmlns="http://mysoapnamespace.com" xsi:nil="true" />
</soap:Body>
</soap:Envelope>
Update:
When I post the 1st xml to my service using fiddler it returns my "Hello World" result. When I post the 2nd I get the following:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:Client</faultcode><faultstring>System.Web.Services.Protocols.SoapException: Server was unable to read request. ---> System.InvalidOperationException: There is an error in XML document (9, 6). ---> System.InvalidOperationException: <HellowWorld xmlns='http://mysoapnamespace.com'> was not expected.
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read21_HellowWorld()
at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer28.Deserialize(XmlSerializationReader reader)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
--- End of inner exception stack trace ---
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()</faultstring><detail /></soap:Fault></soap:Body></soap:Envelope>
Found the problem - the trailing slash on the namespace. .Net just figures that stuff out for your but it needs to be explicitly set in Perl. Also, figured out how to us the ns() function to add names spaces.
This will generate the correct XML.
#!/usr/bin/perl
use SOAP::Lite 'trace', 'debug' ;
$api_ns = "https://mysoapnamespace.com/";
$api_url = "http://mysoapnamespace/api.asmx";
$action = "HelloWorld";
my $soap = SOAP::Lite
-> readable(1)
-> ns($api_types,'types')
-> ns($api_ns,'tns')
-> proxy($api_url)
-> on_action(sub { return "\"$action\"" }) ;
return $soap->HellowWorld();
This link was very helpful in figuring out SOAP::Lite - http://kobesearch.cpan.org/htdocs/SOAP-Lite/SOAP/Lite.pm.html
I had to do the following to get it to work (add this line after my $soap... line):
$soap->ns('http://schemas.xmlsoap.org/soap/envelope/',"s");
I hope this will save someone some time... It took a while to get it figured out... :-)
BTW: I am using .Net 4.5 WCF with a windows service for Web Service server and Perl (activestate) V5.16.3 with SOAP::Lite V 1.08.
精彩评论