diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index 4a03975..bb5a24a 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -23,6 +23,16 @@ class EntityFormController implements EntityFormControllerInterface {
   protected $operation;
 
   /**
+   * The method which the form conroller uses for deleting entities
+   *
+   * Subclasses can change the value to "callback" if deletions are not done
+   * via a link to separate form.
+   *
+   * @var string
+   */
+  protected $delete_method = 'link';
+
+  /**
    * Constructs an EntityFormController object.
    *
    * @param string $operation
@@ -89,11 +99,7 @@ public function form(array $form, array &$form_state, EntityInterface $entity) {
   protected function actionsElement(array $form, array &$form_state) {
     $element = $this->actions($form, $form_state);
 
-    // We cannot delete an entity that has not been created yet.
-    if ($this->getEntity($form_state)->isNew()) {
-      unset($element['delete']);
-    }
-    elseif (isset($element['delete'])) {
+    if (isset($element['delete'])) {
       // Move the delete action as last one, unless weights are explicitly
       // provided.
       $delete = $element['delete'];
@@ -126,7 +132,8 @@ protected function actionsElement(array $form, array &$form_state) {
    * Returns an array of supported actions for the current entity form.
    */
   protected function actions(array $form, array &$form_state) {
-    return array(
+    $entity = $this->getEntity($form_state);
+    $actions = array(
       // @todo Rename the action key from submit to save.
       'submit' => array(
         '#value' => t('Save'),
@@ -138,16 +145,32 @@ protected function actions(array $form, array &$form_state) {
           array($this, 'save'),
         ),
       ),
-      'delete' => array(
-        '#value' => t('Delete'),
-        // No need to validate the form when deleting the entity.
-        '#submit' => array(
-          array($this, 'delete'),
-        ),
-      ),
       // @todo Consider introducing a 'preview' action here, since it is used by
       // many entity types.
     );
+    if (!$entity->isNew()) {
+      if ($this->delete_method == 'callback') {
+        // For EntityFormController subclasses that use a form callback for
+        // deletes we have to make it a button.
+        $actions['delete'] = array(
+          '#value' => t('Delete'),
+          '#submit' => array(
+            array($this, 'delete'),
+          ),
+        );
+      }
+      else {
+        // For EntityFormController subclasses tat delete via a link to the
+        // delete form we have to make a link.
+        $entity_uri = $entity->uri();
+        $actions['delete'] = array(
+          '#type' => 'link',
+          '#title' => t('Delete'),
+          '#href' => $entity_uri['path'] . '/delete',
+        );
+      }
+    }
+    return $actions;
   }
 
   /**
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php
index e93b79f..30dbe38 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php
@@ -220,8 +220,10 @@ function testCRUDUI() {
 
     // Delete the configuration entity.
     $this->drupalGet("admin/structure/config_test/manage/$id/edit");
-    $this->drupalPost(NULL, array(), 'Delete');
-    $this->assertUrl("admin/structure/config_test/manage/$id/delete");
+    // There should be two delete links - a tab and a link in the actions
+    // section.
+    $this->assertLinkByHref("admin/structure/config_test/manage/$id/delete", 1);
+    $this->drupalGet("admin/structure/config_test/manage/$id/delete");
     $this->drupalPost(NULL, array(), 'Delete');
     $this->assertUrl('admin/structure/config_test');
     $this->assertResponse(200);
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index 8082322..1196944 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -305,8 +305,9 @@ protected function actions(array $form, array &$form_state) {
       ),
     );
 
-    $element['delete']['#access'] = node_access('delete', $node);
-    $element['delete']['#weight'] = 100;
+    if (isset($element['delete'])) {
+      $element['delete']['#access'] = node_access('delete', $node);
+    }
 
     return $element;
   }
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
index 9f65f1c..29f0bc6 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
@@ -201,7 +201,11 @@ function testNodeTermCreationAndDeletion() {
     }
 
     // Delete term 1 from the term edit page.
-    $this->drupalPost('taxonomy/term/' . $term_objects['term1']->tid . '/edit', array(), t('Delete'));
+    $this->drupalGet('taxonomy/term/' . $term_objects['term1']->tid . '/edit');
+    // There should be two delete links - a tab and a link in the actions
+    // section.
+    $this->assertLinkByHref('taxonomy/term/' . $term_objects['term1']->tid . '/delete', 1);
+    $this->drupalGet('taxonomy/term/' . $term_objects['term1']->tid . '/delete');
     $this->drupalPost(NULL, NULL, t('Delete'));
 
     // Delete term 2 from the term delete page.
@@ -351,7 +355,7 @@ function testTermInterface() {
     $this->drupalGet('taxonomy/term/' . $term->tid . '/edit/' . $this->randomName());
 
     // Delete the term.
-    $this->drupalPost('taxonomy/term/' . $term->tid . '/edit', array(), t('Delete'));
+    $this->drupalGet('taxonomy/term/' . $term->tid . '/delete');
     $this->drupalPost(NULL, NULL, t('Delete'));
 
     // Assert that the term no longer exists.
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php
index 6785335..48a85b9 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php
@@ -14,6 +14,10 @@
  * Base form controller for vocabulary edit forms.
  */
 class VocabularyFormController extends EntityFormController {
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::delete_method
+   */
+  protected $delete_method = 'callback';
 
   /**
    * Overrides Drupal\Core\Entity\EntityFormController::form().
@@ -87,7 +91,9 @@ protected function actions(array $form, array &$form_state) {
     // If we are displaying the delete confirmation skip the regular actions.
     if (empty($form_state['confirm_delete'])) {
       $actions = parent::actions($form, $form_state);
-      array_unshift($actions['delete']['#submit'], array($this, 'submit'));
+      if (isset($actions['delete'])) {
+        array_unshift($actions['delete']['#submit'], array($this, 'submit'));
+      }
       // Add the language configuration submit handler. This is needed because
       // the submit button has custom submit handlers.
       if (module_exists('language')) {
