3

Im having some problems consuming a wsHttpBinding WCF from PHP. I originally tried to use SOAP1.2 but couldnt get it to specify the WS Action.

I downloaded the nusoap library. I was originally getting an error saying that the webservice wouldnt accept the data due to a type mismatch (text/xml instead of the expected application/soap+xml). I managed to make changes to nusoap.php to send the data as application/soap+xml). Now that doesnt throw an error, i get 400 bad request error from the server.

I can consume the service from WCFTestClient and also from SOAPUI without any messing around, but just cannot get it to fly from PHP. I even copied the entire soap envelope from SOAPUI and set the $soapmsg in nusoap.php to be exactly that and it still fails.

So anyone want to offer some guidance.

EDIT This is the code i was trying in SOAP 1.2

$params  = array("soap_version"=> SOAP_1_2,
                "trace"=>1,
                "exceptions"=>0,
                );

$client = @new SoapClient('https://localhost/wcftest/Service.svc?wsdl',$params);

$retval = $client->GetData(array('value'=>'stuff'));
if (is_soap_fault($retval)) {
    trigger_error("SOAP Fault: (faultcode: {$retval->faultcode}, faultstring: {$retval->faultstring})", E_USER_ERROR);
}

EDIT #2 This is the code that works out of SOAPUI

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/">
   <soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing"><wsa:Action>http://tempuri.org/IService/GetData</wsa:Action></soap:Header>
   <soap:Body>
      <tem:GetData>
         <!--Optional:-->
         <tem:value>stuff</tem:value>
      </tem:GetData>
   </soap:Body>
</soap:Envelope>

After adding the SoapHeaders manually as mentioned by Gords link below i get this as the __last_request when debugging with netbeans and still the same error

    "<?xml version="1.0" encoding="UTF-8"?>
    <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://tempuri.org/">
<env:Header>
<ns1:Action>http://tempuri.org/IService/GetData</ns1:Action>
</env:Header>
<env:Body><ns1:GetData><ns1:value>stuff</ns1:value></ns1:GetData></env:Body></env:Envelope>

any advice??

Thanks! Andy

doptimusprime
  • 9,115
  • 6
  • 52
  • 90
Andrew MacNaughton
  • 783
  • 2
  • 6
  • 21
  • 2
    If you're running on PHP5 have you tried PHP's built-in SOAP support? I used to maintain an ASP.NET-based web service that could be called using PHP5's SOAP implementation, but could not be called from NuSOAP. (IIRC it had something to do with passing arguments to the web service as objects, which was something that NuSOAP apparently could not do.) – Gord Thompson Apr 05 '13 at 19:31
  • Hi Gord. Thanks for the reply. When i was using SOAP_CLIENT (as opposed to Nusoap_client) i would continually get the error 'The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://tempuri.org/IService/GetData. that was one of the reasons i switched to nusoap. – Andrew MacNaughton Apr 05 '13 at 19:32
  • 1
    You mentioned SOAP_1.2, but did you try using WSDL? Again, as I recall (it was a few years ago) that was the only way I found that would let PHP interact with that web service. The few times I tried to dig into it further I got bogged down because the MS docs were all about consuming ASP.NET web services from .NET applications, and most of the PHP references I could find (blogs, etc.) did not seem terribly interested in supporting anything related to MS. :( – Gord Thompson Apr 05 '13 at 19:49
  • Hi Gord. I updated the OP with the the code i was using for 1.2 Totally agree that trying to get interopability between php and MS stuff is just a nightmare! – Andrew MacNaughton Apr 05 '13 at 20:01
  • 1
    I found my old sample code and it looks very similar to yours, so I may not be able to offer a "silver bullet" for this. :( Did you by chance happen upon the Stack Overflow article [here](http://stackoverflow.com/questions/8934365/php-fatal-error-the-soap-action-specified-on-the-message-does-not-match-t)? – Gord Thompson Apr 05 '13 at 20:27
  • Hi Gord. thanks for that, i checked that previously, but it looks like it could be something that may work – Andrew MacNaughton Apr 05 '13 at 21:36

1 Answers1

6

Ok so i got this to work. Thanks to Gord for making me double check stuff that i had overlooked earlier on.

I ended ditching nusoap and just sticking with with SOAP 1.2. Here is my php code

//Declare some paramaters for our soapclient. Need to make sure its set to soap 1.2
$params  = array("soap_version"=> SOAP_1_2,
                "trace"=>1,
                "exceptions"=>0,
                );

//Create the soap client
$client = new SoapClient('https://localhost/wcftest/Service.svc?wsdl',$params);
//add some WSAddressing Headers in. Ensure that you have the Namespace as the address if you are using wsHttpBinding on the endpoint
//This was the step that took me the longest to figure out!
$actionHeader = new SoapHeader('http://www.w3.org/2005/08/addressing','Action','http://tempuri.org/IService/GetData',true);
//Add the headers into the client
$client->__setSoapHeaders($actionHeader);
//Make the call and pass in the variables that we require to go to the server
$retval = $client->__soapCall('GetData',array('value'=>'stuff'));
//Some Error Catching
if (is_soap_fault($retval)) {
    trigger_error("SOAP Fault: (faultcode: {$retval->faultcode}, faultstring: {$retval->faultstring})", E_USER_ERROR);
}

and the working envelope

  <?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://tempuri.org/" xmlns:ns2="http://www.w3.org/2005/08/addressing"> 
    <env:Header> 
        <ns2:Action env:mustUnderstand="true">http://tempuri.org/IService/GetData</ns2:Action>
    </env:Header>
    <env:Body>
        <ns1:GetData/>
    </env:Body>
</env:Envelope>

and the web.config file from the WCF Service

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0"/>
  </system.web>
  <connectionStrings>
    <add name="Timeforce" connectionString="Data Source=apps.ziptrek.com;Initial Catalog=qqest;User ID=qqest; Password=qqest;"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="TransportSecurity">
          <security mode="Transport">
            <transport clientCredentialType="None"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="Service" behaviorConfiguration="Service1">
        <endpoint address="https://localhost/wcftest/Service.svc" binding="wsHttpBinding" bindingConfiguration="TransportSecurity" contract="IService"></endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Service1">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpsGetEnabled="true"/>

          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="httpsService1">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="false"/>


  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>
Andrew MacNaughton
  • 783
  • 2
  • 6
  • 21