diff --git a/core/lib/Drupal/Core/Controller/ControllerResolver.php b/core/lib/Drupal/Core/Controller/ControllerResolver.php
index 385f198..2fd4ee2 100644
--- a/core/lib/Drupal/Core/Controller/ControllerResolver.php
+++ b/core/lib/Drupal/Core/Controller/ControllerResolver.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Controller;
 
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver;
 use Symfony\Component\HttpKernel\Log\LoggerInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
@@ -98,4 +99,27 @@ protected function createController($controller) {
     return array($controller, $method);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function doGetArguments(Request $request, $controller, array $parameters) {
+    $arguments = parent::doGetArguments($request, $controller, $parameters);
+
+    // The parameter converter overrides the raw request attributes with the
+    // upcasted objects. However, it keeps a backup copy of the original, raw
+    // values in a special request attribute ('_raw_variables'). If a controller
+    // argument has a type hint, we pass it the upcasted object, otherwise we
+    // pass it the original, raw value.
+    if ($request->attributes->has('_raw_variables') && $raw = $request->attributes->get('_raw_variables')->all()) {
+      foreach ($parameters as $parameter) {
+        // Use the raw value if a parameter has no typehint.
+        if (!$parameter->getClass() && isset($raw[$parameter->name])) {
+          $position = $parameter->getPosition();
+          $arguments[$position] = $raw[$parameter->name];
+        }
+      }
+    }
+    return $arguments;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php b/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php
index 0b494d8..f4b8a31 100644
--- a/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php
+++ b/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php
@@ -10,6 +10,7 @@
 use Symfony\Component\DependencyInjection\ContainerAware;
 use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
+use Symfony\Component\HttpFoundation\ParameterBag;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Symfony\Component\Routing\RouteCollection;
 use Symfony\Component\HttpFoundation\Request;
@@ -151,7 +152,11 @@ public function setRouteParameterConverters(RouteCollection $routes) {
    *   The modified defaults.
    */
   public function enhance(array $defaults, Request $request) {
+    // Store a backup of the raw $defaults values corresponding to
+    // variables in the route path pattern.
     $route = $defaults[RouteObjectInterface::ROUTE_OBJECT];
+    $variables = array_flip($route->compile()->getVariables());
+    $defaults['_raw_variables'] = new ParameterBag(array_intersect_key($defaults, $variables));
 
     // Skip this enhancer if there are no parameter definitions.
     if (!$parameters = $route->getOption('parameters')) {
diff --git a/core/modules/system/tests/modules/paramconverter_test/lib/Drupal/paramconverter_test/TestControllers.php b/core/modules/system/tests/modules/paramconverter_test/lib/Drupal/paramconverter_test/TestControllers.php
index ca95200..cd9b578 100644
--- a/core/modules/system/tests/modules/paramconverter_test/lib/Drupal/paramconverter_test/TestControllers.php
+++ b/core/modules/system/tests/modules/paramconverter_test/lib/Drupal/paramconverter_test/TestControllers.php
@@ -8,20 +8,21 @@
 namespace Drupal\paramconverter_test;
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\node\NodeInterface;
+use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Controller routine for testing the paramconverter.
  */
 class TestControllers {
 
-  public function testUserNodeFoo($user, $node, $foo) {
-    $retval = "user: " . (is_object($user) ? $user->label() : $user);
-    $retval .= ", node: " . (is_object($node) ? $node->label() : $node);
-    $retval .= ", foo: " . (is_object($foo) ? $foo->label() : $foo);
-    return $retval;
+  public function testUserNodeFoo(EntityInterface $user, NodeInterface $node, Request $request) {
+    $foo = $request->attributes->get('foo');
+    $foo = is_object($foo) ? $foo->label() : $foo;
+    return "user: {$user->label()}, node: {$node->label()}, foo: $foo";
   }
 
-  public function testNodeSetParent(EntityInterface $node, EntityInterface $parent) {
-    return "Setting '{$parent->title}' as parent of '{$node->title}'.";
+  public function testNodeSetParent(NodeInterface $node, NodeInterface $parent) {
+    return "Setting '{$parent->label()}' as parent of '{$node->label()}'.";
   }
 }
diff --git a/core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php b/core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php
new file mode 100644
index 0000000..2fbfa9a
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Controller\ControllerResolverTest.
+ */
+
+namespace Drupal\Tests\Core\Controller;
+
+use Drupal\Core\Controller\ControllerResolver;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Tests\UnitTestCase;
+use Drupal\user\UserInterface;
+use Guzzle\Http\Message\Request;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
+
+/**
+ * Tests that the Drupal-extended ControllerResolver is functioning properly.
+ *
+ * @see \Drupal\Core\Controller\ControllerResolver
+ */
+class ControllerResolverTest extends UnitTestCase {
+
+  /**
+   * The tested controller resolver.
+   *
+   * @var \Drupal\Core\Controller\ControllerResolver
+   */
+  public $controllerResolver;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Controller Resolver tests',
+      'description' => 'Tests that the Drupal-extended ControllerResolver is functioning properly.',
+      'group' => 'Routing',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $container = new ContainerBuilder();
+    $this->controllerResolver = new ControllerResolver($container);
+  }
+
+  /**
+   * Tests getArguments().
+   *
+   * Ensure that doGetArguments uses converted arguments if available.
+   *
+   * @see \Drupal\Core\Controller\ControllerResolver::getArguments()
+   * @see \Drupal\Core\Controller\ControllerResolver::doGetArguments()
+   */
+  public function testGetArguments() {
+    $controller = function(EntityInterface $entity, $user) {
+    };
+    $mock_entity = $this->getMockBuilder('Drupal\Core\Entity\Entity')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $mock_account = $this->getMock('Drupal\Core\Session\AccountInterface');
+    $request = new \Symfony\Component\HttpFoundation\Request(array(), array(), array(
+      'entity' => $mock_entity,
+      'user' => $mock_account,
+      '_raw_variables' => new ParameterBag(array('entity' => 1, 'user' => 1)),
+    ));
+    $arguments = $this->controllerResolver->getArguments($request, $controller);
+
+    $this->assertEquals($mock_entity, $arguments[0], 'Type hinted variables should use upcasted values.');
+    $this->assertEquals(1, $arguments[1], 'Not type hinted variables should use not upcasted values.');
+  }
+
+}
