Web Service - "Uncaught SoapFault exception: [Client] DTD are not supported by SOAP"

Hiya !

I’ve been using Yii for some time now, and I think that I’m starting getting it, so thanks for all the good work.

Now to my question :

As mentionned in this tutorial about Web Service, I followed the instructions, and ended up with the so famous "[Client] DTD are not supported by SOAP" error. Searching the internet, this error seems to have various reasons, but, for this particular case (the tutorial) the error looks like you can not invoke methods through the WSDL generated, because when it tries to reach "back" to the functions through the WSDL file, the client will end up with something which is NOT XML, as expected.

Indeed, and after some headbanging against my desktop (and yes, that hurts), I just found out why :

In the WSDL generated, if you look at the property :<soap:address>, you’ll find this:


<soap:address location="http://localhost/testapi/index.php?r=stock/quote&ws=1"/> 

So, for some reason, the wsdl generation added the parameter "&ws=1" which messes up the whole thing, since trying to reach this URL will prompt a PHP error (while using the URL without the &ws=1 gets me the wsdl), therefore, each call to the methods via soap will get this error as a response, hence not being able to consume the service.

I think that the problem is definetly there, so if someone could come with a way to prevent the WSDL generation from adding that extra parameter, or to try to modify the file post-generation, I would be grateful.

NB : Methods like getfunctiolist and such do work, it’s when you want to consume the services you made that it gets tricky.

OS : Win XP SP2

WAMP : WAMP SERVER

Soap activated

Things I’ve done :

  • Followed the tutorial step-by-step

  • Disabled the cache for wsdl file

  • Got the error

  • Searched for it

  • Found many possible causes

  • Found the issue

  • Scratched my head in confusion

  • Posted here.

I don’t think the problem is ws=1 since it works in my wsdl.

/Tommy

Well, it’s the only explanation I could find, at least the one that makes the most sense, since it’s obviously a response issue …

Which WAMP/LAMP are you using ?

Any suggestions guys ?

I’m on Ubuntu and OpenSUSE. Just realized I was using Yii 1.0 for the services. Switched to a 1.1 app. Noticed that action name ‘itemsWS’ had to be changed to ‘itemsws’.

From the web browser, http://mysite/myapp/index.php/item/itemws presents the wsdl as expected (url in path format)).

Navigating to http://mysite/myapp/index.php/item/itemws/ws/1 gives this error

used to be a decoded Soap message.




<SOAP-ENV:Envelope>

  <SOAP-ENV:Body>

    <SOAP-ENV:Fault>

      <faultcode>CException</faultcode>

      <faultstring>

        Login required.

      </faultstring>

    </SOAP-ENV:Fault>

  </SOAP-ENV:Body>

</SOAP-ENV:Envelope>



Investigating…

Edit: Ok, so it works with url’s in get format but not path format!?

Edit2: Still possible to call from SoapClient, but … had missed to comment out “‘showScriptName’ => false” but used “index.php” in client url. Client thus reported: “SoapFault exception: [Client] DTD are not supported by SOAP”. Now it works again (under 1.1).

Edit3: Duh, have too many temporary projects, get format, path format, some index.php renamed to idx.php (for testing purposes). Added the .htaccess that was missing. Now path format works without index.php in the url (web service client seems to be confused by partially implemented script hiding).

/Tommy

What’s with Web services adding “ones” here and there ? Strange …

Anyway,

Is it the possible solution ? (Upgrading to 1.1 and setting 'showScriptName’to false ?)

(And 1.1 refers to te Yii version or to the SOAP version ?)

I’m kinda confused by your post …

The ws parameter distinguish the call as a service call (not a wsdl call). See also API reference here. I think the "1" should be interpreted as "non-zero".

I reported the differences I had to fix in my old code experiments. I had implemented the path url format (and in some of the "projects" also script hiding), thus had to change a couple of test clients to get everything working again.

I experienced the "DTD are not supported…" message in a state where CUrlManager was configured for script hiding but the corresponding .htaccess was not in effect. If you use CUrlManager in your config, make sure everything is consistent.




//In my case the soap client didn't like the wsdlUrl

http://site/app/index.php/controller/webservice

//but succeeded with

http://site/app/controller/webservice

//(serviceUrl: http://site/app/controller/webservice/ws/1)



Without url rewriting the formats of course are




http://site/app/index.php?r=controller/webservice

and

http://site/app/index.php?r=controller/webservice&ws=1



Bottom line is: the only difference I’ve found moving to Yii 1.1 is the need for lower case in the web service action name.




public function actions()

{

  return array(

    'itemsws'=>array(    // used to be 'itemsWS'

      'class'=>'CWebServiceAction'

    ),

  );

}



Edit: "ones", Yii 1.1, "get" format, prettifying, API ref

/Tommy

[size="5"]AND I GOT IT ![/size]

The bad way. The veeeery bad way.

Ok, First of all, thanks Tommy for all your help.

Secondly, I would have spotted the thing, if only I had a decent debugger, and I can’t for now, due to technical considerations.

Now to the problem.

It was, indeed, an URL problem.

It wasn’t, indeed, the ws parameter.

But for some reason, the problem was in the CWebServiceAction class, precisely in the $wsdlUrl variable, which was, for some reason again, too short.

Indeed, I’m working on localhost for now, and the $wsdlUrl parameter semms to be lacking all the subdirectories of the project, where the controller containing the wsdl is !

So, initially, $wsdlUrl had the value : ‘hhtp://localhost?r=stock/quote’. And this sure don’t work, since nothing’s there.

So, and sorry qiang, I ended up fixing the thing in a very baaad way, by actually playing with CWebServiceAction code.

And thus by replacing line #90 with the following :


$wsdlUrl=$hostInfo.Yii::app()->request->baseUrl.'/'.$controller->createUrl($this->getId());

In fact, I added this, between hostinfo and controller variable :


Yii::app()->request->baseUrl.'/'.

It worked like a charm.

But you guys know that I cannot let this happen, so I’m asking you how could $wsdlUrl be so ‘short’, and how to fix that so CWebServiceAction would go back to its initial form.

Here is how my directories are organized :

www

|–client.php : where I consume the service

|–yii

±–Framework

±-----------Yii’s files …

|—testapi : My application, created with the console

±---------assets

±---------css

±---------protected

|±-----------------controllers

-------------------------------SiteController.php

-------------------------------StockController.php : where the wsdl is generated

-----------All other directories

----All other directories

I’m using Yii 1.0.4, for the matter …