Fosrestbundle: Problem with using manual route definitions and ViewHandler

Created on 9 Dec 2017  路  4Comments  路  Source: FriendsOfSymfony/FOSRestBundle

Hi,
when I define routes manually like described in the documentation and use return $this->view($data),
when ViewResponseListenter::onKernelView gets invoked, the ViewHanlder throws an Exception trying to render the template:

LogicException:
An instance of Symfony\Bundle\FrameworkBundle\Templating\EngineInterface must be injected in FOS\RestBundle\View\ViewHandler to render templates.

  at vendor\friendsofsymfony\rest-bundle\View\ViewHandler.php:346
  at FOS\RestBundle\View\ViewHandler->renderTemplate(object(View), 'html')
     (vendor\friendsofsymfony\rest-bundle\View\ViewHandler.php:442)
  at FOS\RestBundle\View\ViewHandler->initResponse(object(View), 'html')
     (vendor\friendsofsymfony\rest-bundle\View\ViewHandler.php:416)
  at FOS\RestBundle\View\ViewHandler->createResponse(object(View), object(Request), 'html')
     (vendor\friendsofsymfony\rest-bundle\View\ViewHandler.php:300)
  at FOS\RestBundle\View\ViewHandler->handle(object(View), object(Request))
     (vendor\friendsofsymfony\rest-bundle\EventListener\ViewResponseListener.php:132)
  at FOS\RestBundle\EventListener\ViewResponseListener->onKernelView(object(GetResponseForControllerResultEvent), 'kernel.view', object(TraceableEventDispatcher))
  at call_user_func(array(object(ViewResponseListener), 'onKernelView'), object(GetResponseForControllerResultEvent), 'kernel.view', object(TraceableEventDispatcher))
     (vendor\symfony\event-dispatcher\Debug\WrappedListener.php:104)
  at Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(object(GetResponseForControllerResultEvent), 'kernel.view', object(EventDispatcher))
     (vendor\symfony\event-dispatcher\EventDispatcher.php:212)
  at Symfony\Component\EventDispatcher\EventDispatcher->doDispatch(array(object(WrappedListener), object(WrappedListener)), 'kernel.view', object(GetResponseForControllerResultEvent))
     (vendor\symfony\event-dispatcher\EventDispatcher.php:44)
  at Symfony\Component\EventDispatcher\EventDispatcher->dispatch('kernel.view', object(GetResponseForControllerResultEvent))
     (vendor\symfony\event-dispatcher\Debug\TraceableEventDispatcher.php:139)
  at Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch('kernel.view', object(GetResponseForControllerResultEvent))
     (vendor\symfony\http-kernel\HttpKernel.php:156)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
     (vendor\symfony\http-kernel\HttpKernel.php:66)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor\symfony\http-kernel\Kernel.php:190)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (public\index.php:34)

PHP Version: 7.2
Symfony version: 4.0.1
RestBundle version: 2.3

fos_rest.yaml:

fos_rest:
    body_listener: true
    param_fetcher_listener: true
    allowed_methods_listener: true
    view:
        view_response_listener: 'force'
        formats:
            xml: true
            json: true
    routing_loader:
        default_format: json

routes.yaml:

clients:
    type: rest
    resource: App\Controller\ClientController

AppControllerClientController.php

use FOS\RestBundle\Controller\Annotations as Rest;
...
class ClientController extends FOSRestController
{
    /**
     * @Rest\Get("/clients/{id}")
     */
    public function getClientAction($id)
    {
        $data = $this->getDoctrine()->getRepository(Client::class)->find($id);
        return $this->view($data, Response::HTTP_OK);
    }
}

Disabling the view annotations of the FrameworkExtraBundle via

sensio_framework_extra:
    view:    { annotations: false }

creates a RuntimeException with the message
You must enable the SensioFrameworkExtraBundle view annotations to use the ViewResponseListener.

Any ideas?
Thanks

Most helpful comment

They way I solved it was by Adding a line to config/packages/framework.yaml

framework:
    templating: { engines: ['twig'] }

Reference

All 4 comments

When I add entries to the routes.yaml to overwrite the routes that the framework extra bundle creates, I am able to use the FOSRestBundle ViewHandler without any issues:

app_client_getclients:
    path: /clients.{_format}

I don't know the symfony internals well enough but I am guessing that overwriting the route names somehow allows the FOSRestBundle to handle the route matching instead of the framework extra bundle. Can anyone explain why this works?

Well, I just did some work on this. I was able to resolve the issue but I don't know if its a solution or a workaround, but maybe this helps others.

I do get the same error on a fresh clone of my project, but not on the development repository I worked on the last weeks. Both of them use the exact same versions of my software and ALL vendors.

The bundle wants to serialize to html, because there is no format set on the View object or the Request object. The $request->attributes->get('_format') returns null.
I was not able to figure out where

I do not use the format stuff of this bundle, my config:

fos_rest:
    routing_loader:
        default_format: json
        include_format: false
    body_listener: true
   # format_listener:
   #       rules:
   #           - { path: '^/', priorities: ['json'], fallback_format: json, prefer_extension: false }
    param_fetcher_listener: true
    access_denied_listener:
        json: true
    view:
        view_response_listener: 'force'
        formats:
            json: true

After uncommenting the commented lines from the config, it know works again. (I guess that might be the reason why I had them in there initially). This actually surprises me a little because when setting default_format: json and include_format: false I expected it should work without the format listener. Is it this way on purpose?

@juliusstoerrle That format listener rule seems to solve the problem. Still curious why the automatically generated routes contain a default value for 'media_type' and the manual routes don't. Thanks for your time!

They way I solved it was by Adding a line to config/packages/framework.yaml

framework:
    templating: { engines: ['twig'] }

Reference

Was this page helpful?
0 / 5 - 0 ratings