ZF2返回格式基于accept头

In Zend Framework 2, I want to return JSON if the HTTP accept header is set to "application/json" and HTML otherwise. I am using the new acceptableViewModelSelector controller plugin just as in the example in the 2.0.4 changelog.

I have the following code:

class IndexController extends AbstractActionController {
    private $acceptCriteria = array(
        'Zend\View\Model\JsonModel' => array('application/json'),
        'Zend\View\Model\FeedModel' => array('application/rss+xml')
    );

    public function jsonAcceptHeaderAction() {
        $view_model = $this->acceptableViewModelSelector($this->acceptCriteria);

        return $view_model;
    }
}

If I set the accept header like this:

curl -H "Accept: application/json" http://mydomain.com/json

Then the controller plugin returns a JsonModel instance as expected. However, it seems to always do this, even when there is no application/json in my accept header. For example, if I visit the page in Chrome, the following accept headers are sent:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

I also get JSON back if I use curl http://mydomain.com/json. The controller plugin has a default view model name, which I expected it to use when it doesn't find a match with my accept criteria. The changelog says the following:

The above would return a standard Zend\View\Model\ViewModel instance if the criteria is not met, and the specified view model types if the specific criteria is met.

I tried to change my accept criteria to the following, which turned out to do what I wanted.

private $acceptCriteria = array(
        'Zend\View\Model\ViewModel' => array('text/html'),
        'Zend\View\Model\JsonModel' => array('application/json'),
        'Zend\View\Model\FeedModel' => array('application/rss+xml')
    );

I am just wondering why it does not use the default view model name when there is no application/json accept header, because ideally I would want to leave out the first entry in my accept criteria array.

Does anyone know why I always get a JsonModel object unless I do the change above?

The default view model works, there is no issue with your code, if you don't have an text/html entry, if you access the url with any browser which is capable of accepting json, the accept criteria will match with the first entry i.e application/json.

To test the default model is working test your url with curl as below without the text/html entry in the acceptableviewmodel array, you will get the default view model output

curl -H "Accept: text/html" http://mydomain.com/json

This would return the default view model, so to work as you expect you need to have an entry text/html, place the entry in the array with your preferred order