diff --git a/core/modules/views/config/schema/views.data_types.schema.yml b/core/modules/views/config/schema/views.data_types.schema.yml
index a3d1b34..ab96c74 100644
--- a/core/modules/views/config/schema/views.data_types.schema.yml
+++ b/core/modules/views/config/schema/views.data_types.schema.yml
@@ -599,6 +599,9 @@ views_pager_sql:
     id:
       type: integer
       label: 'Pager ID'
+    query_type:
+      type: string
+      label: 'Query type'
     tags:
       type: mapping
       label: 'Pager link labels'
diff --git a/core/modules/views/js/ajax_view.js b/core/modules/views/js/ajax_view.js
index 67601a1..0dc5b5a 100644
--- a/core/modules/views/js/ajax_view.js
+++ b/core/modules/views/js/ajax_view.js
@@ -89,13 +89,15 @@
     var $link = $(link);
     var viewData = {};
     var href = $link.attr('href');
+    var type = typeof this.settings.pager_query_method !== 'undefined' ? this.settings.pager_query_method : 'POST';
 
     $.extend(viewData, this.settings, Drupal.Views.parseQueryString(href), Drupal.Views.parseViewArgs(href, this.settings.view_base_path));
 
     var self_settings = $.extend({}, this.element_settings, {
       submit: viewData,
       base: false,
-      element: link
+      element: link,
+      type: type
     });
     this.pagerAjax = Drupal.ajax(self_settings);
   };
@@ -112,4 +114,4 @@
       $(scrollTarget).animate({ scrollTop: offset.top - 10 }, 500);
     }
   };
-})(jQuery, Drupal, drupalSettings);
\ No newline at end of file
+})(jQuery, Drupal, drupalSettings);
diff --git a/core/modules/views/src/Ajax/ViewAjaxResponse.php b/core/modules/views/src/Ajax/ViewAjaxResponse.php
index d191800..8b3e069 100644
--- a/core/modules/views/src/Ajax/ViewAjaxResponse.php
+++ b/core/modules/views/src/Ajax/ViewAjaxResponse.php
@@ -3,6 +3,7 @@
 namespace Drupal\views\Ajax;
 
 use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Cache\CacheableResponseTrait;
 use Drupal\views\ViewExecutable;
 
 /**
@@ -12,6 +13,8 @@
  */
 class ViewAjaxResponse extends AjaxResponse {
 
+  use CacheableResponseTrait;
+
   /**
    * The view executed on this ajax request.
    *
diff --git a/core/modules/views/src/Controller/ViewAjaxController.php b/core/modules/views/src/Controller/ViewAjaxController.php
index 4aefdab..63d2d21 100644
--- a/core/modules/views/src/Controller/ViewAjaxController.php
+++ b/core/modules/views/src/Controller/ViewAjaxController.php
@@ -110,10 +110,10 @@ public static function create(ContainerInterface $container) {
    *   Thrown when the view was not found.
    */
   public function ajaxView(Request $request) {
-    $name = $request->request->get('view_name');
-    $display_id = $request->request->get('view_display_id');
+    $name = $this->getParam($request, 'view_name');
+    $display_id = $this->getParam($request, 'view_display_id');
     if (isset($name) && isset($display_id)) {
-      $args = $request->request->get('view_args');
+      $args = $this->getParam($request, 'view_args');
       $args = isset($args) && $args !== '' ? explode('/', $args) : [];
 
       // Arguments can be empty, make sure they are passed on as NULL so that
@@ -122,10 +122,10 @@ public function ajaxView(Request $request) {
         return ($arg == '' ? NULL : $arg);
       }, $args);
 
-      $path = $request->request->get('view_path');
-      $dom_id = $request->request->get('view_dom_id');
+      $path = $this->getParam($request, 'view_path');
+      $dom_id = $this->getParam($request, 'view_dom_id');
       $dom_id = isset($dom_id) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $dom_id) : NULL;
-      $pager_element = $request->request->get('pager_element');
+      $pager_element = $this->getParam($request, 'pager_element');
       $pager_element = isset($pager_element) ? intval($pager_element) : NULL;
 
       $response = new ViewAjaxResponse();
@@ -149,8 +149,8 @@ public function ajaxView(Request $request) {
           $this->currentPath->setPath('/' . $path, $request);
         }
 
-        // Add all POST data, because AJAX is always a post and many things,
-        // such as tablesorts, exposed filters and paging assume GET.
+        // Add all POST data, because many things, such as tablesorts, exposed
+        // filters and paging assume GET.
         $request_all = $request->request->all();
         $query_all = $request->query->all();
         $request->query->replace($request_all + $query_all);
@@ -180,16 +180,10 @@ public function ajaxView(Request $request) {
         // Reuse the same DOM id so it matches that in drupalSettings.
         $view->dom_id = $dom_id;
 
-        $context = new RenderContext();
-        $preview = $this->renderer->executeInRenderContext($context, function () use ($view, $display_id, $args) {
-          return $view->preview($display_id, $args);
-        });
-        if (!$context->isEmpty()) {
-          $bubbleable_metadata = $context->pop();
-          BubbleableMetadata::createFromRenderArray($preview)
-            ->merge($bubbleable_metadata)
-            ->applyTo($preview);
-        }
+        // Build the view and add metadata to the response.
+        $preview = $view->buildRenderable($display_id, $args);
+        $cache_metadata = BubbleableMetadata::createFromRenderArray($preview);
+        $response->addCacheableDependency($cache_metadata);
         $response->addCommand(new ReplaceCommand(".js-view-dom-id-$dom_id", $preview));
 
         return $response;
@@ -203,4 +197,27 @@ public function ajaxView(Request $request) {
     }
   }
 
+  /**
+   * Get a request parameter.
+   *
+   * Determines whether request is GET or POST.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   An HTTP request.
+   * @param string $param
+   *   The name of a parameter.
+   *
+   * @return mixed
+   *   The parameter value.
+   */
+  public function getParam(Request $request, $param) {
+    $type = $request->getMethod();
+
+    if ($type == 'GET') {
+      return $request->query->get($param);
+    }
+
+    return $request->request->get($param);
+  }
+
 }
diff --git a/core/modules/views/src/Plugin/views/pager/SqlBase.php b/core/modules/views/src/Plugin/views/pager/SqlBase.php
index 55e07df..cb3cdd2 100644
--- a/core/modules/views/src/Plugin/views/pager/SqlBase.php
+++ b/core/modules/views/src/Plugin/views/pager/SqlBase.php
@@ -16,6 +16,7 @@ protected function defineOptions() {
     $options['items_per_page'] = ['default' => 10];
     $options['offset'] = ['default' => 0];
     $options['id'] = ['default' => 0];
+    $options['query_type'] = array('default' => 'POST');
     $options['total_pages'] = ['default' => ''];
     $options['expose'] = [
       'contains' => [
@@ -72,6 +73,18 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
       '#default_value' => $this->options['total_pages'],
     ];
 
+    if ($this->displayHandler->getOption('use_ajax')) {
+      $form['query_type'] = array(
+        '#type' => 'select',
+        '#title' => $this->t('Pager query type'),
+        '#options' => array(
+          'GET' => $this->t('GET'),
+          'POST' => $this->t('POST'),
+        ),
+        '#default_value' => $this->options['query_type'],
+      );
+    }
+
     $form['tags'] = [
       '#type' => 'details',
       '#open' => TRUE,
diff --git a/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php b/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php
index d65acaa..d9b12c4 100644
--- a/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php
+++ b/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php
@@ -130,8 +130,8 @@ public function testMissingViewName() {
    */
   public function testMissingView() {
     $request = new Request();
-    $request->request->set('view_name', 'test_view');
-    $request->request->set('view_display_id', 'page_1');
+    $request->query->set('view_name', 'test_view');
+    $request->query->set('view_display_id', 'page_1');
 
     $this->viewStorage->expects($this->once())
       ->method('load')
@@ -147,8 +147,8 @@ public function testMissingView() {
    */
   public function testAccessDeniedView() {
     $request = new Request();
-    $request->request->set('view_name', 'test_view');
-    $request->request->set('view_display_id', 'page_1');
+    $request->query->set('view_name', 'test_view');
+    $request->query->set('view_display_id', 'page_1');
 
     $view = $this->getMockBuilder('Drupal\views\Entity\View')
       ->disableOriginalConstructor()
@@ -180,12 +180,12 @@ public function testAccessDeniedView() {
    */
   public function testAjaxView() {
     $request = new Request();
-    $request->request->set('view_name', 'test_view');
-    $request->request->set('view_display_id', 'page_1');
-    $request->request->set('view_path', '/test-page');
-    $request->request->set('_wrapper_format', 'ajax');
-    $request->request->set('ajax_page_state', 'drupal.settings[]');
-    $request->request->set('type', 'article');
+    $request->query->set('view_name', 'test_view');
+    $request->query->set('view_display_id', 'page_1');
+    $request->query->set('view_path', '/test-page');
+    $request->query->set('_wrapper_format', 'ajax');
+    $request->query->set('ajax_page_state', 'drupal.settings[]');
+    $request->query->set('type', 'article');
 
     list($view, $executable) = $this->setupValidMocks();
 
@@ -224,13 +224,13 @@ public function testAjaxViewWithoutAjax() {
    */
   public function testAjaxViewWithArguments() {
     $request = new Request();
-    $request->request->set('view_name', 'test_view');
-    $request->request->set('view_display_id', 'page_1');
-    $request->request->set('view_args', 'arg1/arg2');
+    $request->query->set('view_name', 'test_view');
+    $request->query->set('view_display_id', 'page_1');
+    $request->query->set('view_args', 'arg1/arg2');
 
     list($view, $executable) = $this->setupValidMocks();
     $executable->expects($this->once())
-      ->method('preview')
+      ->method('buildRenderable')
       ->with('page_1', ['arg1', 'arg2']);
 
     $response = $this->viewAjaxController->ajaxView($request);
@@ -244,14 +244,14 @@ public function testAjaxViewWithArguments() {
    */
   public function testAjaxViewWithEmptyArguments() {
     $request = new Request();
-    $request->request->set('view_name', 'test_view');
-    $request->request->set('view_display_id', 'page_1');
+    $request->query->set('view_name', 'test_view');
+    $request->query->set('view_display_id', 'page_1');
     // Simulate a request that has a second, empty argument.
-    $request->request->set('view_args', 'arg1/');
+    $request->query->set('view_args', 'arg1/');
 
     list($view, $executable) = $this->setupValidMocks();
     $executable->expects($this->once())
-      ->method('preview')
+      ->method('buildRenderable')
       ->with('page_1', $this->identicalTo(['arg1', NULL]));
 
     $response = $this->viewAjaxController->ajaxView($request);
@@ -264,12 +264,36 @@ public function testAjaxViewWithEmptyArguments() {
    * Tests a valid view with a pager.
    */
   public function testAjaxViewWithPager() {
+    $this->ajaxViewWithPagerTest();
+  }
+
+  /**
+   * Test a valid view with a pager using POST.
+   */
+  public function testAjaxViewWithPostPager() {
+    $this->ajaxViewWithPagerTest(TRUE);
+  }
+
+  /**
+   * Generate a request for a paged view.
+   *
+   * @param boolean $post
+   *   Whether to structure the request as a POST.
+   */
+  protected function ajaxViewWithPagerTest($post = FALSE) {
     $request = new Request();
-    $request->request->set('view_name', 'test_view');
-    $request->request->set('view_display_id', 'page_1');
+    $param_property = 'query';
+
+    if ($post) {
+      $request->setMethod('POST');
+      $param_property = 'request';
+    }
+
+    $request->{$param_property}->set('view_name', 'test_view');
+    $request->{$param_property}->set('view_display_id', 'page_1');
     $dom_id = $this->randomMachineName(20);
-    $request->request->set('view_dom_id', $dom_id);
-    $request->request->set('pager_element', '0');
+    $request->{$param_property}->set('view_dom_id', $dom_id);
+    $request->{$param_property}->set('pager_element', '0');
 
     list($view, $executable) = $this->setupValidMocks();
 
@@ -329,7 +353,7 @@ protected function setupValidMocks($use_ajax = self::USE_AJAX) {
       ->method('setDisplay')
       ->willReturn(TRUE);
     $executable->expects($this->atMost(1))
-      ->method('preview')
+      ->method('buildRenderable')
       ->will($this->returnValue(['#markup' => 'View result']));
 
     $this->executableFactory->expects($this->once())
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index 8b70764..fa0e957 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -65,6 +65,7 @@ function views_views_pre_render($view) {
           // To fit multiple views on a page, the programmer may have
           // overridden the display's pager_element.
           'pager_element' => isset($view->pager) ? $view->pager->getPagerId() : 0,
+          'pager_query_method' => !empty($view->pager->options['query_type']) ? $view->pager->options['query_type'] : 'POST'
         ],
       ],
     ];
