diff --git a/core/modules/history/history.module b/core/modules/history/history.module
index a3842fc..0dfad16 100644
--- a/core/modules/history/history.module
+++ b/core/modules/history/history.module
@@ -10,6 +10,7 @@
  */
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\entity\Entity\EntityDisplay;
 
 /**
  * Entities changed before this time are always shown as read.
@@ -129,6 +130,30 @@ function history_cron() {
 }
 
 /**
+ * Implements hook_node_view_alter().
+ */
+function history_node_view_alter(&$build, EntityInterface $node, EntityDisplay $display) {
+  // Update the history table, stating that this user viewed this node.
+  if (($display->originalMode === 'full') && \Drupal::currentUser()->isAuthenticated()) {
+    $build['#attached'] = array(
+      'js' => array(
+        // When the window's "load" event is triggered, mark the node as read.
+        // This still allows for Drupal behaviors (which are triggered on the
+        // "DOMContentReady" event) to add "new" and "updated" indicators.
+        array(
+          'data' => 'window.addEventListener("load",function(){Drupal.history.markAsRead(' . $node->id() . ');},false);',
+          'type' => 'inline',
+        ),
+      ),
+      'library' => array(
+        array('history', 'drupal.history'),
+      ),
+    );
+  }
+
+}
+
+/**
  * Implements hook_node_delete().
  */
 function history_node_delete(EntityInterface $node) {
diff --git a/core/modules/node/lib/Drupal/node/Controller/NodeController.php b/core/modules/node/lib/Drupal/node/Controller/NodeController.php
index 09a9690..575387a 100644
--- a/core/modules/node/lib/Drupal/node/Controller/NodeController.php
+++ b/core/modules/node/lib/Drupal/node/Controller/NodeController.php
@@ -7,13 +7,15 @@
 
 namespace Drupal\node\Controller;
 
+use Drupal\Component\Utility\String;
+use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\node\NodeInterface;
 
 /**
  * Returns responses for Node routes.
  */
-class NodeController {
+class NodeController extends ControllerBase {
 
   /**
    * @todo Remove node_admin_nodes().
@@ -40,11 +42,34 @@ public function add(EntityInterface $node_type) {
   }
 
   /**
-   * @todo Remove node_show().
+   * Displays a node revision.
+   *
+   * @param int $node_revision
+   *   The node revision ID.
+   *
+   * @return array
+   *   An array suitable for drupal_render().
    */
   public function revisionShow($node_revision) {
-    $node_revision = entity_revision_load('node', $node_revision);
-    return node_show($node_revision, TRUE);
+    $node = $this->entityManager()->getStorageController('node')->loadRevision($node_revision);
+    $page = $this->buildPage($node);
+    unset($page['nodes'][$node->id()]['#cache']);
+
+    return $page;
+  }
+
+  /**
+   * Page title callback for a node revision.
+   *
+   * @param int $node_revision
+   *   The node revision ID.
+   *
+   * @return string
+   *   The page title.
+   */
+  public function revisionPageTitle($node_revision) {
+    $node = $this->entityManager()->getStorageController('node')->loadRevision($node_revision);
+    return $this->t('Revision of %title from %date', array('%title' => $node->label(), '%date' => format_date($node->getRevisionCreationTime())));
   }
 
   /**
@@ -55,4 +80,60 @@ public function revisionOverview(NodeInterface $node) {
     return node_revision_overview($node);
   }
 
+  /**
+   * Displays a node.
+   *
+   * @param \Drupal\node\NodeInterface $node
+   *   The node we are displaying.
+   *
+   * @return array
+   *   An array suitable for drupal_render().
+   */
+  public function page(NodeInterface $node) {
+    foreach ($node->uriRelationships() as $rel) {
+      $uri = $node->uri($rel);
+      // Set the node path as the canonical URL to prevent duplicate content.
+      drupal_add_html_head_link(array(
+        'rel' => $rel,
+        'href' => $this->urlGenerator()->generateFromPath($uri['path'], $uri['options']),
+      ), TRUE);
+
+      if ($rel == 'canonical') {
+        // Set the non-aliased canonical path as a default shortlink.
+        drupal_add_html_head_link(array(
+          'rel' => 'shortlink',
+          'href' => $this->urlGenerator()->generateFromPath($uri['path'], array_merge($uri['options'], array('alias' => TRUE))),
+        ), TRUE);
+      }
+    }
+
+    return $this->buildPage($node);
+  }
+
+  /**
+   * The _title_callback for the node.view route.
+   *
+   * @param NodeInterface $node
+   *   The current node.
+   *
+   * @return string
+   *   The page title.
+   */
+  public function pageTitle(NodeInterface $node) {
+    return String::checkPlain($node->label());
+  }
+
+  /**
+   * Builds a node page render array.
+   *
+   * @param \Drupal\node\NodeInterface $node
+   *   The node we are displaying.
+   *
+   * @return array
+   *   An array suitable for drupal_render().
+   */
+  protected function buildPage(NodeInterface $node) {
+    return array('nodes' => $this->entityManager()->getRenderController('node')->view($node));
+  }
+
 }
diff --git a/core/modules/node/lib/Drupal/node/Controller/NodeView.php b/core/modules/node/lib/Drupal/node/Controller/NodeView.php
deleted file mode 100644
index 33181d8..0000000
--- a/core/modules/node/lib/Drupal/node/Controller/NodeView.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\node\Controller\NodeView.
- */
-
-namespace Drupal\node\Controller;
-
-use Drupal\Component\Utility\String;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\node\NodeInterface;
-
-/**
- * Returns responses for Node routes.
- */
-class NodeView {
-
-  /**
-   * @todo Remove node_page_view().
-   */
-  public function page(NodeInterface $node) {
-    return node_page_view($node);
-  }
-
-  /**
-   * The _title_callback for the node.view route.
-   *
-   * @param \Drupal\node\NodeInterface $node
-   */
-  public function pageTitle(NodeInterface $node) {
-    return String::checkPlain($node->label());
-  }
-
-}
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 772481b9..f163b51 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -564,54 +564,6 @@ function node_revision_delete($revision_id) {
 }
 
 /**
- * Page callback: Generates an array which displays a node detail page.
- *
- * @param \Drupal\Core\Entity\EntityInterface $node
- *   A node entity.
- * @param $message
- *   (optional) A flag which sets a page title relevant to the revision being
- *   viewed.  Default is FALSE.
- *
- * @return
- *   A $page element suitable for use by drupal_render().
- *
- * @see node_menu()
- *
- * @deprecated Use \Drupal\node\Controller\NodeController::revisionShow()
- */
-function node_show(EntityInterface $node, $message = FALSE) {
-  // For markup consistency with other pages, use node_view_multiple() rather than node_view().
-  $page = array('nodes' => node_view_multiple(array($node->id() => $node), 'full'));
-
-  if ($message) {
-    $page['#title'] = t('Revision of %title from %date', array('%title' => $node->label(), '%date' => format_date($node->getRevisionCreationTime())));
-    // Don't use the render cache when a revision is displayed.
-    unset($page['nodes'][$node->id()]['#cache']);
-  }
-
-  // Update the history table, stating that this user viewed this node.
-  global $user;
-  if (\Drupal::moduleHandler()->moduleExists('history') && $user->isAuthenticated()) {
-    $page['#attached'] = array(
-      'js' => array(
-        // When the window's "load" event is triggered, mark the node as read.
-        // This still allows for Drupal behaviors (which are triggered on the
-        // "DOMContentReady" event) to add "new" and "updated" indicators.
-        array(
-          'data' => 'window.addEventListener("load",function(){Drupal.history.markAsRead(' . $node->id() . ');},false);',
-          'type' => 'inline',
-        ),
-      ),
-      'library' => array(
-        array('history', 'drupal.history'),
-      )
-    );
-  }
-
-  return $page;
-}
-
-/**
  * Checks whether the current page is the full page view of the passed-in node.
  *
  * @param \Drupal\Core\Entity\EntityInterface $node
@@ -1458,36 +1410,6 @@ function node_view_multiple($nodes, $view_mode = 'teaser', $langcode = NULL) {
 }
 
 /**
- * Page callback: Displays a single node.
- *
- * @param \Drupal\Core\Entity\EntityInterface $node
- *   The node entity.
- *
- * @return
- *   A page array suitable for use by drupal_render().
- *
- * @see node_menu()
- *
- * @deprecated Use \Drupal\node\Controller\NodeController::viewPage()
- */
-function node_page_view(EntityInterface $node) {
-  foreach ($node->uriRelationships() as $rel) {
-    $uri = $node->uri($rel);
-    // Set the node path as the canonical URL to prevent duplicate content.
-    drupal_add_html_head_link(array('rel' => $rel, 'href' => url($uri['path'], $uri['options'])), TRUE);
-
-    if ($rel == 'canonical') {
-      // Set the non-aliased canonical path as a default shortlink.
-      drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array_merge($uri['options'], array('alias' => TRUE)))), TRUE);
-    }
-  }
-
-  $build = node_show($node);
-
-  return $build;
-}
-
-/**
  * Implements hook_form_FORM_ID_alter().
  *
  * Alters the System module's site information settings form to add a global
diff --git a/core/modules/node/node.routing.yml b/core/modules/node/node.routing.yml
index aabd9c4..8c92237 100644
--- a/core/modules/node/node.routing.yml
+++ b/core/modules/node/node.routing.yml
@@ -41,8 +41,8 @@ node.add:
 node.view:
   path: '/node/{node}'
   defaults:
-    _content: '\Drupal\node\Controller\NodeView::page'
-    _title_callback: '\Drupal\node\Controller\NodeView::pageTitle'
+    _content: '\Drupal\node\Controller\NodeController::page'
+    _title_callback: '\Drupal\node\Controller\NodeController::pageTitle'
   requirements:
     _entity_access: 'node.view'
 
@@ -64,8 +64,8 @@ node.revision_overview:
 node.revision_show:
   path: '/node/{node}/revisions/{node_revision}/view'
   defaults:
-    _title: 'Revisions'
     _content: '\Drupal\node\Controller\NodeController::revisionShow'
+    _title_callback: '\Drupal\node\Controller\NodeController::revisionPageTitle'
   requirements:
     _access_node_revision: 'view'
 
