Search code examples
phpapisoapsoap-client

How do I solve this SOAP exception 'Unmarshalling Error'


I'm working on a project where I'm using an internally hosted 3rd party applications' SOAP API (BMC FootPrints Service Core). I'm able to make calls to the API with PHP, my credentials are fine, and in one particular API Method, I'm making what looks like a valid call to the API function, but get the following exception / error:

SoapFault exception: [soap:Client] Unmarshalling Error: cvc-complex-type.2.4.b: The content of element 'ns1:runSearch' is not complete. One of '{runSearchRequest}' is expected

what does the "One of '{runSearchRequest}' is expected' part mean exactly? I don't understand what else I need to include with the request I'm making to the API.

The API documentation can be found here and specifically, page 31 refers to the API method I'm trying to use is documented here in this screenshot: image from PDF.

I wont post ALL the code, but just the part where I attempt the API method:

// array that will be used in the method call...
$searchFor = array(
    "_searchId"=>"11",  
);

try { 
    $response = $soapClient->__soapCall("runSearch", $searchFor);
    print_r($response);
} catch (SoapFault $exception) {  
      echo $exception;  
}  

I tested the method call with SOAPUI applcation and I'm able to see the results / response fine.

update: Adding the WSDL xml (snippets)...

I am using a WSDL, but its hosted on our internal / local network and not exposed externally, here's the start of the XML and the runSearch type from that WSDL:

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://externalapi.business.footprints.numarasoftware.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="ExternalApiService" targetNamespace="http://externalapi.business.footprints.numarasoftware.com/">
<wsdl:types>
<schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://xxxxxxxxxxxxxxxxxxxx.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://www.w3.org/2001/XMLSchema">

<import namespace="xxxxxxxxxxxxxxxxxxxxxxxx" schemaLocation="http://xxxxxxxxxxxxxxxxxxxxxxxx:PORT/footprints/servicedesk/externalapisoap/ExternalApiServicePort?xsd=externalapiservices_schema.xsd"/>

</schema>
</wsdl:types>

...

<wsdl:message name="runSearch">
   <wsdl:part element="tns:runSearch" name="parameters">
   </wsdl:part>
</wsdl:message>

Solution

  • The error is indicating that your runSearchReqeust structure (that is, your $searchFor) is missing information. The documentation you provided indicates that the signature of the runSearch() call would look like:

    runSearchResponse runSearch(runSearch $runSearch)
    

    Further, the runSearch datatype would contain one field of type RunSearchRequest.

    So you need a data structure that contains an element 'runSearchRequest' which itself is another data structure that contains _searchId

    Try:

    $searchFor = array(
      'runSearchRequest' => array(
        "_searchId" => "11",
      )
    );
    

    And change your call to:

    $response = $soapClient->runSearch($searchFor);
    

    Or alternatively:

    $response = $soapClient->__soapCall("runSearch", array($searchFor));
    

    This will produce a SOAP XML request that closely matches the one from the doc:

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
                   xmlns:ns1="http://externalapi.business.footprints.numarasoftware.com/">
    <SOAP-ENV:Body>
            <ns1:runSearch>
                <runSearchRequest>
                    <_searchId>11</_searchId>
                </runSearchRequest>
            </ns1:runSearch>
        </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>