diff --git a/core/core.services.yml b/core/core.services.yml
index 9291712..a846459 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -698,10 +698,10 @@ services:
       - { name: render.main_content_renderer, format: drupal_modal }
   controller.form:
     class: Drupal\Core\Controller\HtmlFormController
-    arguments: ['@controller_resolver', '@form_builder', '@class_resolver']
+    arguments: ['@controller_resolver', '@form_builder', '@current_route_match', '@class_resolver']
   controller.entity_form:
     class: Drupal\Core\Entity\HtmlEntityFormController
-    arguments: ['@controller_resolver', '@form_builder', '@entity.manager']
+    arguments: ['@controller_resolver', '@form_builder', '@current_route_match', '@entity.manager']
   router_listener:
     class: Symfony\Component\HttpKernel\EventListener\RouterListener
     tags:
diff --git a/core/lib/Drupal/Core/Controller/FormController.php b/core/lib/Drupal/Core/Controller/FormController.php
index dc191c0..3c025f4 100644
--- a/core/lib/Drupal/Core/Controller/FormController.php
+++ b/core/lib/Drupal/Core/Controller/FormController.php
@@ -10,6 +10,7 @@
 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 use Drupal\Core\Form\FormBuilderInterface;
 use Drupal\Core\Form\FormState;
+use Drupal\Core\Routing\RouteMatchInterface;
 use Symfony\Component\HttpFoundation\Request;
 
 /**
@@ -35,16 +36,26 @@
   protected $formBuilder;
 
   /**
+   * The current route match.
+   *
+   * @var \Drupal\Core\Routing\RouteMatchInterface
+   */
+  protected $routeMatch;
+
+  /**
    * Constructs a new \Drupal\Core\Controller\FormController object.
    *
    * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
    *   The controller resolver.
    * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
    *   The form builder.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
    */
-  public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder) {
+  public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder, RouteMatchInterface $route_match) {
     $this->controllerResolver = $controller_resolver;
     $this->formBuilder = $form_builder;
+    $this->routeMatch = $route_match;
   }
 
   /**
@@ -57,8 +68,8 @@ public function __construct(ControllerResolverInterface $controller_resolver, Fo
    *   The render array that results from invoking the controller.
    */
   public function getContentResult(Request $request) {
-    $form_arg = $this->getFormArgument($request);
-    $form_object = $this->getFormObject($request, $form_arg);
+    $form_arg = $this->getFormArgument();
+    $form_object = $this->getFormObject($form_arg);
 
     // Add the form and form_state to trick the getArguments method of the
     // controller resolver.
@@ -88,25 +99,20 @@ public function getContentResult(Request $request) {
    *     _form: Drupal\example\Form\ExampleForm
    * @endcode
    *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request object from which to extract a form definition string.
-   *
    * @return string
    *   The form definition string.
    */
-  abstract protected function getFormArgument(Request $request);
+  abstract protected function getFormArgument();
 
   /**
    * Returns the object used to build the form.
    *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request using this form.
    * @param string $form_arg
    *   Either a class name or a service ID.
    *
    * @return \Drupal\Core\Form\FormInterface
    *   The form object to use.
    */
-  abstract protected function getFormObject(Request $request, $form_arg);
+  abstract protected function getFormObject($form_arg);
 
 }
diff --git a/core/lib/Drupal/Core/Controller/HtmlFormController.php b/core/lib/Drupal/Core/Controller/HtmlFormController.php
index 81a9b02..ee8af94 100644
--- a/core/lib/Drupal/Core/Controller/HtmlFormController.php
+++ b/core/lib/Drupal/Core/Controller/HtmlFormController.php
@@ -8,7 +8,7 @@
 namespace Drupal\Core\Controller;
 
 use Drupal\Core\Form\FormBuilderInterface;
-use Symfony\Component\HttpFoundation\Request;
+use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\DependencyInjection\ClassResolverInterface;
 
 /**
@@ -30,33 +30,27 @@ class HtmlFormController extends FormController {
    *   The controller resolver.
    * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
    *   The form builder.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
    * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
    *   The class resolver.
    */
-  public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder, ClassResolverInterface $class_resolver) {
-    parent::__construct($controller_resolver, $form_builder);
+  public function __construct(ControllerResolverInterface $controller_resolver, FormBuilderInterface $form_builder, RouteMatchInterface $route_match, ClassResolverInterface $class_resolver) {
+    parent::__construct($controller_resolver, $form_builder, $route_match);
     $this->classResolver = $class_resolver;
   }
 
   /**
-   * @{inheritDoc}
+   * {@inheritdoc}
    */
-  protected function getFormArgument(Request $request) {
-    return $request->attributes->get('_form');
+  protected function getFormArgument() {
+    return $this->routeMatch->getRouteObject()->getDefault('_form');
   }
 
   /**
-   * Returns the object used to build the form.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request using this form.
-   * @param string $form_arg
-   *   Either a class name or a service ID.
-   *
-   * @return \Drupal\Core\Form\FormInterface
-   *   The form object to use.
+   * {@inheritdoc}
    */
-  protected function getFormObject(Request $request, $form_arg) {
+  protected function getFormObject($form_arg) {
     return $this->classResolver->getInstanceFromDefinition($form_arg);
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityForm.php b/core/lib/Drupal/Core/Entity/EntityForm.php
index ba36601..d70f273 100644
--- a/core/lib/Drupal/Core/Entity/EntityForm.php
+++ b/core/lib/Drupal/Core/Entity/EntityForm.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
+use Drupal\Core\Routing\RouteMatchInterface;
 
 /**
  * Base class for entity forms.
@@ -37,6 +38,13 @@ class EntityForm extends FormBase implements EntityFormInterface {
   protected $moduleHandler;
 
   /**
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
+  /**
    * The entity being used by this form.
    *
    * @var \Drupal\Core\Entity\EntityInterface
@@ -322,6 +330,20 @@ public function setEntity(EntityInterface $entity) {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id) {
+    if ($route_match->getRawParameter($entity_type_id)) {
+      $entity = $route_match->getParameter($entity_type_id);
+    }
+    else {
+      $entity = $this->entityManager->getStorage($entity_type_id)->create([]);
+    }
+
+    return $entity;
+  }
+
+  /**
    * Prepares the entity object before the form is built first.
    */
   protected function prepareEntity() {}
@@ -362,4 +384,12 @@ public function setModuleHandler(ModuleHandlerInterface $module_handler) {
     return $this;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setEntityManager(EntityManagerInterface $entity_manager) {
+    $this->entityManager = $entity_manager;
+    return $this;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityFormInterface.php b/core/lib/Drupal/Core/Entity/EntityFormInterface.php
index b8ecab1..0bb11d4 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormInterface.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\BaseFormIdInterface;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
 
 /**
@@ -40,9 +41,6 @@ public function getOperation();
    *
    * The form entity which has been used for populating form element defaults.
    *
-   * @param \Drupal\Core\Form\FormStateInterface $form_state
-   *   The current state of the form.
-   *
    * @return \Drupal\Core\Entity\EntityInterface
    *   The current form entity.
    */
@@ -65,6 +63,19 @@ public function getEntity();
   public function setEntity(EntityInterface $entity);
 
   /**
+   * Determines which entity will be used by this form from a Request object.
+   *
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
+   * @param string $entity_type_id
+   *   The entity type identifier.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface
+   *   The entity object as determined from the passed-in Request.
+   */
+  public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id);
+
+  /**
    * Builds an updated entity object based upon the submitted form values.
    *
    * For building the updated entity object the form's entity is cloned and
@@ -129,4 +140,14 @@ public function setStringTranslation(TranslationInterface $string_translation);
    */
   public function setModuleHandler(ModuleHandlerInterface $module_handler);
 
+  /**
+   * Sets the entity manager for this form.
+   *
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager.
+   *
+   * @return $this
+   */
+  public function setEntityManager(EntityManagerInterface $entity_manager);
+
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 7d7eded..c1ff6f5 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -294,6 +294,7 @@ public function getFormObject($entity_type, $operation) {
       $form_object
         ->setStringTranslation($this->translationManager)
         ->setModuleHandler($this->moduleHandler)
+        ->setEntityManager($this)
         ->setOperation($operation);
       $this->handlers['form'][$operation][$entity_type] = $form_object;
     }
diff --git a/core/lib/Drupal/Core/Entity/HtmlEntityFormController.php b/core/lib/Drupal/Core/Entity/HtmlEntityFormController.php
index bd659a9..208d03c 100644
--- a/core/lib/Drupal/Core/Entity/HtmlEntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/HtmlEntityFormController.php
@@ -10,7 +10,7 @@
 use Drupal\Core\Controller\ControllerResolverInterface;
 use Drupal\Core\Controller\FormController;
 use Drupal\Core\Form\FormBuilderInterface;
-use Symfony\Component\HttpFoundation\Request;
+use Drupal\Core\Routing\RouteMatchInterface;
 
 /**
  * Wrapping controller for entity forms that serve as the main page body.
@@ -22,7 +22,7 @@ class HtmlEntityFormController extends FormController {
    *
    * @var \Drupal\Core\Entity\EntityManagerInterface
    */
-  protected $manager;
+  protected $entityManager;
 
   /**
    * Constructs a new \Drupal\Core\Routing\Enhancer\FormEnhancer object.
@@ -31,19 +31,21 @@ class HtmlEntityFormController extends FormController {
    *   The controller resolver.
    * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
    *   The form builder.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
    * @param \Drupal\Core\Entity\EntityManagerInterface $manager
    *   The entity manager.
    */
-  public function __construct(ControllerResolverInterface $resolver, FormBuilderInterface $form_builder, EntityManagerInterface $manager) {
-    parent::__construct($resolver, $form_builder);
-    $this->manager = $manager;
+  public function __construct(ControllerResolverInterface $resolver, FormBuilderInterface $form_builder, RouteMatchInterface $route_match, EntityManagerInterface $manager) {
+    parent::__construct($resolver, $form_builder, $route_match);
+    $this->entityManager = $manager;
   }
 
   /**
-   * @{inheritDoc}
+   * {@inheritdoc}
    */
-  protected function getFormArgument(Request $request) {
-    return $request->attributes->get('_entity_form');
+  protected function getFormArgument() {
+    return $this->routeMatch->getRouteObject()->getDefault('_entity_form');
   }
 
   /**
@@ -66,19 +68,19 @@ protected function getFormArgument(Request $request) {
    *     _entity_form: 'node'
    * @endcode
    */
-  protected function getFormObject(Request $request, $form_arg) {
+  protected function getFormObject($form_arg) {
     // If no operation is provided, use 'default'.
     $form_arg .= '.default';
-    list ($entity_type, $operation) = explode('.', $form_arg);
+    list ($entity_type_id, $operation) = explode('.', $form_arg);
+
+    $form_object = $this->entityManager->getFormObject($entity_type_id, $operation);
 
-    if ($request->attributes->has($entity_type)) {
-      $entity = $request->attributes->get($entity_type);
-    }
-    else {
-      $entity = $this->manager->getStorage($entity_type)->create([]);
-    }
+    // Allow the entity form handler to determine the entity object from a given
+    // request.
+    $entity = $form_object->getEntityFromRouteMatch($this->routeMatch, $entity_type_id);
+    $form_object->setEntity($entity);
 
-    return $this->manager->getFormObject($entity_type, $operation)->setEntity($entity);
+    return $form_object;
   }
 
 }
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
index fa7c14b..dd7625e 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -1510,6 +1510,13 @@ public function setOperation($operation) {
     return $this;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setEntityManager($entity_manager) {
+    return $this;
+  }
+
 }
 
 /**
