D11 Pipeline: VIEW Event & Main Content Renderers

Phase ③

VIEW Event & Main Content Renderers

When a controller returns a render array, the VIEW event is fired and MainContentViewSubscriber negotiates the response format and delegates to the appropriate renderer.

 
Kernel Event
KernelEvents::VIEW dispatched by HttpKernel
Symfony's HttpKernel fires this event whenever the controller result is
not a Response object. The event payload carries the controller result
(the render array) and the current Request.
 
VIEW Event Subscriber
MainContentViewSubscriber::onViewRenderArray()
The highest-priority subscriber for the VIEW event in Drupal core.
Guards that the controller result is actually a render array, then negotiates format.
1
Verify controller result is a render array
If not an array → subscriber does nothing; Symfony may throw a LogicException.
2
Negotiate request format
Reads $request->getRequestFormat() (set earlier by NegotiationMiddleware from Accept header / _format route param / ?_format= query string).
3
Look up renderer service for that format
Consults the map of main_content_renderer-tagged services, keyed by MIME type / format string.
 
Format supported?
 
 
✗ No matching renderer
406 Not Acceptable
A JSON response is generated listing the supported formats in machine-readable form, per RFC 2616 §10.4.7. Execution ends here.
✓ Renderer found
MainContentRendererInterface::renderResponse()
The matched renderer service is initialized and its renderResponse($main_content, $request, $route_match) method is called. It must return a Response.
 
Built-in MainContent Renderer implementations (Drupal 11 core)
Which renderer is selected?
Determined by request format. Each is a tagged service.
HtmlRenderer
format: html · MIME: text/html
The default path for normal page requests. Decorates content with blocks, invokes page hooks, renders Twig. → Phase ④

→ Detail in Phase ④

AjaxRenderer
format: drupal_ajax · MIME: application/vnd.drupal-ajax
Returns an AJAX command array (JSON). Used by Drupal's built-in AJAX framework ($.ajax callbacks).
DialogRenderer
format: drupal_dialog · MIME: application/vnd.drupal-dialog
Opens content in a jQuery UI dialog. Returns JSON with dialog options and rendered HTML.
ModalRenderer
format: drupal_modal · MIME: application/vnd.drupal-modal
Variant of DialogRenderer with modal: true. Locks background interaction.
Extending — custom renderers

Any module can register its own format renderer by implementing MainContentRendererInterface and tagging the service with main_content_renderer and a format attribute. The format is then available via ?_format=myformat or the _format route parameter.

 
Special case — BareHtmlPageRenderer

For install, update, maintenance mode, and error pages, the full pipeline above is bypassed. BareHtmlPageRenderer is used instead — a simplified renderer with no block decoration, no BigPipe, and minimal asset libraries. It renders #type html directly via the Renderer service.

 
→ Phase ④ HtmlRenderer (HTML path) or Response returned

Next: Phase ④ HTML Renderer →