diff --git a/core/lib/Drupal/Core/Controller/FormController.php b/core/lib/Drupal/Core/Controller/FormController.php
index dc191c0..6a9b9d5 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;
 
 /**
@@ -52,13 +53,15 @@ public function __construct(ControllerResolverInterface $controller_resolver, Fo
    *
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The request object.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
    *
    * @return array
    *   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);
+  public function getContentResult(Request $request, RouteMatchInterface $route_match) {
+    $form_arg = $this->getFormArgument($route_match);
+    $form_object = $this->getFormObject($route_match, $form_arg);
 
     // Add the form and form_state to trick the getArguments method of the
     // controller resolver.
@@ -88,25 +91,25 @@ 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.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match 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(RouteMatchInterface $route_match);
 
   /**
    * Returns the object used to build the form.
    *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request using this form.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
    * @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(RouteMatchInterface $route_match, $form_arg);
 
 }
diff --git a/core/lib/Drupal/Core/Controller/HtmlFormController.php b/core/lib/Drupal/Core/Controller/HtmlFormController.php
index 81a9b02..e84975d 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;
 
 /**
@@ -39,24 +39,16 @@ public function __construct(ControllerResolverInterface $controller_resolver, Fo
   }
 
   /**
-   * @{inheritDoc}
+   * {@inheritdoc}
    */
-  protected function getFormArgument(Request $request) {
-    return $request->attributes->get('_form');
+  protected function getFormArgument(RouteMatchInterface $route_match) {
+    return $route_match->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(RouteMatchInterface $route_match, $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..a0b18fa 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) !== NULL) {
+      $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..a8fe39e 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 RouteMatch 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 route match.
+   */
+  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 df404d8..6e7d87f 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..093cb34 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.
@@ -36,14 +36,14 @@ class HtmlEntityFormController extends FormController {
    */
   public function __construct(ControllerResolverInterface $resolver, FormBuilderInterface $form_builder, EntityManagerInterface $manager) {
     parent::__construct($resolver, $form_builder);
-    $this->manager = $manager;
+    $this->entityManager = $manager;
   }
 
   /**
-   * @{inheritDoc}
+   * {@inheritdoc}
    */
-  protected function getFormArgument(Request $request) {
-    return $request->attributes->get('_entity_form');
+  protected function getFormArgument(RouteMatchInterface $route_match) {
+    return $route_match->getRouteObject()->getDefault('_entity_form');
   }
 
   /**
@@ -66,19 +66,19 @@ protected function getFormArgument(Request $request) {
    *     _entity_form: 'node'
    * @endcode
    */
-  protected function getFormObject(Request $request, $form_arg) {
+  protected function getFormObject(RouteMatchInterface $route_match, $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 to determine the entity object from a given route
+    // match.
+    $entity = $form_object->getEntityFromRouteMatch($route_match, $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 ce6cf27..9c42aec 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -10,14 +10,13 @@
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 use Drupal\Component\Plugin\Exception\PluginNotFoundException;
 use Drupal\Core\Config\Entity\ConfigEntityStorage;
-use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Entity\EntityHandlerBase;
 use Drupal\Core\Entity\EntityHandlerInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityManager;
+use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageInterface;
@@ -1486,6 +1485,13 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
 class TestEntityForm extends EntityHandlerBase {
 
   /**
+   * The entity manager.
+   *
+   * @var \Drupal\Tests\Core\Entity\TestEntityManager
+   */
+  protected $entityManager;
+
+  /**
    * {@inheritdoc}
    */
   public function getBaseFormId() {
@@ -1513,6 +1519,14 @@ public function setOperation($operation) {
     return $this;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setEntityManager(EntityManagerInterface $entity_manager) {
+    $this->entityManager = $entity_manager;
+    return $this;
+  }
+
 }
 
 /**
