diff --git a/src/Plugin/views/argument/SearchApiFulltext.php b/src/Plugin/views/argument/SearchApiFulltext.php
index 7147f07..22a10e7 100644
--- a/src/Plugin/views/argument/SearchApiFulltext.php
+++ b/src/Plugin/views/argument/SearchApiFulltext.php
@@ -10,6 +10,8 @@ namespace Drupal\search_api\Plugin\views\argument;
 use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\search_api\Entity\Index;
+use Drupal\search_api\Plugin\views\query\SearchApiQuery;
 
 /**
  * Defines a contextual filter for doing fulltext searches.
@@ -106,7 +108,17 @@ class SearchApiFulltext extends SearchApiArgument {
    */
   protected function getFulltextFields() {
     $fields = array();
-    $index = $this->query->getIndex();
+
+    if (!empty($this->query)) {
+      $index = $this->query->getIndex();
+    }
+    else {
+      $index = SearchApiQuery::getIndexFromTable($this->table);
+    }
+
+    if (!$index) {
+      return array();
+    }
 
     $fields_info = $index->getFields();
     foreach ($index->getFulltextFields() as $field_id) {
diff --git a/src/Plugin/views/display/FacetsBlock.php b/src/Plugin/views/display/FacetsBlock.php
index 31931a2..f98a011 100644
--- a/src/Plugin/views/display/FacetsBlock.php
+++ b/src/Plugin/views/display/FacetsBlock.php
@@ -79,7 +79,7 @@ class FacetsBlock extends Block {
   public function buildOptionsForm(&$form, FormStateInterface $form_state) {
     parent::buildOptionsForm($form, $form_state);
 
-    if (!$this->getSearchIndexId()) {
+    if (!$this->isTableValid()) {
       return;
     }
 
@@ -122,7 +122,7 @@ class FacetsBlock extends Block {
    * {@inheritdoc}
    */
   public function validateOptionsForm(&$form, FormStateInterface $form_state) {
-    if (!$this->getSearchIndexId()) {
+    if (!$this->isTableValid()) {
       $form_state->setError($form, $this->t('The "Facets block" display can only be used with base tables based on search indexes.'));
     }
   }
@@ -184,11 +184,9 @@ class FacetsBlock extends Block {
    */
   protected function getFieldOptions() {
     if (!isset($this->field_options)) {
-      $index_id = $this->getSearchIndexId();
-      /** @var \Drupal\search_api\IndexInterface $index */
-      $index = NULL;
-      if (!($index_id && ($index = Index::load($index_id)))) {
-        $table = $this->view->storage->get('base_table');
+      $table = $this->view->storage->get('base_table');
+      $index = SearchApiQuery::getIndexFromTable($table);
+      if (!$index) {
         $views_data = Views::viewsData($table);
         $table = empty($views_data['table']['base']['title']) ? $table : $views_data['table']['base']['title'];
         throw new SearchApiException(SafeMarkup::format('The "Facets block" display cannot be used with a view for @base_table. Please only use this display with base tables representing Search API indexes.', array('@base_table' => $table)));
@@ -368,16 +366,12 @@ class FacetsBlock extends Block {
   /**
    * Checks whether the current view has a correct base table.
    *
-   * @return string|null
-   *   If the current view has a Search API base table, the associated search
-   *   index's ID. NULL otherwise.
+   * @return bool
+   *   TRUE if the current view has a Search API base table, FALSE otherwise.
    */
-  protected function getSearchIndexId() {
+  protected function isTableValid() {
     $table = $this->view->storage->get('base_table');
-    if (substr($table, 0, 17) == 'search_api_index_') {
-      return substr($table, 17);
-    }
-    return NULL;
+    return (bool) SearchApiQuery::getIndexFromTable($table);
   }
 
 }
diff --git a/src/Plugin/views/query/SearchApiQuery.php b/src/Plugin/views/query/SearchApiQuery.php
index 9a01ab1..8261ad8 100644
--- a/src/Plugin/views/query/SearchApiQuery.php
+++ b/src/Plugin/views/query/SearchApiQuery.php
@@ -9,6 +9,7 @@ namespace Drupal\search_api\Plugin\views\query;
 
 use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
 use Drupal\search_api\Entity\Index;
@@ -106,22 +107,41 @@ class SearchApiQuery extends QueryPluginBase {
   public $group_operator = 'AND';
 
   /**
+   * Loads the search index belonging to the given Views base table.
+   *
+   * @param string $table
+   *   The Views base table ID.
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   (optional) The entity manager to use.
+   *
+   * @return \Drupal\search_api\IndexInterface|null
+   *   The requested search index, or NULL if it could not be found and loaded.
+   */
+  public static function getIndexFromTable($table, EntityManagerInterface $entity_manager = NULL) {
+    if (substr($table, 0, 17) == 'search_api_index_') {
+      $index_id = substr($table, 17);
+      if ($entity_manager) {
+        return $entity_manager->getStorage('search_api_index')->load($index_id);
+      }
+      return Index::load($index_id);
+    }
+    return NULL;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
     try {
       parent::init($view, $display, $options);
       $this->fields = array();
-      if (substr($view->storage->get('base_table'), 0, 17) == 'search_api_index_') {
-        $id = substr($view->storage->get('base_table'), 17);
-        $this->index = Index::load($id);
-        $this->query = $this->index->query(array(
-          'parse mode' => $this->options['parse_mode'],
-        ));
-      }
-      else {
+      $this->index = self::getIndexFromTable($view->storage->get('base_table'));
+      if (!$this->index) {
         $this->abort(SafeMarkup::format('View %view is not based on Search API but tries to use its query plugin.', array('%view' => $view->storage->label())));
       }
+      $this->query = $this->index->query(array(
+        'parse mode' => $this->options['parse_mode'],
+      ));
     }
     catch (\Exception $e) {
       $this->abort($e->getMessage());
diff --git a/src/Plugin/views/row/SearchApiRow.php b/src/Plugin/views/row/SearchApiRow.php
index 029ac47..2d9cccb 100644
--- a/src/Plugin/views/row/SearchApiRow.php
+++ b/src/Plugin/views/row/SearchApiRow.php
@@ -12,6 +12,7 @@ use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Logger\LoggerChannelInterface;
 use Drupal\Core\TypedData\ComplexDataInterface;
+use Drupal\search_api\Plugin\views\query\SearchApiQuery;
 use Drupal\search_api\SearchApiException;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\Plugin\views\row\RowPluginBase;
@@ -119,11 +120,10 @@ class SearchApiRow extends RowPluginBase {
     parent::init($view, $display, $options);
 
     $base_table = $view->storage->get('base_table');
-    if (substr($base_table, 0, 17) !== 'search_api_index_') {
+    $this->index = SearchApiQuery::getIndexFromTable($base_table, $this->getEntityManager());
+    if (!$this->index) {
       throw new \InvalidArgumentException(SafeMarkup::format('View %view is not based on Search API but tries to use its row plugin.', array('%view' => $view->storage->label())));
     }
-    $index_id = substr($base_table, 17);
-    $this->index = $this->getEntityManager()->getStorage('search_api_index')->load($index_id);
   }
 
   /**
