Soap web service and android client using ksoap protocal mismatch - c#

I have and android client, that uses ksoap to communicate with a wsdl web service written in c# asp.net. I have a problem with matching the argument types between the web service and the client.
The web server expects to this kind of request (auto generated):
<?xml version="1.0" encoding="utf-8"?>
<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/">
<soap:Body>
<GetDetails xmlns="http://host.org/">
<event_id>int</event_id>
</GetDetails>
</soap:Body>
</soap:Envelope>
the client sends requests using ksoap, and they look like this:
<v:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/">
<v:Header />
<v:Body>
<n0:GetDetails id="o0" c:root="1" xmlns:n0="http://tempuri.org">
<event_id i:type="d:int">1</event_id>
</n0:GetDetails>
</v:Body>
</v:Envelope>
For some reason the WS parses the following' client's request as 0 (I guess because of the additional type attributes - i:type="d:int") when the request is assembled manually to look like the first option, it works correctly.
How can i make the web service read the ksoap format correctly or how can i change it's expected format to look like ksoap request. (the web service soap protocol is auto generated).

Well the solution has 2 parts:
1. regarding removing the attribute types, I found the answer here:
using addMapping without the "i:type=" attribute in ksoap2 for android
I neede to set:
envelope.implicitTypes = true;
The name space has to end with a backspace, and i missed it.

Related

Are namespaces taken into account when contacting a soap web service?

I have some existing code which uses a third party SOAP client to retrieve data from another third party web service. As we switched to a new data provider, we also switched to their new endpoint. We found out that our current requests are all failing and the error we get in return is "Policy Falsified".
I have used SOAP UI to test the new web service and I can successfully obtain data this way. That is why I compared the two soap messages and found out that the problem is likely with the URI used for the soap namespace.
Code generated soap message
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Request>
//...
</Request>
</s:Body>
</s:Envelope>
Working message with SOAP UI
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Request>
//...
</Request>
</soap:Body>
</soap:Envelope>
The only differences in these messages are the namespace prefixes and the soap namespace (the data inside the request tag are identical). I would like to know if this web service is rejecting my soap message purely by the soap namespace that it's using, or that something else might play a problem?
Obviously I am likely going to need to make my own implementation to generate the soap messages myself, but I'd still like to know if the webservice is set to only accept messages with that specific soap namespace or that it's some other kind of issue?

WCF client exception: Unrecognized message version

I hit this error today when deploying a WCF client to QA:
System.ServiceModel.CommunicationException: Unrecognized message version.
In Fiddler I noticed that the WCF client sends its request wrapped in a SOAP Envelope (as expected) but that the response from the remote web service is not wrapped in a SOAP Envelope. That is, our local debug web service sends a response like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Response xmlns="urn:example">
<Success>true</Success>
...
</Response>
</s:Body>
</s:Envelope>
But the remote web service is just sending this:
<?xml version="1.0" encoding="utf-8"?>
<ns0:Response xmlns:ns0="urn:example">
<ns0:Success>true</ns0:Success>
...
</ns0:Response>
As far as I can tell the WCF client is throwing the exception because there's no SOAP Envelope. So my questions are:
Is my assumption correct or should be I looking elsewhere?
Is there some way to configure the WCF client's bindings to remove the SOAP Envelope expectation?
Should I just tell the remote service implementor to fix their service (which they wrote just for us from a supplied WSDL)?
The WCF client is using basicHttpBindings (and HTTP Basic Authentication over SSL/TLS). I'd considered using IClientMessageInspector.AfterReceiveReply() to rewrite the response but the exception gets thrown before that method is invoked, i.e.: We already have an implementation of it for request/response logging and it's not hitting a breakpoint in there.
More info:
After communicating with the service developer it sounds like they completely ignored the .wsdl and (svcutil generated) IService.cs files we gave them and wrote a POX (Plain-Old XML) service from scratch.
I'm not confident that we can convince them to do it properly, so now I'm looking for tips to convert a properly behaving WCF SOAP client into a POX client.
This may be caused by that your service uses Soap1.2 while you are using a different version to call it.
Please try "Add Service Reference" - "Advanced..." - "Add Web Reference..." as a compatibility approach.
I had this issue as well. I know this is an older post, but in my case I modified the app.config file in my C# .NET app that calls this web service. I think it was adding
<security mode="Transport" />
to the basicHttpBinding element that solved it. I also extended the timeouts and maxBufferPoolSize.
Microsoft has documentation that describes this, in case this helps someone else.

Add Web Service Reference fails

I'm trying to connect a SAP soap provider with a C# program...
#Edit: SAP on it's non-public webservice provider, prompts for user and password (before anything)
Using the info here:
I came to the webservice I have to attach to, and when user/password prompted, I've placed it. However I think I've written the password wrong (See EDIT II down below), because the soap response is this one:
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>No binding data for configuration key: "005056AA63891ED480C5CC2F714805E3"</faultstring>
- <detail xmlns:slibfault="http://xml.sap.com/2005/11/esi/slib/fault/">
<slibfault:timestamp>Tue, 15 Jul 2014 16:01:21 GMT</slibfault:timestamp>
- <slibfault:exception>
<slibfault:text>No binding data for configuration key: "005056AA63891ED480C5CC2F714805E3"</slibfault:text>
<slibfault:position program="CL_SRT_WSP_WSDL_HANDLER=======CP" include="CL_SRT_WSP_WSDL_HANDLER=======CM00K" line="82" />
</slibfault:exception>
</detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Now, User and Password aren't prompted, as if a "Remind My Password" checkbox were checked.
Is there any way to refresh the "Visual Studio WebService cache" or something?
#EDIT II: I've tried twice now (by adding it to another project with the same results) and it's not problem that the passwd has been miswritten, the pass is correct, but the reference builder keeps showing this.
WebServices Found at this URL:
There was an error downloading 'http://fooserver:8000/sap/bc/srt/wsdl/srvc_005056AA63891ED480C5CC2F714805E3/wsdl11/allinone/ws_policy/document?sap-client=400/_vti_bin/ListData.svc/$metadata'.
The request failed with the error message:
--
<soap:Envelope xmlns:soap="http://s
Any Ideas?
When this response is the one you receive from SAP, it means the service exposed has been deprecated.
I cannot explain what is happening from the SAP side, (since I'm a C# dev), but What I do can tell you is that the SAP side is intentionally (manual abap developer handling) not expecting further communications from clients.
So... ask your ABAPer on your SAP side, he may have done something with the service you where trying to connect to, since it's no longer available.
You can also verify that by going to the wsdl page "manually" by placing it in the browser. You'll see the same XML response.
#Icing-on-the-cake Edit: If you encounter the issue that credentials is somewhat stored/cached by .Net, simply
go to the Solution Panel,
left click on the project on which you tried to add the reference
and select unload project.
Afterwards repeat that but to Load that same project.
That will "refresh" the credentials "stored".

Using SOAP 1.1 instead of 1.2 [duplicate]

I am connecting to a third-party end point via WCF and I have one problem. The schema for the SOAP envelope that is generated by WCF isn't compatible with the end point.
Currently WCF is generating this:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
But it needs to be this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="http://www.w3.org/2005/08/addressing">
I've tested this in soapUI to confirm this is the problem, but how can I control this in WCF? I used the Add Service Reference option in Visual Studio to generate the service.
Any ideas?
Thanks in advance.
Andy
Most likely, you have an issue with the SOAP version. What binding are you using??
basicHttpBinding defaults to SOAP 1.1, while wsHttpBinding defaults to SOAP 1.2
This is SOAP 1.1 (default in basicHttpBinding):
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
while this is SOAP 1.2 (default in wsHttpBinding):
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
Possible solutions:
1) either you can just switch bindings and that's all there is - you need to make sure to check for security settings and so on (which differ between basic and wsHttpBinding)
or
2) you need to create your own custom binding and explicitly specify the SOAP version you need

Delphi SOAP Envelope and WCF

I am working on a system that provides a soap interface. One of the systems that are going to use the interface is coded in Delphi 7. The web service is developed with WCF, basic http binding, SOAP 1.1.
If I use SOAP UI (JAVA), the service works properly. But Delphi seems to do special things here ;)
This is how the message looks like in SOAP UI:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://services.xxx.de/xxx">
<soapenv:Header/>
<soapenv:Body>
<ser:GetCustomer>
<!--Optional:-->
<ser:GetCustomerRequest> <!-- this is a data contract -->
<ser:Id>?</ser:Id>
</ser:GetCustomerRequest>
</ser:GetCustomer>
</soapenv:Body>
</soapenv:Envelope>
I am not a delphi developer , but I developed a simple test client to see what's going wrong. This what Delphi sends as a SOAP envelope.
<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/">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:NS2="http://services.xxx.de/xxx">
<NS1:GetCustomer xmlns:NS1="http://services.xxx.de/xxx">
<GetCustomerRequest href="#1"/>
</NS1:GetCustomer>
<NS2:GetCustomerRequest id="1" xsi:type="NS2:GetCustomerRequest">
<Id xsi:type="xsd:int">253</Id>
</NS2:GetCustomerRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
WCF throws an error that is in German language... ;)
Es wurde das Endelement "Body" aus Namespace "http://schemas.xmlsoap.org/soap/envelope/" erwartet. Gefunden wurde "Element "NS2:GetCustomerRequest" aus Namespace "http://services.xxx.de/xxx"". Zeile 1, Position 599.
Means something like
The Body was expected. But instead the Element "NS2:GetCustomerReques" was found.
Now my questions is: Can I somehow change the way Delphi creates the envelope? Or are the ways to make WCF work with such message formats? Any help is greatly appreciated!
Contrary to what some people here seem to be implying, Delphi is not sending invalid SOAP, it is simply sending RPC/Encoded SOAP. It's very easy to recognize from all the xsi:type attributes. RPC/Encoded is not WS-I compliant but it is still valid SOAP.
WCF, by default, uses the Document/Literal/Wrapped SOAP format, which Delphi 7 can't handle at all on the server side and you have to make some adjustments on the client side.
The simplest solution is to simply tell Delphi to use the Document/Literal style. You do that by turning on soLiteralParams in the THttpRio.Converter.Options. This tells Delphi not to "unwind" the parameters as you are seeing. The "Document" aspect is something that the Delphi WSDL importer can usually figure out so you shouldn't need to worry about that.
The other solution is to tell the WCF service to use RPC/Encoded style, which you can do by adding the following attributes to the service:
[ServiceContract]
[XmlSerializerFormat(Style = OperationFormatStyle.Rpc,
Use = OperationFormatUse.Encoded)]
public interface IMyService
{
// etc.
}
The second is not recommended because, as I mentioned earlier, RPC/Encoded is not WS-I compliant, but nevertheless most SOAP toolkits do recognize it, so I list it here as a possibility.
I just did one of these, and I ended up with a series of stringreplace calls to alter my XML output to strip the in-line namespaces out and make it look like SoapUI's format. Yes it takes a lot of manual hacking to do that.
ex:
After you create the RIO, call your own BeforeExecute proc:
...
EEUPSERTRIO.OnBeforeExecute := self.RIO_BeforeExecute;
...
procedure TMyWrapper.RIO_BeforeExecute(const MethodName: string; var SOAPRequest: WideString);
{
Since Delphi isn't very good at SOAP, we need to fix the request so that the namespaces are correct.
Basically, you take what Delphi gives you and try it in SoapUI.
If yours doesn't work and SoapUI's version does, make yours look like theirs.
}
...
Now strip out the in-line Namespaces:
SOAPRequest := StringReplace(SOAPRequest,' xmlns:NS1="http://services.xxx.de/xxx"','',[rfReplaceAll,rfIgnoreCase]);
...
Lots of these.
Then you'll replace the soap header with one that contains the namespaces that you want.
SOAPRequest := StringReplace(SOAPRequest,'xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"','xmlns:ns1="http://services.xyzcorp.com/xyz/EnterpriseEmployeeService_1_0" '+'xmlns:ns1="http://schemas.xyzcorp.com/TLOIntegration_HRO_Preview/TLOIntegration_1_0" ',[]);
Then you can re-inject good ones:
ReplaceTag(SOAPRequest,'<metaData>','ns1:');
ReplaceTag(SOAPRequest,'<trackingId>','ns1:');
ReplaceTag(SOAPRequest,'<srcSystem>','ns1:');
Lastly, you can easily capture your Delphi output by re-consuming the WSDL with SoapUI and having it host a mockservice. Then point your app to it as the endpoint, and it'll capture the ouput.
Or, you can use Fiddler as a proxy, to capture requests.
Delphi and Java frameworks use different name space. One way to make if compatible is to intercept the raw xml and change all the "NS2" to whatever the deserializer expects
Cheers

Categories

Resources