Take the 2-minute tour ×

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">
         <ser:GetCustomerRequest> <!-- this is a data contract -->

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: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"/>
    <NS2:GetCustomerRequest id="1" xsi:type="NS2:GetCustomerRequest">
      <Id xsi:type="xsd:int">253</Id>

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!

share|improve this question
The problem is not the NS1 NS2 part. The problem is that Delphi is making structurally incorrect XML. It appears that the web service is expecting GetCustomerRequest to be nested inside GetCustomer, but the Delphi client is not nesting the GetCustomerRequest element. I don't know how to fix it though. Did you generate the Delphi client using the WSDL from the WCF service? –  Erv Walter Mar 18 '10 at 22:17
add comment

3 Answers

up vote 10 down vote accepted

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:

[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.

share|improve this answer
add comment

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.


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:


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.

share|improve this answer
FYI - We were using D2005 with the fixes from D2007. –  Chris Thornton Mar 18 '10 at 22:02
Added to the Delphi Nitpick List... stackoverflow.com/questions/2112729/biggest-delphi-nitpicks/… –  Chris Thornton Mar 18 '10 at 22:11
Thsnks for decision. It's the one, which is really helped –  Andrew Kalashnikov Jun 8 '11 at 9:29
add comment

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


share|improve this answer
-1: for a standards compliant SOAP parser, the name space prefix does not matter at all –  mjn Mar 19 '10 at 11:58
add comment

Your Answer


