I've got this WSDL(the service is not mine): http://soaptest.webapi-beta.gratka.pl/dom.html?wsdl
When I use WCF generated proxy the method tag in request soap message gets additional namespace definition like:
<q1:zaloguj xmlns:q1="http://soaptest.webapi-beta.gratka.pl/dom.html">
When I use PHP or proxy generated by wsdl.exe this doesn't happen.
I would like to ask, why does WCF do so, and is there possibility to change this behaviour (without using hand-made message modification in BeforeSendRequest)
Below I paste messages generated by PHP and WCF:
PHP one:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://soaptest.webapi-beta.gratka.pl/dom.html" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:zaloguj>
<login xsi:type="xsd:string">login</login>
<haslo xsi:type="xsd:string">password</haslo>
<klucz_webapi xsi:type="xsd:string">key</klucz_webapi>
<id_kategoria xsi:type="xsd:int">382a</id_kategoria>
<wersja_webapi xsi:type="xsd:int">2</wersja_webapi>
</ns1:zaloguj>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
WCF one:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<q1:zaloguj xmlns:q1="http://soaptest.webapi-beta.gratka.pl/dom.html">
<login xsi:type="xsd:string">login</login>
<haslo xsi:type="xsd:string">password</haslo>
<klucz_webapi xsi:type="xsd:string">key</klucz_webapi>
<id_kategoria xsi:type="xsd:int">382</id_kategoria>
<wersja_webapi xsi:type="xsd:int">2</wersja_webapi>
</q1:zaloguj>
</s:Body>
</s:Envelope>
Are you facing any issues? As far as xml is concerned, both are equivalent. PHP code is declaring the namespace (xmlns:ns1="http://soaptest.webapi-beta.gratka.pl/dom.html") at the root element while WCF is declaring at the point where it is needed - I would believe that this is what WSDL's implementation would be - does not seem to be anything wrong in it.
Related
My customer wants to a web service for integration. They send me the documentation and I created a WCF Service with methods.
But there are namespaces and prefixs problem. I didn't find any solution and I didn't find any suggest. For example there is a different tag (
Customer will send request like this:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ws="http://ws.common.haciosman.com">
<soapenv:Header />
<soap:Body>
<ws:getSystemStatus/>
</soap:Body>
</soap:Envelope>
Customer wants to response like that:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header/>
<soapenv:Body>
<ns:getSystemStatusResponse xmlns:ns="http://ws.common.haciosman.com">
<ns:return xsi:type="ax21:OutputMessage" xmlns:ax21="http://ws.common.haciosman.com/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ax21:code>200</ax21:code>
<ax21:description>Success</ax21:description>
</ns:return>
</ns:getSystemStatusResponse>
</soapenv:Body>
</soapenv:Envelope>
Okay, I created a service but namespace and prefix not match. My service response like that:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<getSystemStatusResponse>
<getSystemStatusResult xmlns:a="http://schemas.datacontract.org/2004/07/WCFLocal.cls" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:code>200</a:code>
<a:description>Success</a:description>
</getSystemStatusResult>
</getSystemStatusResponse>
</s:Body>
</s:Envelope>
As you see, tags are different. What is wrong and how can I change prefix in WCF Service?
Thanks for your reply.
I have a WCF service that works with a test client generated with SvcUtil.exe.
But my real client is another company that used different technology.
With the generated test client the XML looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<PostModel xmlns="http://tempuri.org/">
<model xmlns:a="http://schemas.datacontract.org/2004/07/SomeName.Models" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Items>
<a:Item>
<a:SomeElement1>SomeValue</a:SomeElement1>
<a:SomeElement2>SomeValue</a:SomeElement2>
</a:Item>
<a:Item>
<a:SomeElement1>SomeValue</a:SomeElement1>
<a:SomeElement2>SomeValue</a:SomeElement2>
</a:Item>
</a:Items>
<a:MoreItems>
<a:MoreItem>
<a:SomeElement3>binary</a:SomeElement3>
</a:MoreItem>
</a:MoreItems>
</model>
</PostModel>
</s:Body>
</s:Envelope>
But the real client sends the xml without alias:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<PostModel xmlns="http://tempuri.org/">
<model xmlns="http://schemas.datacontract.org/2004/07/SomeName.Models">
<Items>
<Item>
<SomeElement1>SomeValue</SomeElement1>
<SomeElement2>SomeValue</SomeElement2>
</Item>
<Item>
<SomeElement1>SomeValue</SomeElement1>
<SomeElement2>SomeValue</SomeElement2>
</Item>
</Items>
<MoreItems>
<MoreItem>
<SomeElement3>binary</SomeElement3>
</MoreItem>
</MoreItems>
</model>
</PostModel>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The result is that the model that I receive in the endpoint is NULL.
If I catch the request in fiddler and edit it, add nothing but the alias for the model namespace and add it to the child-elements it works.
Is there a solution for this problem, as far as I know the XML that the client sends is valid XML, aliases are not mandatory.
The difference between the test client XML and the real client XML lies in the namespace of the element model. From the test client:
<PostModel xmlns="http://tempuri.org/">
<model xmlns:a="http://schemas.datacontract.org/2004/07/SomeName.Models" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
This defines an element with local name "model". It has no namespace prefix so exists in the default namespace. However, it does not define a default namespace for itself -- instead it defines namespaces with prefixes "a" and "i". Thus it belongs in whatever default namespace its parent hierarchy defines, in this case "http://tempuri.org/" from its immediate parent.
In the real client's XML, the model element again has no prefix but does have its own default namespace declaration:
<PostModel xmlns="http://tempuri.org/">
<model xmlns="http://schemas.datacontract.org/2004/07/SomeName.Models">
Thus model falls into the namespace "http://schemas.datacontract.org/2004/07/SomeName.Models" rather than the parent's default namespace.
All the child elements of model are in the same namespace in both XML versions. It's only the model element itself which is inconsistent.
This inconsistency would explain the null model in the endpoint.
I have downloaded WsdlUI, a open source C# SOAP client that is able to consume and process WCF messages without needing to add a reference. I can post to a method that has simple types(like strings and ints). When the WCF method has a complex type the XML envelope is incorrect. I am somewhat a noob to WCF and am a little lost with all the code... someone please help; how do I get the XML to return the correct XML?
I enabled tracing on my server and here is the valid xml envelope from a console app that has the service reference added:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://host.com/BG.WCF/Service.svc</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/MobileInterface/CreateQueuedMsg</Action>
</s:Header>
<s:Body>
<CreateQueuedMsg xmlns="http://tempuri.org/">
<Token>add568d9-45e0-0000-98a5-762b84989797</Token>
<BGSMSMessage xmlns:a="http://schemas.datacontract.org/2004/07/BG.Bus.Mobile.Classes" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:BusinessID>Test</a:BusinessID>
<a:CommsGUID>eca403e7-1116-4bc3-a476-31e91c4ca33f</a:CommsGUID>
<a:DestinationAddress>+27000000000</a:DestinationAddress>
<a:Msg>test msg</a:Msg>
<a:MsgEncodingType>Default</a:MsgEncodingType>
<a:SendDT>2014-02-24T07:21:45.3187492+02:00</a:SendDT>
<a:SystemID>Test</a:SystemID>
<a:ValidityDT>2014-02-27T07:21:45.3187492+02:00</a:ValidityDT>
</BGSMSMessage>
<smsRoute xmlns:a="http://schemas.datacontract.org/2004/07/BG.Bus.Mobile.Classes" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:SMSRoute>BGWASP</a:SMSRoute>
</smsRoute>
</CreateQueuedMsg>
</s:Body>
here is the envelope WsdlUi returns:
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://bgvm08mbl01.businessgenetics.co.za/BG.Bus/BG.Bus.Mobile.WCF/MobileService.svc</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/MobileInterface/CreateQueuedMsg</Action>
</s:Header>
<soap:Body>
<CreateQueuedMsg xmlns="http://tempuri.org/">
<Token>ADD568D9-45E0-498E-98A5-762B84989797</Token>
<BGSMSMessage>
<BusinessID>Test</BusinessID>
<CommsGUID>559eb322-7b01-438d-93f1-74b1aafccc4f</CommsGUID>
<DestinationAddress>0000000000</DestinationAddress>
<Msg>Testers2014-02-24 07:37:53</Msg>
<MsgEncodingType>Default</MsgEncodingType>
<SendDT>2014-02-24 07:37:53</SendDT>
<SystemID>Test</SystemID>
<ValidityDT>2014-02-27 07:37:53</ValidityDT>
</BGSMSMessage>
<smsRoute>
<SMSRoute>BGWASP</SMSRoute>
<SMSRoute>GV</SMSRoute>
</smsRoute>
</CreateQueuedMsg>
</soap:Body>
I am the developer of WsdlUI so thanks for using it.
The application currently does not work with complex types due to the bug that you are referring to.
I should have a release out mid June that will fix this problem.
Thanks for the detailed description of the problem in your post.
I've got this WSDL(the service is not mine): http://soaptest.webapi-beta.gratka.pl/dom.html?wsdl
When I get response from method "pobierz_kategorie" I get exception like that
CommunicationException
Error in deserializing body of reply message for operation 'pobierz_kategorie'.
{"There is an error in XML document (2, 501)."} {"The specified type was not recognized: name='kategoria_drzewo', namespace='http://soap.webapi-beta.gratka.pl/dom.html', at ."}
I would like to ask how to modify WSDL or WCF configuration or generated proxy to make it working. When I use PHP to call that method it works so I guess that must be some XMLSerializer problem.
This the response message I get:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://soap.webapi-beta.gratka.pl/dom.html" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:pobierz_kategorieResponse>
<drzewo_kategorii SOAP-ENC:arrayType="ns1:kategoria_drzewo[48]" xsi:type="ns1:drzewo_kategorii">
<item xsi:type="ns1:kategoria_drzewo">
<id xsi:type="xsd:int">382</id>
<nazwa xsi:type="xsd:string">Dom</nazwa>
<dane xsi:type="xsd:string">0</dane>
<id_rodzic xsi:type="xsd:int">1</id_rodzic>
<poziom xsi:type="xsd:int">0</poziom>
<id_prasa xsi:type="xsd:int">2</id_prasa>
</item>
<item xsi:type="ns1:kategoria_drzewo">
<id xsi:type="xsd:int">8251</id>
<nazwa xsi:type="xsd:string">Pokoje</nazwa>
<dane xsi:type="xsd:string"/>
<id_rodzic xsi:type="xsd:int">382</id_rodzic>
<poziom xsi:type="xsd:int">1</poziom>
<id_prasa xsi:type="xsd:int">0</id_prasa>
</item>
</drzewo_kategorii>
</ns1:pobierz_kategorieResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
That is the request:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q1="http://soaptest.webapi-beta.gratka.pl/dom.html">
<s:Body s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<q1:pobierz_kategorie>
<sesja xsi:type="xsd:string">ad9e730460e334b916c95533c8da320003ac7e14</sesja>
<id_kategoria xsi:type="xsd:int">382</id_kategoria>
</q1:pobierz_kategorie>
</s:Body>
</s:Envelope>
I've retrieved that WSDL and the response message name does not match what you have above.
Where you have pobierz_kategorieResponse in the wsdl, it is pobierz_kategorie_wyjscie in the WSDL definition.
Message...
<message name="pobierz_kategorie_wyjscie">
<part name="drzewo_kategorii" type="tns:drzewo_kategorii"/>
</message>
Operation...
<operation name="pobierz_kategorie">
<input message="tns:pobierz_kategorie_wejscie"/>
<output message="tns:pobierz_kategorie_wyjscie"/>
</operation>
Maybe you need to regenerate your service reference or point it at a different endpoint.
EDIT
You may have to customize your reference.cs file (your generated WCF client code) to handle the soap array. I haven't done this myself but there is an SO article about it:-
Why won't .NET deserialize my primitive array from a web service?
I'm not 100% sure if this is the same issue as what you are having. It looks like you need to tell WCF explicitly - for this element, this is how you de-serialize the array. Sorry I can't be of more help.
EDIT #2
There is a mismatch between the wsdl published to you 'soaptest' and the actual implementation. Note the namespaces. Or, you've generated your code of a test wsdl endpoint and pointed it at a prod endpoint.See the namespaces below.Your request's namespaces looked like this:-
http://soaptest.webapi-beta.gratka.pl/dom.html
But the response's namespaces looked like this:-
http://soap.webapi-beta.gratka.pl/dom.html
That ain't gonna work!
Try generating your WCF client off
http://soap.webapi-beta.gratka.pl/dom.html?wsdl
instead of off
http://soaptest.webapi-beta.gratka.pl/dom.html?wsdl
I am receiving the following error when calling a web service method.
Cannot assign object of type System.Xml.XmlNode[] to an object of type System.String.
The web service is a PHP service. I created my proxy class using wsdl.exe from the wsdl document defined here - http://webservice.intelecast.com.au/traffic/PublicSoap/server.php?wsdl
Below is the proxy client method I am calling.
[System.Web.Services.Protocols.SoapRpcMethodAttribute("http://webservice.intelecast.com.au/traffic/PublicSoap/server.php#getAllTraffic", RequestNamespace="http://webservice.intelecast.com.au/traffic/PublicSoap/server.php", ResponseNamespace="http://webservice.intelecast.com.au/traffic/PublicSoap/server.php")]
[return: System.Xml.Serialization.SoapElementAttribute("return")]
public TmcInfo[] getAllTmcTraffic(string[] States, int[] EventCodes) {
object[] results = this.Invoke("getAllTmcTraffic", new object[] { //Error here
States,
EventCodes});
It appear the proxy class is failing to deal with the complex types/arrays defined in the wsdl...I am unsure now how to proceed can't find a solution on the web anywhere.
Below is the SOAP response i am receiving. This all appears valid.
<?xml version="1.0" encoding="iso-8859-1"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://webservice.intelecast.com.au/traffic/PublicSoap/server.php">
<SOAP-ENV:Body>
<ns1:getAllTrafficResponse
xmlns:ns1="http://webservice.intelecast.com.au/traffic/PublicSoap/server.php">
<return xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="tns:TrafficInfo[2]">
<item xsi:type="tns:TrafficInfo">
<id xsi:type="xsd:string">1245632068110</id>
<entryDate xsi:type="xsd:datetime">22/06/2009 10:54:28</entryDate>
<direction xsi:type="xsd:int">0</direction>
<extent xsi:type="xsd:int">1</extent>
<locationCode xsi:type="xsd:int">31593</locationCode>
<countryCode xsi:type="xsd:int">4</countryCode>
<ltn xsi:type="xsd:int">56</ltn>
<diversionAdvice xsi:type="xsd:int">0</diversionAdvice>
<slAdvice xsi:type="xsd:int">0</slAdvice>
<quantifier xsi:type="xsd:int">0</quantifier>
<suppInfoCode xsi:type="xsd:int">0</suppInfoCode>
<addEvent xsi:type="xsd:int">0</addEvent>
<detDivAdvice xsi:type="xsd:int">0</detDivAdvice>
<destinations xsi:type="xsd:int">0</destinations>
<clSourceProblem xsi:type="xsd:int">0</clSourceProblem>
<eventCode xsi:type="xsd:int">802</eventCode>
<timeInfo xsi:type="tns:TimeInfo">
<start xsi:type="xsd:string">21/06/2009 14:00:00</start>
<finish xsi:type="xsd:string">05/11/2009 14:00:00</finish>
<timeZone xsi:type="xsd:string">Australia/Brisbane</timeZone>
</timeInfo>
<location xsi:type="tns:Point">
<lat xsi:type="xsd:float">-27.3112692120521</lat>
<lon xsi:type="xsd:float">153.029100894928</lon>
</location>
<additionalStreetInfo
xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="tns:AdditionalStreetInfo[1]">
<item xsi:type="tns:AdditionalStreetInfo">
<street xsi:type="xsd:string">Bracken Ridge Rd</street>
<type xsi:type="xsd:string">CROSS</type>
</item>
</additionalStreetInfo>
<address xsi:type="tns:Address">
<streetNumber xsi:type="xsd:string"/>
<streetName xsi:type="xsd:string">Bracken Ridge Rd</streetName>
<suburb xsi:type="xsd:string">Bracken Ridge</suburb>
<state xsi:type="xsd:string">QLD</state>
</address>
</item>
<item xsi:type="tns:TrafficInfo">
<id xsi:type="xsd:string">1245632111995</id>
<entryDate xsi:type="xsd:datetime">22/06/2009 10:55:11</entryDate>
<direction xsi:type="xsd:int">1</direction>
<extent xsi:type="xsd:int">1</extent>
<locationCode xsi:type="xsd:int">31592</locationCode>
<countryCode xsi:type="xsd:int">4</countryCode>
<ltn xsi:type="xsd:int">56</ltn>
<diversionAdvice xsi:type="xsd:int">0</diversionAdvice>
<slAdvice xsi:type="xsd:int">0</slAdvice>
<quantifier xsi:type="xsd:int">0</quantifier>
<suppInfoCode xsi:type="xsd:int">0</suppInfoCode>
<addEvent xsi:type="xsd:int">0</addEvent>
<detDivAdvice xsi:type="xsd:int">0</detDivAdvice>
<destinations xsi:type="xsd:int">0</destinations>
<clSourceProblem xsi:type="xsd:int">0</clSourceProblem>
<eventCode xsi:type="xsd:int">802</eventCode>
<timeInfo xsi:type="tns:TimeInfo">
<start xsi:type="xsd:string">21/06/2009 14:00:00</start>
<finish xsi:type="xsd:string">05/11/2009 14:00:00</finish>
<timeZone xsi:type="xsd:string">Australia/Brisbane</timeZone>
</timeInfo>
<location xsi:type="tns:Point">
<lat xsi:type="xsd:float">-27.3125370752656</lat>
<lon xsi:type="xsd:float">153.042898178101</lon>
</location>
<additionalStreetInfo
xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="tns:AdditionalStreetInfo[1]">
<item xsi:type="tns:AdditionalStreetInfo">
<street xsi:type="xsd:string">Bracken Ridge Rd</street>
<type xsi:type="xsd:string">CROSS</type>
</item>
</additionalStreetInfo>
<address xsi:type="tns:Address">
<streetNumber xsi:type="xsd:string"/>
<streetName xsi:type="xsd:string">Bracken Ridge Rd</streetName>
<suburb xsi:type="xsd:string">Bracken Ridge</suburb>
<state xsi:type="xsd:string">QLD</state>
</address>
</item>
</return>
</ns1:getAllTrafficResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Is it a bug in wsdl.exe? I have a few unpleasant encounters with wsdl.exe. Here are the problems outlined in my post:
The first issue it fails to handle
sequence with complex element. You
would think that in today's webservice
environment, a sequence of complex
elements is a norm. But apparently
Microsoft doesn't think so, and this
results in inability of wsdl.exe to
handle a sequence of complex elements.
What if you insist on using wsdl.exe
to generate proxy class for element
with a sequence of complex types? You
will get a cryptic exception: unable
to import binding * from namespace *
- unable to import operation *
- the datatype * is missing The second bug wsdl has is that it is not
permissible to have two web methods
that have the same return signature.
Yes, if one method returns a type of
ComplexType, the other methods must
have a different return type. Failing
to do so will result in an
System.InvalidOperationException: The
XML element * from namespace *
references a references a method and a
type exception.
Note that in both cases the messages
are cryptic. You won't actually know
what's going on behind the hood. And
this is the most frustrating of all.
You don't know whether you fail
because the tool is lousy, or because
you are not doing things right.
Maybe you can refer to this post for an alternative of wsdl.exe.
It's worth noting that rpc/encoded SOAP implementation have problems on complex types. One way around this problem is to convert the WSDL to Document/Literal format.