diff --git a/includes/common.inc b/includes/common.inc
index 31923f2..c130227 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -7833,6 +7833,55 @@ 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 $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..c9f1fdf 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,8 +1103,11 @@ 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);
+  $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);
+  }
 
   $build = array(
     '#sorted' => TRUE,
diff --git a/modules/node/node.module b/modules/node/node.module
index f20c229..af3ed56 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,8 +2658,12 @@ 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);
+  $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);
+  }
+
   $build = array();
   foreach ($nodes as $node) {
     $build['nodes'][$node->nid] = node_view($node, $view_mode, $langcode);
diff --git a/modules/node/node.test b/modules/node/node.test
index 0256fec..d81d26d 100644
--- a/modules/node/node.test
+++ b/modules/node/node.test
@@ -2698,3 +2698,60 @@ class NodeEntityViewModeAlterTest extends NodeWebTestCase {
     $this->assertEqual($build['#view_mode'], 'teaser', 'The view mode has correctly been set to teaser.');
   }
 }
+
+/**
+ * Tests changing view mode for nodes when teaser display shows a field which is missing on the default display.
+ */
+class NodeEntityViewModeAlterMinimalDefaultDisplayTest extends NodeWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Node entity view mode minimal default display',
+      'description' => 'Test changing view mode when teaser display shows a field which is missing on the default display.',
+      'group' => 'Node'
+    );
+  }
+
+  function setUp() {
+    parent::setUp(array('node_test'));
+
+    // Hide the tags field on the default display
+    $instance = field_read_instance('node', 'field_tags', 'article');
+    $instance['display']['default']['type'] = 'hidden';
+    field_update_instance($instance);
+  }
+
+  /**
+   * Create a "Article" node and verify its consistency in the database.
+   */
+  function testNodeViewModeChange() {
+    $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]"] = 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["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..1045c2f 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -771,8 +771,11 @@ 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);
+  $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);
+  }
   $build = array();
   foreach ($terms as $term) {
     $build['taxonomy_terms'][$term->tid] = taxonomy_term_view($term, $view_mode, $langcode);
@@ -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 bff6f76..7483131 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -2596,12 +2596,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);
