diff --git a/core/lib/Drupal/Core/Controller/ControllerResolver.php b/core/lib/Drupal/Core/Controller/ControllerResolver.php
index 385f198..1733738 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'). 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') && $raw = $request->attributes->get(':raw')->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 be5676e..a75b138 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\HttpFoundation\Request;
 
@@ -68,17 +69,24 @@ public function enhance(array $defaults, Request $request) {
     //    a variable again.
     // 2. To check if upcasting was successfull after each converter had
     //    a go. See below.
-    $converters = array();
+    $converted = array();
 
     $route = $defaults[RouteObjectInterface::ROUTE_OBJECT];
+    // Store a backup of the raw $defaults values corresponding to
+    // variables in the route path pattern.
+    $variables = array_flip($route->compile()->getVariables());
+    $raw = new ParameterBag(array_intersect_key($defaults, $variables));
 
     foreach ($this->converters as $converter) {
-      $converter->process($defaults, $route, $converters);
+      $converter->process($defaults, $route, $converted);
     }
 
+    // Add the copy the raw values of all the URI variables to $defaults.
+    $defaults[':raw'] = $raw;
+
     // Check if all upcasting yielded a result.
     // If an upcast value is NULL do a 404.
-    foreach ($converters as $variable) {
+    foreach ($converted as $variable) {
       if ($defaults[$variable] === NULL) {
         throw new NotFoundHttpException();
       }
diff --git a/core/modules/image/lib/Drupal/image/Form/ImageEffectDeleteForm.php b/core/modules/image/lib/Drupal/image/Form/ImageEffectDeleteForm.php
index 50bf2bb..15197e4 100644
--- a/core/modules/image/lib/Drupal/image/Form/ImageEffectDeleteForm.php
+++ b/core/modules/image/lib/Drupal/image/Form/ImageEffectDeleteForm.php
@@ -61,7 +61,7 @@ public function getFormID() {
   /**
    * {@inheritdoc}
    */
-  public function buildForm(array $form, array &$form_state, $image_style = NULL, $image_effect = NULL, Request $request = NULL) {
+  public function buildForm(array $form, array &$form_state, ImageStyle $image_style = NULL, $image_effect = NULL, Request $request = NULL) {
     $this->imageStyle = $image_style;
     $this->imageEffect = image_effect_load($image_effect, $this->imageStyle->id());
 
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..a1db7e8
--- /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' => 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.');
+  }
+
+}
