diff --git a/lib/Drupal/views/Tests/ViewStorageTest.php b/lib/Drupal/views/Tests/ViewStorageTest.php
new file mode 100644
index 0000000..1f93e60
--- /dev/null
+++ b/lib/Drupal/views/Tests/ViewStorageTest.php
@@ -0,0 +1,163 @@
+<?php
+
+/**
+ * Definition of Drupal\views\Tests\ViewStorageTest.
+ */
+
+namespace Drupal\views\Tests;
+
+use Drupal\simpletest\WebTestBase;
+use Drupal\views\ViewStorageController;
+use Drupal\views\View;
+use Drupal\views\ViewDisplay;
+
+/**
+ * Tests that functionality of the the ViewStorageController.
+ */
+class ViewStorageTest extends WebTestBase {
+
+  /**
+   * Properties that should be stored in the configuration.
+   *
+   * @var array
+   */
+  protected $config_properties = array(
+    'disabled',
+    'api_version',
+    'name',
+    'description',
+    'tag',
+    'base_table',
+    'human_name',
+    'core',
+    'display',
+  );
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('views');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Views configurable CRUD tests',
+      'description' => 'Test the CRUD functionality for ViewStorage.',
+      'group' => 'Views',
+    );
+  }
+
+  /**
+   * Tests CRUD operations.
+   */
+  function testConfigurableCRUD() {
+
+    // Get the Configurable information and controller.
+    $info = entity_get_info('view');
+    $controller = entity_get_controller('view');
+
+    // Confirm that an info array has been returned.
+    $this->assertTrue(!empty($info) && is_array($info), 'The View  info array is loaded.');
+
+    // Confirm we have the correct controller class.
+    $this->assertTrue($controller instanceof ViewStorageController, 'The correct controller is loaded.');
+
+    // Load a single Configurable object from the controller.
+    $load = $controller->load(array('archive'));
+    $view = reset($load);
+
+    // Confirm that an actual view object is loaded and that it returns all of
+    // expected properties.
+    $this->assertTrue($view instanceof View, 'Single View instance loaded.');
+    foreach ($this->config_properties as $property) {
+      $this->assertTrue(isset($view->{$property}), format_string('Property: @property loaded onto View.', array('@property' => $property)));
+    }
+
+    // Check the displays have been loaded correctly from config display data.
+    $expected_displays = array('default', 'page', 'block');
+    $this->assertEqual(array_keys($view->display), $expected_displays, 'The correct display names are present.');
+
+    // Check each ViewDisplay object and confirm that it has the correct key.
+    foreach ($view->display as $key => $display) {
+      $this->assertTrue($display instanceof ViewDisplay, format_string('Display: @display is instance of ViewDisplay.', array('@display' => $key)));
+      $this->assertEqual($key, $display->id, 'The display has the correct ID.');
+      // Confirm that the display options array exists.
+      $display_options = $display->display_options;
+      $this->assertTrue(!empty($display_options) && is_array($display_options), 'Display options exist.');
+    }
+
+    // Fetch data for all Configurable objects and default view configurations.
+    $all_configurables = $controller->load();
+    $all_config = config_get_storage_names_with_prefix('views.view');
+
+    // Remove the 'views.view.' prefix from config names for comparision with
+    // loaded Configurable objects.
+    $prefix_map = function ($value) {
+      $parts = explode('.', $value);
+      return end($parts);
+    };
+
+    // Check that the correct number of Configurable objects have been loaded.
+    $count = count($all_configurables);
+    $this->assertEqual($count, count($all_config), format_string('The array of all @count Configurable objects is loaded.', array('@count' => $count)));
+
+    // Check that all of these machine names match.
+    $this->assertIdentical(array_keys($all_configurables), array_map($prefix_map, $all_config), 'All loaded elements match.');
+
+    // Create a new View instance with empty values.
+    $created = $controller->create(array());
+
+    $this->assertTrue($created instanceof View, 'Created object is a View.');
+    // Check that the View contains all of the properties.
+    foreach ($this->config_properties as $property) {
+      $this->assertTrue(isset($view->{$property}), format_string('Property: @property created on View.', array('@property' => $property)));
+    }
+
+    // Create a new View instance with config values.
+    $values = config('views.view.archive')->get();
+    $created = $controller->create($values);
+
+    $this->assertTrue($created instanceof View, 'Created object is a View.');
+    // Check that the View contains all of the properties.
+    $properties = $this->config_properties;
+    array_pop($properties);
+
+    // Test all properties except displays.
+    foreach ($properties as $property) {
+      $this->assertTrue(isset($created->{$property}), format_string('Property: @property created on View.', array('@property' => $property)));
+      $this->assertIdentical($values[$property], $created->{$property}, format_string('Property value: @property matches configuration value.', array('@property' => $property)));
+    }
+
+    // Test created displays.
+    foreach ($created->display as $key => $display) {
+      $this->assertTrue($display instanceof ViewDisplay, format_string('Display @display is an instance of ViewDisplay.', array('@display' => $key)));
+    }
+
+    // Save the newly created view, but modify the name.
+    $created->set('name', 'archive_copy');
+    $created->set('tag', 'changed');
+    $created->save();
+
+    // Load the newly saved config.
+    $config = config('views.view.archive_copy');
+    $this->assertFalse($config->isNew(), 'New config has been loaded.');
+
+    $this->assertEqual($created->tag, $config->get('tag'), 'A changed value has been saved.');
+
+    // Change a value and save.
+    $view->tag = 'changed';
+    $view->save();
+
+    // Check value have been written to config.
+    $config = config('views.view.archive')->get();
+    $this->assertEqual($view->tag, $config['tag'], 'View property saved to config.');
+
+    // Delete the config.
+    $created->delete();
+    $config = config('views.view.archive_copy');
+
+    $this->assertTrue($config->isNew(), 'Deleted config is now new.');
+  }
+
+}
diff --git a/lib/Drupal/views/View.php b/lib/Drupal/views/View.php
index 80d7d94..ca6babd 100644
--- a/lib/Drupal/views/View.php
+++ b/lib/Drupal/views/View.php
@@ -21,9 +21,7 @@ use Drupal\views\Plugin\Type\ViewsPluginManager;
  * An object to contain all of the data to generate a view, plus the member
  * functions to build the view query, execute the query and render the output.
  */
-class View extends ViewsDbObject {
-
-  var $db_table = 'views_view';
+class View extends ViewStorage {
 
   var $base_table = 'node';
 
@@ -37,13 +35,6 @@ class View extends ViewsDbObject {
   var $name = "";
 
   /**
-   * The id of the view, which is used only for views in the database.
-   *
-   * @var number
-   */
-  var $vid;
-
-  /**
    * The description of the view, which is used only in the interface.
    *
    * @var string
@@ -276,17 +267,6 @@ class View extends ViewsDbObject {
   protected $response = NULL;
 
   /**
-   * Constructor
-   */
-  function __construct() {
-    parent::init();
-    // Make sure all of our sub objects are arrays.
-    foreach ($this->db_objects() as $key => $object) {
-      $this->$key = array();
-    }
-  }
-
-  /**
    * Perform automatic updates when loading or importing a view.
    *
    * Over time, some things about Views or Drupal data has changed.
@@ -309,14 +289,6 @@ class View extends ViewsDbObject {
   }
 
   /**
-   * Returns the complete list of dependent objects in a view, for the purpose
-   * of initialization and loading/saving to/from the database.
-   */
-  static function db_objects() {
-    return array('display' => 'Display');
-  }
-
-  /**
    * Set the arguments that come to this view. Usually from the URL
    * but possibly from elsewhere.
    */
@@ -1804,186 +1776,6 @@ class View extends ViewsDbObject {
   }
 
   /**
-   * Static factory method to load a list of views based upon a $where clause.
-   *
-   * Although this method could be implemented to simply iterate over views::load(),
-   * that would be very slow.  Buiding the views externally from unified queries is
-   * much faster.
-   */
-  static function load_views() {
-    $result = db_query("SELECT DISTINCT v.* FROM {views_view} v");
-    $views = array();
-
-    // Load all the views.
-    foreach ($result as $data) {
-      $view = new View();
-      $view->load_row($data);
-      $view->loaded = TRUE;
-      $view->type = t('Normal');
-      $views[$view->name] = $view;
-      $names[$view->vid] = $view->name;
-    }
-
-    // Stop if we didn't get any views.
-    if (!$views) {
-      return array();
-    }
-
-    // Now load all the subtables:
-    foreach (View::db_objects() as $key => $object) {
-      $table_name = "views_" . $key;
-      $object_name = "Views$object";
-      $result = db_query("SELECT * FROM {{$table_name}} WHERE vid IN (:vids) ORDER BY vid, position",
-        array(':vids' => array_keys($names)));
-
-      foreach ($result as $data) {
-        $object = new $object_name(FALSE);
-        $object->load_row($data);
-
-        // Because it can get complicated with this much indirection,
-        // make a shortcut reference.
-        $location = &$views[$names[$object->vid]]->$key;
-
-        // If we have a basic id field, load the item onto the view based on
-        // this ID, otherwise push it on.
-        if (!empty($object->id)) {
-          $location[$object->id] = $object;
-        }
-        else {
-          $location[] = $object;
-        }
-      }
-    }
-    return $views;
-  }
-
-  /**
-   * Save the view to the database. If the view does not already exist,
-   * A vid will be assigned to the view and also returned from this function.
-   */
-  function save() {
-    if ($this->vid == 'new') {
-      $this->vid = NULL;
-    }
-    // If there is no vid, check if a view with this machine name already exists.
-    elseif (empty($this->vid)) {
-      $vid = db_query("SELECT vid from {views_view} WHERE name = :name", array(':name' => $this->name))->fetchField();
-      $this->vid = $vid ? $vid : NULL;
-    }
-
-    $transaction = db_transaction();
-
-    try {
-      // If we have no vid or our vid is a string, this is a new view.
-      if (!empty($this->vid)) {
-        // remove existing table entries
-        foreach ($this->db_objects() as $key => $object) {
-          db_delete('views_' . $key)
-            ->condition('vid', $this->vid)
-            ->execute();
-        }
-      }
-
-      $this->save_row(!empty($this->vid) ? 'vid' : FALSE);
-
-      // Save all of our subtables.
-      foreach ($this->db_objects() as $key => $object) {
-        $this->_save_rows($key);
-      }
-    }
-    catch (Exception $e) {
-      $transaction->rollback();
-      watchdog_exception('views', $e);
-      throw $e;
-    }
-
-    $this->save_locale_strings();
-
-    // Clear caches.
-    views_invalidate_cache();
-
-    // @todo Remove this.
-    // Explicitly rebuild the menu.
-    menu_router_rebuild();
-  }
-
-  /**
-   * Save a row to the database for the given key, which is one of the
-   * keys from View::db_objects()
-   */
-  function _save_rows($key) {
-    $count = 0;
-    foreach ($this->$key as $position => $object) {
-      $object->position = ++$count;
-      $object->vid = $this->vid;
-      $object->save_row();
-    }
-  }
-
-  /**
-   * Delete the view from the database.
-   */
-  function delete($clear = TRUE) {
-    if (empty($this->vid)) {
-      return;
-    }
-
-    db_delete('views_view')
-      ->condition('vid', $this->vid)
-      ->execute();
-    // Delete from all of our subtables as well.
-    foreach ($this->db_objects() as $key => $object) {
-      db_delete('views_'. $key)
-        ->condition('vid', $this->vid)
-        ->execute();
-    }
-
-    cache('cache_views')->delete('views_query:' . $this->name);
-
-    if ($clear) {
-      // Clear caches.
-      views_invalidate_cache();
-    }
-  }
-
-  /**
-   * Export a view as PHP code.
-   */
-  function export($indent = '') {
-    $this->init_display();
-    $this->init_query();
-    $output = '';
-    $output .= $this->export_row('view', $indent);
-    // Set the API version
-    $output .= $indent . '$view->api_version = \'' . views_api_version() . "';\n";
-    $output .= $indent . '$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */' . "\n";
-
-    foreach ($this->display as $id => $display) {
-      $output .= "\n" . $indent . "/* Display: $display->display_title */\n";
-      $output .= $indent . '$handler = $view->new_display(' . ctools_var_export($display->display_plugin, $indent) . ', ' . ctools_var_export($display->display_title, $indent) . ', \'' . $id . "');\n";
-      if (empty($display->handler)) {
-        // @todo -- probably need a method of exporting broken displays as
-        // they may simply be broken because a module is not installed. That
-        // does not invalidate the display.
-        continue;
-      }
-
-      $output .= $display->handler->export_options($indent, '$handler->options');
-    }
-
-    // Give the localization system a chance to export translatables to code.
-    if ($this->init_localization()) {
-      $this->export_locale_strings('export');
-      $translatables = $this->localization_plugin->export_render($indent);
-      if (!empty($translatables)) {
-        $output .= $translatables;
-      }
-    }
-
-    return $output;
-  }
-
-  /**
    * Make a copy of this view that has been sanitized of all database IDs
    * and handlers and other stuff.
    *
diff --git a/lib/Drupal/views/ViewDisplay.php b/lib/Drupal/views/ViewDisplay.php
new file mode 100644
index 0000000..1e374d4
--- /dev/null
+++ b/lib/Drupal/views/ViewDisplay.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\views\ViewDisplay.
+ */
+
+namespace Drupal\views;
+
+/**
+ * A display type in a view.
+ *
+ * This is just the database storage mechanism, and isn't terribly important
+ * to the behavior of the display at all.
+ */
+class ViewDisplay {
+
+  /**
+   * The display handler itself, which has all the methods.
+   *
+   * @var views_plugin_display
+   */
+  public $handler;
+
+  /**
+   * Stores all options of the display, like fields, filters etc.
+   *
+   * @var array
+   */
+  public $display_options;
+
+  function __construct(array $display_options = array()) {
+    if (!empty($display_options)) {
+      $this->display_options = $display_options['display_options'];
+      $this->display_plugin = $display_options['display_plugin'];
+      $this->id = $display_options['id'];
+      $this->display_title = $display_options['display_title'];
+    }
+  }
+
+}
diff --git a/lib/Drupal/views/ViewsDbObject.php b/lib/Drupal/views/ViewStorage.php
similarity index 60%
rename from lib/Drupal/views/ViewsDbObject.php
rename to lib/Drupal/views/ViewStorage.php
index ba3a9a0..3d87285 100644
--- a/lib/Drupal/views/ViewsDbObject.php
+++ b/lib/Drupal/views/ViewStorage.php
@@ -2,171 +2,24 @@
 
 /**
  * @file
- * Definition of Drupal\views\ViewsDbObject.
+ * Definition of Drupal\views\ViewStorage.
  */
 
 namespace Drupal\views;
 
-/**
- * Base class for views' database objects.
- */
-class ViewsDbObject {
+use Drupal\config\ConfigurableBase;
 
-  public $db_table;
-
-  /**
-   * Initialize this object, setting values from schema defaults.
-   *
-   * @param $init
-   *   If an array, this is a set of values from db_fetch_object to
-   *   load. Otherwse, if TRUE values will be filled in from schema
-   *   defaults.
-   */
-  function init($init = TRUE) {
-    if (is_array($init)) {
-      return $this->load_row($init);
-    }
+class ViewStorage extends ConfigurableBase {
 
-    if (!$init) {
-      return;
-    }
-
-    $schema = drupal_get_schema($this->db_table);
-
-    if (!$schema) {
-      return;
-    }
-
-    // Go through our schema and build correlations.
-    foreach ($schema['fields'] as $field => $info) {
-      if ($info['type'] == 'serial') {
-        $this->$field = NULL;
-      }
-      if (!isset($this->$field)) {
-        if (!empty($info['serialize']) && isset($info['serialized default'])) {
-          $this->$field = unserialize($info['serialized default']);
-        }
-        elseif (isset($info['default'])) {
-          $this->$field = $info['default'];
-        }
-        else {
-          $this->$field = '';
-        }
-      }
-    }
+  public function __construct(array $values, $entity_type) {
+    parent::__construct($values, 'view');
   }
 
   /**
-   * Write the row to the database.
-   *
-   * @param $update
-   *   If true this will be an UPDATE query. Otherwise it will be an INSERT.
+   * Overrides Drupal\entity\StorableInterface::id().
    */
-  function save_row($update = NULL) {
-    $fields = $defs = $values = $serials = array();
-    $schema = drupal_get_schema($this->db_table);
-
-    // Go through our schema and build correlations.
-    foreach ($schema['fields'] as $field => $info) {
-      // special case -- skip serial types if we are updating.
-      if ($info['type'] == 'serial') {
-        $serials[] = $field;
-        continue;
-      }
-      elseif ($info['type'] == 'int') {
-        $this->$field = (int) $this->$field;
-      }
-      $fields[$field] = empty($info['serialize']) ? $this->$field : serialize($this->$field);
-    }
-    if (!$update) {
-      $query = db_insert($this->db_table);
-    }
-    else {
-      $query = db_update($this->db_table)
-        ->condition($update, $this->$update);
-    }
-    $return = $query
-      ->fields($fields)
-      ->execute();
-
-    if ($serials && !$update) {
-      // get last insert ids and fill them in.
-      // Well, one ID.
-      foreach ($serials as $field) {
-        $this->$field = $return;
-      }
-    }
-  }
-
-  /**
-   * Load the object with a row from the database.
-   *
-   * This method is separate from the constructor in order to give us
-   * more flexibility in terms of how the view object is built in different
-   * contexts.
-   *
-   * @param $data
-   *   An object from db_fetch_object. It should contain all of the fields
-   *   that are in the schema.
-   */
-  function load_row($data) {
-    $schema = drupal_get_schema($this->db_table);
-
-    // Go through our schema and build correlations.
-    foreach ($schema['fields'] as $field => $info) {
-      $this->$field = empty($info['serialize']) ? $data->$field : unserialize($data->$field);
-    }
-  }
-
-  /**
-   * Export a loaded row, such as an argument, field or the view itself to PHP code.
-   *
-   * @param $identifier
-   *   The variable to assign the PHP code for this object to.
-   * @param $indent
-   *   An optional indentation for prettifying nested code.
-   */
-  function export_row($identifier = NULL, $indent = '') {
-    // @todo replace with http://drupal.org/node/1741154.
-    ctools_include('export');
-
-    if (!$identifier) {
-      $identifier = $this->db_table;
-    }
-    $schema = drupal_get_schema($this->db_table);
-
-    $output = $indent . '$' . $identifier . ' = new ' . get_class($this) . "();\n";
-    // Go through our schema and build correlations.
-    foreach ($schema['fields'] as $field => $info) {
-      if (!empty($info['no export'])) {
-        continue;
-      }
-      if (!isset($this->$field)) {
-        if (isset($info['default'])) {
-          $this->$field = $info['default'];
-        }
-        else {
-          $this->$field = '';
-        }
-
-        // serialized defaults must be set as serialized.
-        if (isset($info['serialize'])) {
-          $this->$field = unserialize($this->$field);
-        }
-      }
-      $value = $this->$field;
-      if ($info['type'] == 'int') {
-        if (isset($info['size']) && $info['size'] == 'tiny') {
-          $value = (bool) $value;
-        }
-        else {
-          $value = (int) $value;
-        }
-      }
-
-      $output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ";\n";
-    }
-    return $output;
+  public function id() {
+    return $this->name;
   }
 
   /**
@@ -213,9 +66,14 @@ class ViewsDbObject {
       }
     }
 
+    $display_options = array(
+      'type' => $type,
+      'id' => $id,
+      'display_title' => $title,
+    );
+
     // Create the new display object
-    $display = new ViewsDisplay();
-    $display->options($type, $id, $title);
+    $display = new ViewDisplay($display_options);
 
     // Add the new display object to the view.
     $this->display[$id] = $display;
diff --git a/lib/Drupal/views/ViewStorageController.php b/lib/Drupal/views/ViewStorageController.php
new file mode 100644
index 0000000..ef5911a
--- /dev/null
+++ b/lib/Drupal/views/ViewStorageController.php
@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\views\ViewStorageController.
+ */
+
+namespace Drupal\views;
+
+use Drupal\config\ConfigStorageController;
+use Drupal\entity\StorableInterface;
+
+class ViewStorageController extends ConfigStorageController {
+
+  /**
+   * Overrides Drupal\config\ConfigStorageController::attachLoad();
+   */
+  protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
+    foreach ($queried_entities as $id => $entity) {
+      $this->attachDisplays($entity);
+    }
+  }
+
+  /**
+   * Overrides Drupal\config\ConfigStorageController::save().
+   *
+   * This currently replaces the reflection code with a static array of
+   * properties to be set on the config object. This can be removed
+   * when the view storage is isolated so the ReflectionClass can work.
+   */
+  public function save(StorableInterface $entity) {
+    $prefix = $this->entityInfo['config prefix'] . '.';
+
+    // Load the stored entity, if any.
+    if ($entity->getOriginalID()) {
+      $id = $entity->getOriginalID();
+    }
+    else {
+      $id = $entity->id();
+    }
+    $config = config($prefix . $id);
+    $config->setName($prefix . $entity->id());
+
+    if (!$config->isNew() && !isset($entity->original)) {
+      $entity->original = entity_load_unchanged($this->entityType, $id);
+    }
+
+    $this->preSave($entity);
+    $this->invokeHook('presave', $entity);
+
+    // @todo: This temp measure will be removed once we have a better way or
+    // separation of storage and the executed view.
+    $config_properties = array (
+      'disabled',
+      'api_version',
+      'name',
+      'description',
+      'tag',
+      'base_table',
+      'human_name',
+      'core',
+      'display',
+    );
+
+    foreach ($config_properties as $property) {
+      if ($property == 'display') {
+        $displays = array();
+        foreach ($entity->display as $key => $display) {
+          $displays[$key] = array(
+            'display_options' => $display->display_options,
+            'display_plugin' => $display->display_plugin,
+            'id' => $display->id,
+            'display_title' => $display->display_title,
+            'position' => isset($display->position) ? $display->position : 0,
+          );
+        }
+        $config->set('display', $displays);
+      }
+      else {
+        $config->set($property, $entity->$property);
+      }
+    }
+
+    if (!$config->isNew()) {
+      $return = SAVED_NEW;
+      $config->save();
+      $this->postSave($entity, TRUE);
+      $this->invokeHook('update', $entity);
+    }
+    else {
+      $return = SAVED_UPDATED;
+      $config->save();
+      $entity->enforceIsNew(FALSE);
+      $this->postSave($entity, FALSE);
+      $this->invokeHook('insert', $entity);
+    }
+
+    unset($entity->original);
+
+    return $return;
+  }
+
+  /**
+   * Overrides Drupal\config\ConfigStorageController::create().
+   */
+  public function create(array $values) {
+    $entity = parent::create($values);
+    $this->attachDisplays($entity);
+    return $entity;
+  }
+
+  /**
+   * Attaches an array of ViewDisplay objects to the view display property.
+   *
+   * @param Drupal\entity\StorableInterface $entity
+   */
+  protected function attachDisplays($entity) {
+    if (isset($entity->display) && is_array($entity->display)) {
+      $displays = array();
+      foreach ($entity->get('display') as $key => $options) {
+        // Create a ViewDisplay object using the display options.
+        $displays[$key] = new ViewDisplay($options);
+      }
+      $entity->set('display', $displays);
+    }
+  }
+
+}
diff --git a/lib/Drupal/views/ViewsDisplay.php b/lib/Drupal/views/ViewsDisplay.php
deleted file mode 100644
index af7f47a..0000000
--- a/lib/Drupal/views/ViewsDisplay.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\views\ViewsDisplay.
- */
-
-namespace Drupal\views;
-
-/**
- * A display type in a view.
- *
- * This is just the database storage mechanism, and isn't terribly important
- * to the behavior of the display at all.
- */
-class ViewsDisplay extends ViewsDbObject {
-
-  /**
-   * The display handler itself, which has all the methods.
-   *
-   * @var views_plugin_display
-   */
-  var $handler;
-
-  /**
-   * Stores all options of the display, like fields, filters etc.
-   *
-   * @var array
-   */
-  var $display_options;
-
-  var $db_table = 'views_display';
-
-  function __construct($init = TRUE) {
-    parent::init($init);
-  }
-
-  function options($type, $id, $title) {
-    $this->display_plugin = $type;
-    $this->id = $id;
-    $this->display_title = $title;
-  }
-
-}
diff --git a/views.info b/views.info
index adea473..77703ce 100644
--- a/views.info
+++ b/views.info
@@ -4,6 +4,7 @@ package = Views
 core = 8.x
 php = 5.2
 dependencies[] = ctools
+dependencies[] = config
 
 ; Always available CSS
 stylesheets[all][] = css/views.base.css
diff --git a/views.install b/views.install
index b986b05..6154bab 100644
--- a/views.install
+++ b/views.install
@@ -35,6 +35,9 @@ function views_schema() {
       ),
       'object' => 'Drupal\views\View',
       // the callback to load the displays
+      'load all callback' => 'views_get_all_views',
+      'load callback' => 'views_storage_load',
+      'save callback' => 'views_storage_save',
       'subrecords callback' => 'views_load_display_records',
       // the variable that holds enabled/disabled status
       'status' => 'views_defaults',
diff --git a/views.module b/views.module
index b840c02..6d49f15 100644
--- a/views.module
+++ b/views.module
@@ -75,25 +75,28 @@ function views_temp_store() {
 }
 
 /**
- * Implements hook_ctools_exportable_info().
+ * Implements hook_entity_info().
  */
-function views_ctools_exportable_info() {
-  return array(
+function views_entity_info() {
+  $return = array(
     'view' => array(
-      'controller class' => 'Drupal\ctools\DatabaseExportableController',
-      'key' => 'name',
-      'identifier' => 'view',
-      'default hook' => 'views_default_views',
-      'bulk export' => TRUE,
-      'api' => array(
-        'owner' => 'views',
-        'api' => 'views_default',
-        'minimum_version' => '2',
-        'current_version' => '3.0',
+      'label' => t('View'),
+      'entity class' => 'Drupal\views\View',
+      'controller class' => 'Drupal\views\ViewStorageController',
+      'form controller class' => array(
+        'default' => 'Drupal\node\NodeFormController',
+      ),
+      'config prefix' => 'views.view',
+      'fieldable' => FALSE,
+      'entity keys' => array(
+        'id' => 'name',
+        'label' => 'human_name',
+        'uuid' => 'uuid',
       ),
-      'schema' => 'views_view',
     ),
   );
+
+  return $return;
 }
 
 /**
@@ -1570,8 +1573,28 @@ function views_get_applicable_views($type) {
  */
 function views_get_all_views($reset = FALSE) {
   // @todo replace with http://drupal.org/node/1741154.
-  ctools_include('export');
-  return ctools_export_crud_load_all('views_view', $reset);
+  $controller = entity_get_controller('view');
+  return $controller->load();
+}
+
+/**
+ * Loads a view with the storage controller.
+ *
+ * @param string $id
+ *   The view name to load.
+ *
+ * @return Drupal\views\View
+ *   The view which is loaded.
+ */
+function views_storage_load($id) {
+  $controller = entity_get_controller('view');
+  $result = $controller->load(array($id));
+  return reset($result);
+}
+
+function views_storage_save(View $view) {
+  $controller = entity_get_controller('view');
+  return $controller->save($view);
 }
 
 /**
