10

I'm trying to set the content-type header for a JSON response accessed with an AJAX GET request. I've followed tutorials on blogs and the bakery but I always receive 'text/html' back from CakePHP. How do I set the content-type header correctly?

Here's my code at the moment:

public function admin_controller_actions_ajax()
{
    Configure::write('debug', 0);
    if ($this->RequestHandler->isGet()) {
        $this->autoRender = FALSE;

        $aco_id = $this->params['url']['aco_id'];
        $aro_id = $this->params['url']['aro_id'];

        assert('$aco_id != NULL && $aro_id != NULL &&
                is_numeric($aco_id) && is_numeric($aro_id)');

        $actions = $this->Resource->getActionsForController($aco_id, $aro_id);

        assert('is_array($actions) && is_array($actions[0])');

        /* I made RequestHandler part of the $components property */
        $this->RequestHandler->setContent('json');
        $this->RequestHandler->respondAs('json'); /* I've tried 'json', 'JSON', 'application/json' but none of them work */

        $this->set('json_content', json_encode(array('response' => $actions[0])));
        $this->layout = NULL;
        $this->render('/json/default');
    }
}


/* json/default.ctp */
<?php echo $json_content; ?>

Any help would be appreciated.

Thanks,

-- Isaac

JProgrammer
  • 2,680
  • 23
  • 36
  • 1
    Do you use Router::parseExtensions() in your routes.php file? If yes, you have to set "debug" to 0 in app/config/core.php to make it respond with the correct content type. – dhofstet Aug 04 '09 at 09:34
  • No, I don't use Router::parseExtensions() but I set debug to 0 in the request anyway. –  Aug 04 '09 at 11:55

5 Answers5

7

I make Ajax calls to retrieve JSON content in all of my projects and I've never done most of what you're doing here. The extent of my controller code looks something like this:

public function do_something_ajaxy() {
  Configure::write ( 'debug', 0 );
  $this->autoRender = false;

  /** Business logic as required */

  echo json_encode ( $whatever_should_be_encoded );
}

I make my Ajax calls via jQuery so I suppose that could make a difference, but it would surprise me. In this case, you're problem appears to be in the handler, not with the caller. I'd recommend removing lines 17-23 and replacing them with a simple echo json_encode ( array('response' => $actions[0]) ) statement.

You're also testing for $this->RequestHandler->isGet(). Try testing $this->RequestHandler->isAjax() instead. I'm not sure whether Ajax calls are recognized as by both their type and their method.

Rob Wilkerson
  • 37,910
  • 41
  • 130
  • 185
  • I tried doing that before - I just had 'return json_encode' (and I tried 'echo json_encode' too). I was told in the IRC channel that that was a bad way of doing it and the 'right way' is to use a view. I disagreed, but I did it anyway to comply. I'll test isAjax, but given that my ajax call is a get request, isGet should work too. I also make my ajax calls with jQuery. –  Aug 04 '09 at 11:43
  • I've just tried your suggestion (I simplified everything to echo json_encode and used isAjax instead of isGet) and I still get 'text/html' returned. –  Aug 04 '09 at 11:46
  • 1
    Sorry, Isaac. I forgot to loop back on this. The content type shouldn't matter as long as the content itself is valid JSON. I avoid views for stuff like this because it's an extra file doing essentially nothing. I have issues with clutter. :-) – Rob Wilkerson Aug 20 '09 at 17:51
  • For me the `Configure::write ( 'debug', 0 );` was the magic sauce. N.B. as per [@Ajtacka's answer](https://stackoverflow.com/a/3148181/327074), `Configure::write ( 'debug', 1 );` works too – icc97 Apr 26 '18 at 09:16
7

After reading this and this, I got the following to return "Content-Type:application/json":

Configure::write('debug', 0);
$this->RequestHandler->respondAs('json');
$this->autoRender = false;            
echo json_encode($data);

With JQuery's $.getJSON method, I'm still getting

Resource interpreted as image but transferred with MIME type text/html.

But at least my data is parsing.

Myer
  • 3,434
  • 1
  • 34
  • 46
  • I've recently used this method in Cake 2.0 (although moved this code to a function in AppController so that any controller can use it without repetition). It seems to work well and allows jQuery (1.7) to auto-detect the content as JSON. – Simon East Dec 20 '11 at 22:32
2

I've also just had this problem, and solved it by using:

$this->RequestHandler->respondAs('text/x-json');

Also make sure that "debug" in your config file is set to less than 2 otherwise the header will not be set.

Ajtacka
  • 21
  • 1
  • You comment about debug < 2 is brilliant. However as far as I know `$this->RequestHandler->respondAs('json');` should be correct - that corresponds to setting a header of `application/json` which is the [most appropriate header for JSON](https://stackoverflow.com/a/477819/327074) – icc97 Apr 26 '18 at 09:10
1

I am not sure (and, to be honest, I've never used CakePHP), but you may want to try to specify a second argument in the setContent method..

replace this:

$this->RequestHandler->setContent('json') 

with this:

$this->RequestHandler->setContent('json', 'text/x-json');

see this file for an example..

Andrea Fiore
  • 1,568
  • 2
  • 12
  • 17
  • I've just tried this (I've tried similar secondary arguments before, but I thought I'd give it another go) and it doesn't work. I still get 'text/html' returned. –  Aug 04 '09 at 11:48
  • Me too. I use that AND try and force the response type with: $this->RequestHandler->respondAs('json'); Neither work for me. – zmonteca Dec 20 '11 at 21:16
0

I've been having the same problem as the original poster, and what worked for me was to follow Rob Wilkerson's advice, but also make sure I was using

jQuery.ajax()

instead of

jQuery.get()

or

jQuery.post()

jQuery.ajax() allows you to set the dataType to 'json' whereas the other two don't seem to allow you to set the datatype at all. When I set the data type in the AJAX request to 'json' it all worked as it should.

mtnorthrop
  • 2,583
  • 1
  • 18
  • 21
  • 2
    You can actually specify a datatype in `.post()` and `.get()`, see the docs (as of Dec 2011). http://api.jquery.com/jQuery.post/ http://api.jquery.com/jQuery.get/ – Simon East Dec 20 '11 at 01:20