diff --git a/includes/common.inc b/includes/common.inc
index 9283766..d4a5429 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -7860,6 +7860,56 @@ function entity_prepare_view($entity_type, $entities, $langcode = NULL) {
 }
 
 /**
+ * Invoke hook_entity_view_mode_alter().
+ *
+ * If adding a new entity similar to nodes, comments or users, you should invoke
+ * this function during the ENTITY_build_content() or ENTITY_view_multiple()
+ * phases of rendering to allow other modules to alter the view mode during this
+ * phase. This function needs to be called before field_attach_prepare_view() to
+ * ensure that the correct content is loaded by field API.
+ *
+ * @param $entity_type
+ *   The type of entity, i.e. 'node', 'user'.
+ * @param $entities
+ *   The entity objects which are being prepared for view, keyed by object ID.
+ * @param $view_mode
+ *   The original view mode e.g. 'full', 'teaser'...
+ * @param $langcode
+ *   (optional) A language code to be used for rendering. Defaults to the global
+ *   content language of the current request.
+ * @return
+ *   An associative array with arrays of entities keyed by view mode.
+ *
+ * @see hook_entity_view_mode_alter()
+ */
+function entity_view_mode_prepare($entity_type, $entities, $view_mode, $langcode = NULL) {
+  if (!isset($langcode)) {
+    $langcode = $GLOBALS['language_content']->language;
+  }
+
+  // To ensure hooks are never run after field_attach_prepare_view() only
+  // process items without the entity_view_prepared flag.
+  $entities_by_view_mode = array();
+  foreach ($entities as $id => $entity) {
+    $entity_view_mode = $view_mode;
+    if (empty($entity->entity_view_prepared)) {
+
+      // Allow modules to change the view mode.
+      $context = array(
+        'entity_type' => $entity_type,
+        'entity' => $entity,
+        'langcode' => $langcode,
+      );
+      drupal_alter('entity_view_mode', $entity_view_mode, $context);
+    }
+
+    $entities_by_view_mode[$entity_view_mode][$id] = $entity;
+  }
+
+  return $entities_by_view_mode;
+}
+
+/**
  * Returns the URI elements of an entity.
  *
  * @param $entity_type
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index a83069f..950e087 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -993,12 +993,7 @@ function comment_build_content($comment, $node, $view_mode = 'full', $langcode =
   $comment->content = array();
 
   // Allow modules to change the view mode.
-  $context = array(
-    'entity_type' => 'comment',
-    'entity' => $comment,
-    'langcode' => $langcode,
-  );
-  drupal_alter('entity_view_mode', $view_mode, $context);
+  $view_mode = key(entity_view_mode_prepare('comment', array($comment->cid => $comment), $view_mode, $langcode));
 
   // Build fields content.
   field_attach_prepare_view('comment', array($comment->cid => $comment), $view_mode, $langcode);
@@ -1108,16 +1103,17 @@ function comment_links($comment, $node) {
  *   An array in the format expected by drupal_render().
  */
 function comment_view_multiple($comments, $node, $view_mode = 'full', $weight = 0, $langcode = NULL) {
-  field_attach_prepare_view('comment', $comments, $view_mode, $langcode);
-  entity_prepare_view('comment', $comments, $langcode);
-
-  $build = array(
-    '#sorted' => TRUE,
-  );
-  foreach ($comments as $comment) {
-    $build[$comment->cid] = comment_view($comment, $node, $view_mode, $langcode);
-    $build[$comment->cid]['#weight'] = $weight;
-    $weight++;
+  $build = array();
+  $comments_by_view_mode = entity_view_mode_prepare('comment', $comments, $view_mode, $langcode);
+  foreach ($comments_by_view_mode as $view_mode => $comments) {
+    field_attach_prepare_view('comment', $comments, $view_mode, $langcode);
+    entity_prepare_view('comment', $comments, $langcode);
+
+    foreach ($comments as $comment) {
+      $build[$comment->cid] = comment_view($comment, $node, $view_mode, $langcode);
+      $build[$comment->cid]['#weight'] = $weight;
+      $weight++;
+    }
   }
   return $build;
 }
diff --git a/modules/node/node.module b/modules/node/node.module
index f20c229..4937212 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -1399,12 +1399,7 @@ function node_build_content($node, $view_mode = 'full', $langcode = NULL) {
   $node->content = array();
 
   // Allow modules to change the view mode.
-  $context = array(
-    'entity_type' => 'node',
-    'entity' => $node,
-    'langcode' => $langcode,
-  );
-  drupal_alter('entity_view_mode', $view_mode, $context);
+  $view_mode = key(entity_view_mode_prepare('node', array($node->nid => $node), $view_mode, $langcode));
 
   // The 'view' hook can be implemented to overwrite the default function
   // to display nodes.
@@ -2663,15 +2658,18 @@ function node_feed($nids = FALSE, $channel = array()) {
  *   An array in the format expected by drupal_render().
  */
 function node_view_multiple($nodes, $view_mode = 'teaser', $weight = 0, $langcode = NULL) {
-  field_attach_prepare_view('node', $nodes, $view_mode, $langcode);
-  entity_prepare_view('node', $nodes, $langcode);
   $build = array();
-  foreach ($nodes as $node) {
-    $build['nodes'][$node->nid] = node_view($node, $view_mode, $langcode);
-    $build['nodes'][$node->nid]['#weight'] = $weight;
-    $weight++;
+  $nodes_by_view_mode = entity_view_mode_prepare('node', $nodes, $view_mode, $langcode);
+  foreach ($nodes_by_view_mode as $view_mode => $nodes) {
+    field_attach_prepare_view('node', $nodes, $view_mode, $langcode);
+    entity_prepare_view('node', $nodes, $langcode);
+
+    foreach ($nodes as $node) {
+      $build['nodes'][$node->nid] = node_view($node, $view_mode, $langcode);
+      $build['nodes'][$node->nid]['#weight'] = $weight;
+      $weight++;
+    }
   }
-  $build['nodes']['#sorted'] = TRUE;
   return $build;
 }
 
diff --git a/modules/node/node.test b/modules/node/node.test
index b1d78fa..0009f8a 100644
--- a/modules/node/node.test
+++ b/modules/node/node.test
@@ -2735,8 +2735,8 @@ class NodeEntityViewModeAlterTest extends NodeWebTestCase {
     $edit = array();
     $langcode = LANGUAGE_NONE;
     $edit["title"] = $this->randomName(8);
-    $edit["body[$langcode][0][value]"] = t('Data that should appear only in the body for the node.');
-    $edit["body[$langcode][0][summary]"] = t('Extra data that should appear only in the teaser for the node.');
+    $edit["body[$langcode][0][value]"] = 'Data that should appear only in the body for the node.';
+    $edit["body[$langcode][0][summary]"] = 'Extra data that should appear only in the teaser for the node.';
     $this->drupalPost('node/add/page', $edit, t('Save'));
 
     $node = $this->drupalGetNodeByTitle($edit["title"]);
@@ -2754,4 +2754,43 @@ class NodeEntityViewModeAlterTest extends NodeWebTestCase {
     $build = node_view($node);
     $this->assertEqual($build['#view_mode'], 'teaser', 'The view mode has correctly been set to teaser.');
   }
+
+  /**
+   * Tests fields that were previously hidden when the view mode is changed.
+   */
+  function testNodeViewModeChangeHiddenField() {
+    // Hide the tags field on the default display
+    $instance = field_info_instance('node', 'field_tags', 'article');
+    $instance['display']['default']['type'] = 'hidden';
+    field_update_instance($instance);
+
+    $web_user = $this->drupalCreateUser(array('create article content', 'edit own article content'));
+    $this->drupalLogin($web_user);
+
+    // Create a node.
+    $edit = array();
+    $langcode = LANGUAGE_NONE;
+    $edit["title"] = $this->randomName(8);
+    $edit["body[$langcode][0][value]"] = 'Data that should appear only in the body for the node.';
+    $edit["body[$langcode][0][summary]"] = 'Extra data that should appear only in the teaser for the node.';
+    $edit["field_tags[$langcode]"] = 'Extra tag';
+    $this->drupalPost('node/add/article', $edit, t('Save'));
+
+    $node = $this->drupalGetNodeByTitle($edit["title"]);
+
+    // Set the flag to alter the view mode and view the node.
+    variable_set('node_test_change_view_mode', 'teaser');
+    $this->drupalGet('node/' . $node->nid);
+
+    // Check that teaser mode is viewed.
+    $this->assertText('Extra data that should appear only in the teaser for the node.', 'Teaser text present');
+    // Make sure body text is not present.
+    $this->assertNoText('Data that should appear only in the body for the node.', 'Body text not present');
+    // Make sure tags are present.
+    $this->assertText('Extra tag', 'Taxonomy term present');
+
+    // Test that the correct build mode has been set.
+    $build = node_view($node);
+    $this->assertEqual($build['#view_mode'], 'teaser', 'The view mode has correctly been set to teaser.');
+  }
 }
diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module
index 7ad28e9..5101a68 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -771,15 +771,18 @@ function taxonomy_term_show($term) {
  *   An array in the format expected by drupal_render().
  */
 function taxonomy_term_view_multiple($terms, $view_mode = 'teaser', $weight = 0, $langcode = NULL) {
-  field_attach_prepare_view('taxonomy_term', $terms, $view_mode, $langcode);
-  entity_prepare_view('taxonomy_term', $terms, $langcode);
   $build = array();
-  foreach ($terms as $term) {
-    $build['taxonomy_terms'][$term->tid] = taxonomy_term_view($term, $view_mode, $langcode);
-    $build['taxonomy_terms'][$term->tid]['#weight'] = $weight;
-    $weight++;
+  $terms_by_view_mode = entity_view_mode_prepare('taxonomy_term', $terms, $view_mode, $langcode);
+  foreach ($terms_by_view_mode as $view_mode => $terms) {
+    field_attach_prepare_view('taxonomy_term', $terms, $view_mode, $langcode);
+    entity_prepare_view('taxonomy_term', $terms, $langcode);
+
+    foreach ($terms as $term) {
+      $build['taxonomy_terms'][$term->tid] = taxonomy_term_view($term, $view_mode, $langcode);
+      $build['taxonomy_terms'][$term->tid]['#weight'] = $weight;
+      $weight++;
+    }
   }
-  $build['taxonomy_terms']['#sorted'] = TRUE;
   return $build;
 }
 
@@ -812,12 +815,7 @@ function taxonomy_term_build_content($term, $view_mode = 'full', $langcode = NUL
   $term->content = array();
 
   // Allow modules to change the view mode.
-  $context = array(
-    'entity_type' => 'taxonomy_term',
-    'entity' => $term,
-    'langcode' => $langcode,
-  );
-  drupal_alter('entity_view_mode', $view_mode, $context);
+  $view_mode = key(entity_view_mode_prepare('taxonomy_term', array($term->tid => $term), $view_mode, $langcode));
 
   // Add the term description if the term has one and it is visible.
   $type = 'taxonomy_term';
diff --git a/modules/user/user.module b/modules/user/user.module
index 06233fc..308c3b7 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -2604,12 +2604,7 @@ function user_build_content($account, $view_mode = 'full', $langcode = NULL) {
   $account->content = array();
 
   // Allow modules to change the view mode.
-  $context = array(
-    'entity_type' => 'user',
-    'entity' => $account,
-    'langcode' => $langcode,
-  );
-  drupal_alter('entity_view_mode', $view_mode, $context);
+  $view_mode = key(entity_view_mode_prepare('user', array($account->uid => $account), $view_mode, $langcode));
 
   // Build fields content.
   field_attach_prepare_view('user', array($account->uid => $account), $view_mode, $langcode);
