diff --git a/core/modules/system/lib/Drupal/system/Controller/ThemeController.php b/core/modules/system/lib/Drupal/system/Controller/ThemeController.php
index 61d931c..e67f6ee 100644
--- a/core/modules/system/lib/Drupal/system/Controller/ThemeController.php
+++ b/core/modules/system/lib/Drupal/system/Controller/ThemeController.php
@@ -12,6 +12,7 @@
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 
 /**
@@ -123,4 +124,67 @@ public function enable(Request $request) {
     throw new AccessDeniedHttpException();
   }
 
+  /**
+   * Set the default theme.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   A request object containing a theme name and a valid token.
+   *
+   * @return \Symfony\Component\HttpFoundation\RedirectResponse
+   *   Redirects back to the appearance admin page.
+   *
+   * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
+   *   Throws access denied when no theme or token is set in the request or when
+   *   the token is invalid.
+   */
+  public function defaultTheme(Request $request) {
+    // Set the page title.
+    drupal_set_title(t('Set default theme'));
+
+    $theme = $request->get('theme');
+    $token = $request->get('token');
+    if (isset($theme) && isset($token) && drupal_valid_token($token, 'system-theme-operation-link')) {
+      // Get current list of themes.
+      $themes = list_themes();
+
+      // Check if the specified theme is one recognized by the system.
+      if (!empty($themes[$theme])) {
+        // Enable the theme if it is currently disabled.
+        if (empty($themes[$theme]->status)) {
+          theme_enable(array($theme));
+        }
+
+        // Set the default theme.
+        $this->config->set('default', $theme)
+          ->save();
+
+        // Rebuild the menu. This duplicates the menu_router_rebuild() in
+        // theme_enable(). However, modules must know the current default theme in
+        // order to use this information in hook_menu() or hook_menu_alter()
+        // implementations, and doing the variable_set() before the theme_enable()
+        // could result in a race condition where the theme is default but not
+        // enabled.
+        menu_router_rebuild();
+
+        // The status message depends on whether an admin theme is currently in use:
+        // a value of 0 means the admin theme is set to be the default theme.
+        $admin_theme = $this->config->get('admin');
+        if ($admin_theme != 0 && $admin_theme != $theme) {
+          drupal_set_message(t('Please note that the administration theme is still set to the %admin_theme theme; consequently, the theme on this page remains unchanged. All non-administrative sections of the site, however, will show the selected %selected_theme theme by default.', array(
+            '%admin_theme' => $themes[$admin_theme]->info['name'],
+            '%selected_theme' => $themes[$theme]->info['name'],
+          )));
+        }
+        else {
+          drupal_set_message(t('%theme is now the default theme.', array('%theme' => $themes[$theme]->info['name'])));
+        }
+      }
+      else {
+        drupal_set_message(t('The %theme theme was not found.', array('%theme' => $theme)), 'error');
+      }
+      return new RedirectResponse(url('admin/appearance', array('absolute' => TRUE)));
+    }
+    throw new AccessDeniedHttpException();
+  }
+
 }
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 1cfea0c..67bbe0b 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -256,55 +256,6 @@ function system_themes_admin_form_submit($form, &$form_state) {
 }
 
 /**
- * Menu callback; Set the default theme.
- */
-function system_theme_default() {
-  if (isset($_REQUEST['theme']) && isset($_REQUEST['token']) && drupal_valid_token($_REQUEST['token'], 'system-theme-operation-link')) {
-    $theme = $_REQUEST['theme'];
-    // Get current list of themes.
-    $themes = list_themes();
-
-    // Check if the specified theme is one recognized by the system.
-    if (!empty($themes[$theme])) {
-      // Enable the theme if it is currently disabled.
-      if (empty($themes[$theme]->status)) {
-       theme_enable(array($theme));
-      }
-      // Set the default theme.
-      config('system.theme')
-        ->set('default', $theme)
-        ->save();
-
-      // Rebuild the menu. This duplicates the menu_router_rebuild() in
-      // theme_enable(). However, modules must know the current default theme in
-      // order to use this information in hook_menu() or hook_menu_alter()
-      // implementations, and doing the variable_set() before the theme_enable()
-      // could result in a race condition where the theme is default but not
-      // enabled.
-      menu_router_rebuild();
-
-      // The status message depends on whether an admin theme is currently in use:
-      // a value of 0 means the admin theme is set to be the default theme.
-      $admin_theme = config('system.theme')->get('admin');
-      if ($admin_theme != 0 && $admin_theme != $theme) {
-        drupal_set_message(t('Please note that the administration theme is still set to the %admin_theme theme; consequently, the theme on this page remains unchanged. All non-administrative sections of the site, however, will show the selected %selected_theme theme by default.', array(
-          '%admin_theme' => $themes[$admin_theme]->info['name'],
-          '%selected_theme' => $themes[$theme]->info['name'],
-        )));
-      }
-      else {
-        drupal_set_message(t('%theme is now the default theme.', array('%theme' => $themes[$theme]->info['name'])));
-      }
-    }
-    else {
-      drupal_set_message(t('The %theme theme was not found.', array('%theme' => $theme)), 'error');
-    }
-    drupal_goto('admin/appearance');
-  }
-  throw new AccessDeniedHttpException();
-}
-
-/**
  * Form builder; display theme configuration for entire site and individual themes.
  *
  * @param $key
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 6a1f766..8fbdb29 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -699,13 +699,6 @@ function system_menu() {
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'file' => 'system.admin.inc',
   );
-  $items['admin/appearance/default'] = array(
-    'title' => 'Set default theme',
-    'page callback' => 'system_theme_default',
-    'access arguments' => array('administer themes'),
-    'type' => MENU_CALLBACK,
-    'file' => 'system.admin.inc',
-  );
   $items['admin/appearance/settings'] = array(
     'title' => 'Settings',
     'description' => 'Configure default and theme specific settings.',
diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml
index 0ba8674..878c8d8 100644
--- a/core/modules/system/system.routing.yml
+++ b/core/modules/system/system.routing.yml
@@ -143,3 +143,10 @@ system_admin_index:
     _content: 'Drupal\system\Controller\AdminController::index'
   requirements:
     _permission: 'access administration pages'
+
+system_theme_default:
+  pattern: '/admin/appearance/default'
+  defaults:
+    _controller: 'Drupal\system\Controller\ThemeController::defaultTheme'
+  requirements:
+    _permission: 'administer themes'
