14

Guys, I'm stuck, banging my head off the desk for the past few hours.

I am trying to consume a service, and I have 8 other functions that I call that are almost IDENTICAL in nature to this one, but this one, results in a 'SOAP-ERROR: Encoding: Violation of encoding rules' error.

Heres the function call (wsdl omitted for security):

    function CanLoadProduct($data){

    $client = new SoapClient('wsdl-url');

    $params = array('username'   => $this->username,
                    'password'  => $this->password,
                    'prod'      => $data['productid'],
                    'mdn'       => $data['mdn']);

    try {
        $reply = $client->__soapCall("CanLoadProduct", $params);
    } catch (Exception $e) {
        echo 'Error: ',  $e->getMessage(), "\n";
        print_r($params);
        die();
    }

    if( $reply['result'] == 1 ){
        return TRUE;        // 1 = true
    } else {
        return FALSE;
    }

}

Ok so this function, connects to a webservice, the required elements are: username, password, prod, mdn, all 4 of which I supply as part of the $params array. Username/Pass are defined earlier, and do work fine, as the other 8 functions consume the web service without any problems.

The $data[] array (that I pass to the function), contains: $data['productid'] $data['mdn'] nothing else is used.

I am getting

SOAP-ERROR: Encoding: Violation of encoding rules

for some unexplained reason, and Googling this error gets me nowhere. Anyone else run into this? Running PHP 5.2.9-2. The strange thing is this is identical to this function which works 100%:

    function GetPIN($productid){

    $client = new SoapClient('wsdl-url');

    $params = array('username'  => $this->username,
                    'password'  => $this->password,
                    'prod'      => $productid);

    try {
        $reply = $client->__soapCall("GetPIN", $params);
    } catch (Exception $e) {
        echo 'Error: ',  $e->getMessage(), "\n";
        die();
    }
        return $reply;
}

Here is the WSDL (should have posted this first):

<?xml version="1.0" encoding="ISO-8859-1"?>
<definitions 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/" 
    xmlns:tns="ready:test" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="ready:test">
<types>
<xsd:schema targetNamespace="ready:test"
>
 <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
 <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
</xsd:schema>
</types>
<message name="CanLoadProductRequest">
  <part name="username" type="xsd:string" />
  <part name="password" type="xsd:string" />
  <part name="prod" type="xsd:string" />    
  <part name="mdn" type="xsd:string" />
  <part name="esn" type="xsd:string" /></message>
<message name="CanLoadProductResponse">
  <part name="result" type="xsd:int" /></message>
<portType name="CanLoadProductPortType">
  <operation name="CanLoadProduct">
    <input message="tns:CanLoadProductRequest"/>
    <output message="tns:CanLoadProductResponse"/>
  </operation>
</portType>

<binding name="CanLoadProductBinding" type="tns:CanLoadProductPortType">
  <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
  <operation name="CanLoadProduct">
    <soap:operation soapAction="{url-removed}" style="rpc"/>
    <input>
        <soap:body use="encoded" namespace="" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    </input>
    <output>
        <soap:body use="encoded" namespace="" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    </output>
  </operation>
</binding>
<service name="CanLoadProduct">
  <port name="CanLoadProductPort" binding="tns:CanLoadProductBinding">

    <soap:address location="{url-removed}"/>
  </port>
</service>
</definitions>
John Saunders
  • 160,644
  • 26
  • 247
  • 397
Jakub
  • 20,418
  • 8
  • 65
  • 92
  • 2
    If this were a .NET client, I'd try hard-coding "prod" and "mdn" to be known-good values and see what happens. If it works, I'd' remove the hard-codes one at a time to see which one is the problem. I'd then look at the failing value to see if there's anything special about it. – John Saunders Aug 21 '09 at 00:20
  • That was my first thought as well. – Rob Drimmie Aug 21 '09 at 02:49
  • I tried hardcoding it, but I get the same result, its VERY strange. I am not aware of any other method of trouble shooting this. – Jakub Aug 21 '09 at 03:08
  • 1
    Interesting. I think the next thing I'd want to do is look at the WSDL, and the next thing after that would be to try to create a similar client using a different language, like Java or C#. In fact, with all due respect to "scripty" languages, I'd make sure the other language was one with more tool support, etc. I'd only try to implement the one call. It would be interesting to see if it works. – John Saunders Aug 21 '09 at 04:19
  • I have included the WSDL, sorry should have done this sooner. – Jakub Aug 21 '09 at 12:23
  • Jakub, I've done a little test using you WSDL and it appears that SoapClient does not complain about it when issuing the request. It successfully sends the payload. I've logged it. http://dpaste.com/83543/ – Ionuț G. Stan Aug 21 '09 at 12:48
  • It seems like the error can also be caused by the web service erroneously returning a value that does not match the wsdl type specification, causing the client to throw an error. Updated answer below to include that. – Henrik Opel Aug 24 '09 at 10:20

13 Answers13

18

It looks like you have a type mismatch somewhere, either while assembling your request (one of the parameters is not of type string), or the server returns something other than an int (violating the WSDL response definition and thus causing the client to consider the response invalid, as it expects something else).

  • To test the first case, ensure casting all parameters to string first
  • To test the second case, create your SoapClient with the trace option set to true in order to gain access to the actual XML answer from the server via $client->__getLastResponse() afterwards (You can use this for request debugging also via __getLastRequest()).

Some additional observations/questions:

  • According to the posted WSDL, the 'CanLoadProductRequest' has a fifth param 'esn', which you do not supply in your function call.
  • Any reason why you use $client->__soapCall("CanLoadProduct", $params) instead of $client->CanLoadProduct($username, $password, etc.)? (The first version is a lower level variation which is intended to be used for non_WSDL scenarios. The second version might give you a more detailed error/exception)
  • Can you test the SOAP Call to CanLoadProductRequest by some other means? The error could be on the server side, trying to return a result type that does not fit the WSDL definition.
Henrik Opel
  • 19,341
  • 1
  • 48
  • 64
  • The 'esn' is optional, and this pattern of data user/pass/prod/mdn/esn is standard for most of the other 8 calls that I use, none seem to fail except for this one. I have tried $client->CanLoadProduct($params), but it results in: Array to string conversion Notice from PHP – Jakub Aug 21 '09 at 14:54
  • Oups - sorry, if you use the $client->CanLoadProduct() notation, you do not pass an array of parameters, but the single parameters as you would with a standard function call (e.g. $client->CanLoadProduct($username, $password, etc.)) ) – Henrik Opel Aug 21 '09 at 15:11
  • 1
    Another thing to try would be explicitly casting the parameters to string before the call (e.g. the productid might be passed as an int here) – Henrik Opel Aug 21 '09 at 15:23
  • Edited Answer according to new assumptions taken from the comments. – Henrik Opel Aug 21 '09 at 16:37
  • I have marked this as answer, because it helped me check off all possible issues. I concluded the WSDL was causing the error as it is such a simple SOAP call, and I ended up not using it as it was a 'check' call, and the post check function would return a fail message if it did not go through which worked as a check as well. I brought the issue up with the designer of the API. Thanks for your help everyone! – Jakub Aug 24 '09 at 13:27
9

I had the same problem.

In soapUI preferences I checked the option Preferences → Editor Settings → Validate Responses and I received this information:

line 3027: Invalid decimal value: unexpected char '44'.

This solved my problem. Field contained wrong type value.

ЯegDwight
  • 24,821
  • 10
  • 45
  • 52
Atlos
  • 91
  • 1
  • 1
  • This helped me a ton with debugging my wsdl. – Halfstop May 18 '16 at 18:51
  • Preferences is located under "File", and you can also turn on "Validate requests" to find out if you're submitting the wrong kind of data in your test examples. – MatsLindh Mar 01 '18 at 11:05
5

If you upgrade your PHP version to 7.3 or later, the previous WSDL cache may stop working.

The default install directory is /tmp and disabling cache or deleting the wsdl* cache files should remove the problem. I would recommend clearing the cache, or else your server will pull the WSDL every time (which may not be desirable).

Machavity
  • 30,841
  • 27
  • 92
  • 100
  • change soap.wsdl_cache_enabled=0 solved my problem,thx – Tony Feb 21 '22 at 03:50
  • @Tony, it would be better to remove the cache files from the /tmp directory and keep caching enabled. Thats what I just did after updating to php7.4 – Timo002 Feb 23 '22 at 09:26
3

I had the same problem when trying to pass XML as a parameter to one of my webservices. Wrapping the XML data in <![CDATA[ ... ]]> got rid of the SOAP-ERROR: Encoding: Violation of encoding rules and everything worked fine.

Other details:
1. The parameter was defined as xsd:string as well.
2. WSDL was document/literal.
3. Using built in SOAP class with php 5.2.10.

Shane
  • 31
  • 1
3
<![CDATA[<?xml version="1.0"
encoding="utf-8"?>
<CONTENTXML></CONTENTXML]]></xmlCallString>]]>
Mischa
  • 42,876
  • 8
  • 99
  • 111
sanchoo
  • 31
  • 1
2

I had the same problem and I resolved using this syntax for __soapCall:

...
$params = new SoapParam($data, 'parameters');

$response = $this->__soapCall('methodName', 
    array(new SoapVar($data, XSD_ANYTYPE, 'parameters'))
  );        
...

Instead of

__soapCall('methodName', array($params)
Sergey Glotov
  • 20,200
  • 11
  • 84
  • 98
Cristiana
  • 21
  • 1
2

I was getting this error using the SoapUI tool, until I reformatted the response with real test data and not just '?'. Also with SoapUI, the response may be more than expected and may have to shorten to the expected response by removing several optional response parameters. Hope this helps?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
2

Similar to @bezz, my issue was also caused by the WSDL being cached in a temp directory.

I cleared out the wsdl-* files in /tmp and it worked.

Shane N
  • 1,742
  • 2
  • 17
  • 24
1

I had this issue in PhpStorm when doing unit tests. I disabled the wsdl cache and it worked:

ini_set("soap.wsdl_cache_enabled", "0");
Machavity
  • 30,841
  • 27
  • 92
  • 100
bezz
  • 1,438
  • 18
  • 28
1

There's also a kind of bug in PHP where a wrong type leaves no room for giving a proper SOAPfault back to the client.

http://bugs.php.net/bug.php?id=50547

mdekrijger
  • 11
  • 1
0

I had the same problem, and managed to fix it by correcting the WSDL, which was assuming the server would send an integer for a particular value, but was actually sending a string. Perhaps modifying the WSDL from:

<part name="result" type="xsd:int" /></message>

to

<part name="result" type="xsd:string" /></message>

May solve your issue, here is some information on the particular case I was facing: https://blog.dotnetframework.org/2016/12/06/uncaught-soapfault-exception-sender-soap-error-encoding-violation-of-encoding-rules/

Fiach Reid
  • 6,149
  • 2
  • 30
  • 34
0

I solved the problem (SOAP-ERROR: Encoding: Violation of encoding rules) by changing the PHP version from 7.2 to 7.3

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
0

I got the same problem... but I found why.

  • First, I trying SoapClient with PHP 7.3 or 7.4 or 8.0, it works.
  • Secondly, I trying SoapClient (same code) with PHP 7.2, it does not work.

Solution: when changing PHP version, remove the wsdl cache: rm /tmp/wsdl*

luigifab
  • 384
  • 3
  • 19