diff --git a/src/Controller/EntityResource.php b/src/Controller/EntityResource.php
index 2d5f2e9..8d4d99c 100644
--- a/src/Controller/EntityResource.php
+++ b/src/Controller/EntityResource.php
@@ -6,12 +6,12 @@ use Drupal\Component\Serialization\Json;
 use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Config\Entity\ConfigEntityInterface;
 use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\Entity;
 use Drupal\Core\Entity\EntityFieldManagerInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Entity\FieldableEntityInterface;
-use Drupal\Core\Entity\Query\QueryInterface;
 use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\FieldTypePluginManagerInterface;
@@ -124,10 +124,6 @@ class EntityResource {
    *
    * @param \Drupal\Core\Entity\EntityInterface $entity
    *   The loaded entity.
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request object.
-   * @param int $response_code
-   *   The response code. Defaults to 200.
    *
    * @return \Drupal\jsonapi\ResourceResponse
    *   The response.
@@ -135,20 +131,13 @@ class EntityResource {
    * @throws \Drupal\jsonapi\Exception\EntityAccessDeniedHttpException
    *   Thrown when access to the entity is not allowed.
    */
-  public function getIndividual(EntityInterface $entity, Request $request, $response_code = 200) {
-    $entity_access = $entity->access('view', NULL, TRUE);
-    if (!$entity_access->isAllowed()) {
-      $entity_label_access = $entity->access('view label', NULL, TRUE);
-      if (!$entity_label_access->isAllowed()) {
-        throw new EntityAccessDeniedHttpException($entity, $entity_access, '/data', 'The current user is not allowed to GET the selected resource.');
-      }
-      $entity = new LabelOnlyEntity($entity);
-    }
-    $response = $this->buildWrappedResponse($entity, $response_code);
-    $response->addCacheableDependency($entity_access);
-    if (isset($entity_label_access)) {
-      $response->addCacheableDependency($entity_label_access);
+  public function getIndividual(EntityInterface $entity) {
+    $entity = static::getAccessCheckedEntity($entity);
+    if ($entity instanceof EntityAccessDeniedHttpException) {
+      throw $entity;
     }
+    $response = $this->buildWrappedResponse($entity);
+    $response->addCacheableDependency($entity);
     return $response;
   }
 
@@ -313,13 +302,11 @@ class EntityResource {
    *
    * @param \Drupal\Core\Entity\EntityInterface $entity
    *   The loaded entity.
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request object.
    *
    * @return \Drupal\jsonapi\ResourceResponse
    *   The response.
    */
-  public function deleteIndividual(EntityInterface $entity, Request $request) {
+  public function deleteIndividual(EntityInterface $entity) {
     $entity->delete();
     return new ResourceResponse(NULL, 204);
   }
@@ -342,47 +329,9 @@ class EntityResource {
 
     $route_params = $request->attributes->get('_route_params');
     $params = isset($route_params['_json_api_params']) ? $route_params['_json_api_params'] : [];
+    $query = $this->getCollectionQuery($entity_type_id, $params);
     $query_cacheability = new CacheableMetadata();
-    $query = $this->filterQueryByBundle($this->resourceType, $this->getCollectionQuery($entity_type_id, $params));
-    $entity_collection = $this->doCollectionQuery($query, $query_cacheability);
-
-    // Calculate all the results and pass them to the EntityCollectionInterface.
-    if ($this->resourceType->includeCount()) {
-      $total_results = $this
-        ->getCollectionCountQuery($entity_type_id, $params)
-        ->execute();
-
-      $entity_collection->setTotalCount($total_results);
-    }
-
-    $response = $this->respondWithCollection($entity_collection, $entity_type_id);
-    // When a new change to any entity in the resource happens, we cannot ensure
-    // the validity of this cached list. Add the list tag to deal with that.
-    $list_tag = $this->entityTypeManager->getDefinition($entity_type_id)->getListCacheTags();
-    $response->getCacheableMetadata()->addCacheTags($list_tag);
-    // Ensure that any cacheability from query execution is applied.
-    $response->addCacheableDependency($query_cacheability);
 
-    return $response;
-  }
-
-  /**
-   * Executes a query, checks access and returns a loaded entity collection.
-   *
-   * @param \Drupal\Core\Entity\Query\QueryInterface $query
-   *   The query to execute.
-   * @param \Drupal\Core\Cache\CacheableMetadata $query_cacheability
-   *   A CacheableMetadata object to capture cacheability metadata generated by
-   *   the query execution. This can happen when cacheability is affected by a
-   *   hook_query_alter, for example.
-   *
-   * @return \Drupal\jsonapi\JsonApiResource\EntityCollection
-   *   A loaded entity collection that has been checked for access.
-   *
-   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
-   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
-   */
-  protected function doCollectionQuery(QueryInterface $query, CacheableMetadata $query_cacheability) {
     try {
       // Execute the query in a render context, to catch bubbled cacheability.
       // @see node_query_node_access_alter()
@@ -411,7 +360,7 @@ class EntityResource {
       }
     }
 
-    $storage = $this->entityTypeManager->getStorage($query->getEntityTypeId());
+    $storage = $this->entityTypeManager->getStorage($entity_type_id);
     // We request N+1 items to find out if there is a next page for the pager.
     // We may need to remove that extra item before loading the entities.
     $pager_size = $query->getMetaData('pager_size');
@@ -422,10 +371,23 @@ class EntityResource {
     // Each item of the collection data contains an array with 'entity' and
     // 'access' elements.
     $collection_data = $this->loadEntitiesWithAccess($storage, $results);
-    $entity_collection = new EntityCollection($collection_data, -1);
+    $entity_collection = new EntityCollection($collection_data);
     $entity_collection->setHasNextPage($has_next_page);
 
-    return $entity_collection;
+    // Calculate all the results and pass them to the EntityCollectionInterface.
+    if ($this->resourceType->includeCount()) {
+      $total_results = $this
+        ->getCollectionCountQuery($entity_type_id, $params)
+        ->execute();
+
+      $entity_collection->setTotalCount($total_results);
+    }
+
+    $response = $this->respondWithCollection($entity_collection, $entity_type_id);
+
+    $response->addCacheableDependency($query_cacheability);
+
+    return $response;
   }
 
   /**
@@ -442,19 +404,25 @@ class EntityResource {
   public function getRelated(FieldableEntityInterface $entity, $related_field) {
     /* @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $field_list */
     $field_list = $entity->get($this->resourceType->getInternalName($related_field));
-    $entity_type_id = array_reduce($this->resourceType->getRelatableResourceTypesByField($related_field), function ($entity_type_id, ResourceType $target_resource_type) {
-      assert(is_null($entity_type_id) || $entity_type_id === $target_resource_type->getEntityTypeId());
-      return $target_resource_type->getEntityTypeId();
-    }, NULL);
 
-    // Ensure access is respected for each targeted entity.
-    $entities = array_map([static::class, 'getAccessCheckedEntity'], $field_list->filterEmptyItems()->referencedEntities());
-    $entity_collection = new EntityCollection($entities, $field_list->getFieldDefinition()->getFieldStorageDefinition()->getCardinality());
-    $entity_collection->setHasNextPage(FALSE);
+    // Remove the entities pointing to a resource that may be disabled. Even
+    // though the normalizer skips disabled references, we can avoid unnecessary
+    // work by checking here too.
+    /* @var \Drupal\Core\Entity\EntityInterface[] $referenced_entities */
+    $referenced_entities = array_filter($field_list->filterEmptyItems()->referencedEntities(), function (EntityInterface $entity) {
+      return (bool) $this->resourceTypeRepository->get($entity->getEntityTypeId(), $entity->bundle());
+    });
 
-    $response = $this->respondWithCollection($entity_collection, $entity_type_id);
+    // Check access to each of the referenced entities.
+    $access_checked_entities = array_map(function (EntityInterface $entity) {
+      return static::getAccessCheckedEntity($entity);
+    }, $referenced_entities);
 
-    // Add the cacheable metadata from the host entity.
+    $entity_collection = new EntityCollection($access_checked_entities, $field_list->getFieldDefinition()->getFieldStorageDefinition()->getCardinality());
+    $response = $this->buildWrappedResponse($entity_collection);
+
+    // $response does not contain the entity list cache tag. We add the
+    // cacheable metadata for the finite list of entities in the relationship.
     $response->addCacheableDependency($entity);
 
     return $response;
@@ -467,15 +435,14 @@ class EntityResource {
    *   The requested entity.
    * @param string $related_field
    *   The related field name.
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request object.
    * @param int $response_code
    *   The response code. Defaults to 200.
    *
    * @return \Drupal\jsonapi\ResourceResponse
    *   The response.
    */
-  public function getRelationship(FieldableEntityInterface $entity, $related_field, Request $request, $response_code = 200) {
+  public function getRelationship(FieldableEntityInterface $entity, $related_field, $response_code = 200) {
+    assert(!$response_code instanceof Request);
     /* @var \Drupal\Core\Field\FieldItemListInterface $field_list */
     $field_list = $entity->get($this->resourceType->getInternalName($related_field));
     $response = $this->buildWrappedResponse($field_list, $response_code);
@@ -492,8 +459,6 @@ class EntityResource {
    * @param mixed $parsed_field_list
    *   The entity reference field list of items to add, or a response object in
    *   case of error.
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request object.
    *
    * @return \Drupal\jsonapi\ResourceResponse
    *   The response.
@@ -504,7 +469,7 @@ class EntityResource {
    * @throws \Symfony\Component\HttpKernel\Exception\ConflictHttpException
    *   Thrown when POSTing to a "to-one" relationship.
    */
-  public function createRelationship(EntityInterface $entity, $related_field, $parsed_field_list, Request $request) {
+  public function createRelationship(EntityInterface $entity, $related_field, $parsed_field_list) {
     $related_field = $this->resourceType->getInternalName($related_field);
     /* @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $parsed_field_list */
     if ($parsed_field_list instanceof Response) {
@@ -533,7 +498,7 @@ class EntityResource {
     $status = static::relationshipArityIsAffected($original_field_list, $field_list)
       ? 200
       : 204;
-    return $this->getRelationship($entity, $related_field, $request, $status);
+    return $this->getRelationship($entity, $related_field, $status);
   }
 
   /**
@@ -594,7 +559,7 @@ class EntityResource {
    * @return \Drupal\jsonapi\ResourceResponse
    *   The response.
    */
-  public function patchRelationship(EntityInterface $entity, $related_field, $parsed_field_list, Request $request) {
+  public function patchRelationship(EntityInterface $entity, $related_field, $parsed_field_list) {
     $related_field = $this->resourceType->getInternalName($related_field);
     if ($parsed_field_list instanceof Response) {
       // This usually means that there was an error, so there is no point on
@@ -613,7 +578,7 @@ class EntityResource {
     $this->{$method}($entity, $parsed_field_list);
     $this->validate($entity);
     $entity->save();
-    return $this->getRelationship($entity, $related_field, $request, 204);
+    return $this->getRelationship($entity, $related_field, 204);
   }
 
   /**
@@ -666,8 +631,6 @@ class EntityResource {
    * @param mixed $parsed_field_list
    *   The entity reference field list of items to add, or a response object in
    *   case of error.
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request object.
    *
    * @return \Drupal\jsonapi\ResourceResponse
    *   The response.
@@ -677,7 +640,7 @@ class EntityResource {
    * @throws \Symfony\Component\HttpKernel\Exception\ConflictHttpException
    *   Thrown when deleting a "to-one" relationship.
    */
-  public function deleteRelationship(EntityInterface $entity, $related_field, $parsed_field_list, Request $request = NULL) {
+  public function deleteRelationship(EntityInterface $entity, $related_field, $parsed_field_list) {
     if ($parsed_field_list instanceof Response) {
       // This usually means that there was an error, so there is no point on
       // processing further.
@@ -709,7 +672,7 @@ class EntityResource {
     // Save the entity and return the response object.
     $this->validate($entity);
     $entity->save();
-    return $this->getRelationship($entity, $related_field, $request, 204);
+    return $this->getRelationship($entity, $related_field, 204);
   }
 
   /**
@@ -724,6 +687,7 @@ class EntityResource {
    *   A new query.
    */
   protected function getCollectionQuery($entity_type_id, array $params) {
+    $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
     $entity_storage = $this->entityTypeManager->getStorage($entity_type_id);
 
     $query = $entity_storage->getQuery();
@@ -757,6 +721,14 @@ class EntityResource {
     $query->range($pagination->getOffset(), $pagination->getSize() + 1);
     $query->addMetaData('pager_size', (int) $pagination->getSize());
 
+    // Limit this query to the bundle type for this resource.
+    $bundle = $this->resourceType->getBundle();
+    if ($bundle && ($bundle_key = $entity_type->getKey('bundle'))) {
+      $query->condition(
+        $bundle_key, $bundle
+      );
+    }
+
     return $query;
   }
 
@@ -773,28 +745,7 @@ class EntityResource {
    */
   protected function getCollectionCountQuery($entity_type_id, array $params) {
     // Reset the range to get all the available results.
-    $collection_query = $this->getCollectionQuery($entity_type_id, $params);
-    return $this->filterQueryByBundle($this->resourceType, $collection_query)->range()->count();
-  }
-
-  /**
-   * Adds a bundle condition to an entity query for a given resource type.
-   *
-   * @param \Drupal\jsonapi\ResourceType\ResourceType $resource_type
-   *   A JSON API resource type.
-   * @param \Drupal\Core\Entity\Query\QueryInterface $query
-   *   The query to which the condition should be applied.
-   *
-   * @return \Drupal\Core\Entity\Query\QueryInterface
-   *   The filtered query.
-   */
-  protected function filterQueryByBundle(ResourceType $resource_type, QueryInterface $query) {
-    $entity_type = $this->entityTypeManager->getDefinition($resource_type->getEntityTypeId());
-    // Limit this query to the bundle type for this resource.
-    if (($bundle = $this->resourceType->getBundle()) && ($bundle_key = $entity_type->getKey('bundle'))) {
-      $query->condition($bundle_key, $bundle);
-    }
-    return $query;
+    return $this->getCollectionQuery($entity_type_id, $params)->range()->count();
   }
 
   /**
@@ -827,6 +778,12 @@ class EntityResource {
    */
   protected function respondWithCollection(EntityCollection $entity_collection, $entity_type_id) {
     $response = $this->buildWrappedResponse($entity_collection);
+
+    // When a new change to any entity in the resource happens, we cannot ensure
+    // the validity of this cached list. Add the list tag to deal with that.
+    $list_tag = $this->entityTypeManager->getDefinition($entity_type_id)
+      ->getListCacheTags();
+    $response->getCacheableMetadata()->addCacheTags($list_tag);
     foreach ($entity_collection as $entity) {
       $response->addCacheableDependency($entity);
     }
diff --git a/src/Controller/RequestHandler.php b/src/Controller/RequestHandler.php
index eb480b3..65e118a 100644
--- a/src/Controller/RequestHandler.php
+++ b/src/Controller/RequestHandler.php
@@ -131,8 +131,17 @@ class RequestHandler {
     $action = $this->action($request, $resource_type);
     $resource = $this->resourceFactory($resource_type);
 
+    $extra_parameters = [];
+
     // Only add the unserialized data if there is something there.
-    $extra_parameters = $unserialized ? [$unserialized, $request] : [$request];
+    if ($unserialized) {
+      $extra_parameters[] = $unserialized;
+    }
+
+    // Only add the request object for the methods that require it.
+    if (in_array($action, ['createIndividual', 'patchIndividual', 'getCollection', 'deleteRelationship'])) {
+      $extra_parameters[] = $request;
+    }
 
     return call_user_func_array([$resource, $action], array_merge($parameters, $extra_parameters));
   }
diff --git a/tests/src/Kernel/Controller/EntityResourceTest.php b/tests/src/Kernel/Controller/EntityResourceTest.php
index bdfccfb..3861c91 100644
--- a/tests/src/Kernel/Controller/EntityResourceTest.php
+++ b/tests/src/Kernel/Controller/EntityResourceTest.php
@@ -162,7 +162,7 @@ class EntityResourceTest extends JsonapiKernelTestBase {
    */
   public function testGetIndividual() {
     $entity_resource = $this->buildEntityResource('node', 'article');
-    $response = $entity_resource->getIndividual($this->node, new Request());
+    $response = $entity_resource->getIndividual($this->node);
     $this->assertInstanceOf(JsonApiDocumentTopLevel::class, $response->getResponseData());
     $this->assertEquals(1, $response->getResponseData()->getData()->id());
   }
@@ -176,7 +176,7 @@ class EntityResourceTest extends JsonapiKernelTestBase {
     $role->save();
     $entity_resource = $this->buildEntityResource('node', 'article');
     $this->setExpectedException(EntityAccessDeniedHttpException::class);
-    $entity_resource->getIndividual($this->node, new Request());
+    $entity_resource->getIndividual($this->node);
   }
 
   /**
@@ -370,6 +370,7 @@ class EntityResourceTest extends JsonapiKernelTestBase {
       ['node:1', 'user:1'],
       $response->getCacheableMetadata()->getCacheTags()
     );
+    $this->assertSame(['user.permissions'], $response->getCacheableMetadata()->getCacheContexts());
     // to-many relationship.
     $response = $entity_resource->getRelated($this->node4, 'field_relationships', new Request());
     $this->assertInstanceOf(JsonApiDocumentTopLevel::class, $response
@@ -381,6 +382,7 @@ class EntityResourceTest extends JsonapiKernelTestBase {
       ['node:1', 'node:2', 'node:3', 'node:4'],
       $response->getCacheableMetadata()->getCacheTags()
     );
+    $this->assertSame(['user.permissions'], $response->getCacheableMetadata()->getCacheContexts());
   }
 
   /**
@@ -391,7 +393,7 @@ class EntityResourceTest extends JsonapiKernelTestBase {
     $entity_resource = $this->buildEntityResource('node', 'article', [
       'uid' => [new ResourceType('user', 'user', NULL)],
     ]);
-    $response = $entity_resource->getRelationship($this->node, 'uid', new Request());
+    $response = $entity_resource->getRelationship($this->node, 'uid');
     $this->assertInstanceOf(JsonApiDocumentTopLevel::class, $response->getResponseData());
     $this->assertInstanceOf(
       EntityReferenceFieldItemListInterface::class,
