views:

1059

answers:

2

I have a RPC encoded PHP webservice that returns a simple soap envelope with a boolean datatype. When doing the trace on the client side, the soap envelope looks like this right before it goes into the WCF proxy:

<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ns1="http://sample.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org
/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:ServiceMessageResponse>
       <outgoingVar1>true</outgoingVar1>
    </ns1:ServiceMessageResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

However, when the returned value comes out the other side of the proxy it's been changed to false. I've tried adding an xsi:type="xsd:boolean" to the outgoingVar1, but that doesn't help. The soap envelope itself is exactly what the client should be expecting, but for some reason it won't consume it correctly. Is this something that has to do with the way the PHP web service is set up or is it in the WCF proxy? The PHP web service is simply set up like this:

ini_set('soap.wsdl_cache_enabled', '0');
ini_set('soap.wsdl_cache_ttl', '0');
$soapServer = new SoapServer('wsdl/sample.wsdl', array('soap_version' => SOAP_1_1));
$soapServer->addFunction('Service');
$soapServer->handle();

and the function ends with a simple 'return true;' line. Nothing complicated here. Any ideas what the problem may be?

The annotated WSDL (removed trivial namespaces and modified the real ones) looks like this:

<wsdl:definitions name="IJLSoapResponse" targetNamespace="http://casey.com"
tns="http://casey.com" xmlns:samp="http://sample.com" ...>
  <wsdl:types>
    <xsd:schema targetNamespace="http://casey.com" ...>
            <xsd:element name="incomingVar1" type="xsd:string" nillable="true"/>
            <xsd:element name="incomingVar2" type="xsd:string" nillable="true"/>
    </xsd:schema>
    <xsd:schema targetNamespace="http://sample.com" ...>
            <xsd:element name="outgoingVar1" type="xsd:boolean" nillable="true"/>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="ServiceInput">
    <wsdl:part name="incomingVar1" element="tns:incomingVar1"/>
    <wsdl:part name="incomingVar2" element="tns:incomingVar2"/>
  </wsdl:message>
  <wsdl:message name="ServiceOutput">
    <wsdl:part name="outgoingVar1" element="samp:outgoingVar1"/>
  </wsdl:message>
  <wsdl:portType name="ServicePortType">
    <wsdl:operation name="ServiceMessage" parameterOrder="incomingVar1 incomingVar2">
            <wsdl:input name="ServiceMessageRequest" message="tns:ServiceInput"/>
            <wsdl:output name="ServiceMessageResponse" message="tns:ServiceOutput"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="ServiceBinding" type="tns:ServicePortType">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/&gt;
    <wsdl:operation name="ServiceMessage">
            <soap:operation soapAction="http://casey.com/soap/Service"/&gt;
            <wsdl:input name="ServiceMessageRequest">
                    <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://casey.com"/&gt;
            </wsdl:input>
            <wsdl:output name="ServiceMessageResponse">
                    <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://sample.com"/&gt;
            </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="ServiceService">
    <wsdl:port name="ServicePort" binding="tns:ServiceBinding">
            <soap:address location="http://casey.com/soap/Service"/&gt;
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

This should be enough to see how things are declared...let me know if you need anything else clarified. Thanks for your help!

A: 

May we see the WSDL of the service? I'm wondering what namespace outgoingVar1 is meant to be in.

RPC encoded services have always been a pain because of ambiguity about which namespace message parts are meant to be in. It won't surprise me to see that this is the problem here.


The following binding seems to work in soapUI. At least, it can generate a mock service, and the response message looks like what you were looking for (outgoingVar1 in sample namespace):

<wsdl:binding name="ServiceBinding" type="tns:ServicePortType">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/&gt;
    <wsdl:operation name="ServiceMessage">
        <soap:operation soapAction="http://casey.com/soap/Service"/&gt;
        <wsdl:input name="ServiceMessageRequest">
            <soap:body parts="incomingVar1 incomingVar2" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://casey.com"/&gt;
        </wsdl:input>
        <wsdl:output name="ServiceMessageResponse">
            <soap:body parts="outgoingVar1" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://sample.com"/&gt;
        </wsdl:output>
    </wsdl:operation>
</wsdl:binding>
John Saunders
outgoingVar1 should be a part of http://sample.com...in the soap envelope shouldn't ns1 (http://sample.com) propagate to the children of ServiceResponse?
No. Namespaces don't propagate like that. It would have taken an xmlns="http://sample.com" in order to do that (make sample.com the default namespace going forward). The ns1 only applies to the element it's used on.
John Saunders
I played around a bit with the WSDL with XMLSpy and with soapUI. soapUI does not like it. It seems to want the input and output names to match between the portType and the binding.
John Saunders
John: Thanks for your help so far and I'll make sure and keep namespaces in from now on. The mismatch on the WSDL was an editing mistake that I fixed above. I added the parts attribute to the soap:body node, but it didn't change the look of the output SOAP envelope at all. It's still prefix-less.
When I generate a mock service in soapUI, I do get the outgoingVar1 as part of the right namespace. However, when I hit the actual service with the same WSDL it comes back with only the ServiceMessageResponse with the prefix. Is there something missing from the declaration of the PHP Service itself?
Sorry, I don't think I'd ever even _seen_ PHP until you posted it above. I can only assume it's interpreting the WSDL differently, which is the problem with RPC services. BTW, you might want to check the service for WS-I compliance. I don't know how to make that work in soapUI.
John Saunders
A: 

The solution ended up dealing with the namespaces. Since they weren't propagating correctly, I needed to add the attribute elementFormDefault="qualified" to the schema. That forces the prefix to be present on every element, which is the only way I could make .NET happy. Thanks for your help on this.