diff --git a/core/modules/rest/src/RequestHandler.php b/core/modules/rest/src/RequestHandler.php
index 2aa3673..b1f770b 100644
--- a/core/modules/rest/src/RequestHandler.php
+++ b/core/modules/rest/src/RequestHandler.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\rest;
 
+use Drupal\Component\Utility\ArgumentsResolver;
 use Drupal\Core\Cache\CacheableResponseInterface;
 use Drupal\Core\Render\RenderContext;
 use Drupal\Core\Routing\RouteMatchInterface;
@@ -9,6 +10,7 @@
 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
 use Symfony\Component\HttpKernel\Exception\HttpException;
 use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
 use Symfony\Component\Serializer\Exception\UnexpectedValueException;
@@ -73,13 +75,12 @@ public function handle(RouteMatchInterface $route_match, Request $request) {
 
     // Determine the request parameters that should be passed to the resource
     // plugin.
-    $route_parameters = $route_match->getParameters();
-    $parameters = array();
-    // Filter out all internal parameters starting with "_".
-    foreach ($route_parameters as $key => $parameter) {
-      if ($key{0} !== '_') {
-        $parameters[] = $parameter;
-      }
+    $argument_resolver = $this->getArgumentResolver($route_match);
+    try {
+      $arguments = $argument_resolver->getArguments([$resource, $method]);
+    }
+    catch (\RuntimeException $exception) {
+      $arguments = $this->getLegacyParameters($route_match, $unserialized, $request);
     }
 
     // Invoke the operation on the resource plugin.
@@ -88,7 +89,7 @@ public function handle(RouteMatchInterface $route_match, Request $request) {
     // format requirement. If there is no format associated, just pick JSON.
     $format = $route_match->getRouteObject()->getRequirement('_format') ?: 'json';
     try {
-      $response = call_user_func_array(array($resource, $method), array_merge($parameters, array($unserialized, $request)));
+      $response = call_user_func_array(array($resource, $method), $arguments);
     }
     catch (HttpException $e) {
       $error['error'] = $e->getMessage();
@@ -105,6 +106,67 @@ public function handle(RouteMatchInterface $route_match, Request $request) {
   }
 
   /**
+   * Creates an argument resolver, which can pass along the REST parameters.
+   *
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match
+   * @param mixed $unserialized
+   *   The unserialized data.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request.
+   *
+   * @return \Drupal\Component\Utility\ArgumentsResolver
+   */
+  protected function getArgumentResolver(RouteMatchInterface $route_match, $unserialized, Request $request) {
+    $route = $route_match->getRouteObject();
+
+    // Defaults for the parameters defined on the route object need to be added
+    // to the raw arguments.
+    $raw_route_arguments = $route_match->getRawParameters()->all() + $route->getDefaults();
+
+    $upcasted_route_arguments = $route_match->getParameters()->all();
+    $upcasted_route_arguments['entity'] = $unserialized;
+    $upcasted_route_arguments['data'] = $unserialized;
+    $upcasted_route_arguments['unserialized'] = $unserialized;
+
+    // Parameters which are not defined on the route object, but still are
+    // essential for access checking are passed as wildcards to the argument
+    // resolver.
+    $wildcard_arguments = [$route, $route_match];
+    if (isset($request)) {
+      $wildcard_arguments[] = $request;
+    }
+    $wildcard_arguments[] = $unserialized;
+
+    return new ArgumentsResolver($raw_route_arguments, $upcasted_route_arguments, $wildcard_arguments);
+  }
+
+  /**
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match
+   * @param mixed $unserialized
+   *   The unserialized data.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request.
+   *
+   * @return array
+   */
+  protected function getLegacyParameters(RouteMatchInterface $route_match, $unserialized, Request $request) {
+    $route_parameters = $route_match->getParameters();
+    $parameters = array();
+    // Filter out all internal parameters starting with "_".
+    foreach ($route_parameters as $key => $parameter) {
+      if ($key{0} !== '_') {
+        $parameters[] = $parameter;
+      }
+    }
+
+    array_merge($parameters, array($unserialized, $request));
+
+    return $parameters;
+  }
+
+  /**
    * Generates a CSRF protecting session token.
    *
    * @return \Symfony\Component\HttpFoundation\Response
