PagedList を使って ASP.NET MVC でページネーション


本記事の概要

Webアプリにおいてページ処理が必要になる場面は多いですが、自力で実装するのは大変。
Paginate機能が標準で付いているフレームワークもありますが、ASP.NET MVCには無さそうなので PagedList というライブラリを使ってみる。

PagedList (PagedList.MVC) とは

PagedList は Nuget で一番DLされてるページネイション用ライブラリ。
PagedList.MVC はHTMLヘルパー用のライブラリになりますので両方セットでインストールします。
(PagedList.MVC のほうをインストールすると PagedList も一緒にインストールされます)
https://github.com/TroyGoode/PagedList
https://www.nuget.org/packages/PagedList.Mvc

使い方(Model, Controller側)

// データベースから取得するためのIQueryable型を用意
IQueryable<Book> books = dbSet
    .Where(b => b.Price < 3000)
    .OrderBy(b => b.Title);

int pageNumber = 1; // ページ番号
int pageSize = 20;  // 1ページに表示する件数

IPagedList<Book> bookPages = books.ToPagedList(pageNumber, pageSize); // Bookをページで取得

基本的な使い方は IQueryable型 に対して拡張メソッド ToPagedList() でページ番号とサイズを指定するだけ。
IPagedList型 は IEnumerable型 を継承してページ情報のプロパティを実装したもの。
books は ToPagedList() 実行時に、必要な件数のLIMIT句をSQLに加えた形で遅延評価されます。

さらに ToPagedList() はIQueryable型の拡張メソッドなので、前回 紹介した AutoMapper のマッピングに対してもそのまま実行できます。

IPagedList<BookViewModel> books = dbSet
    .Where(b => b.Price < 3000)
    .OrderBy(b => b.Title)
    .ProjectTo<BookViewModel>() // AutoMapperによるBookViewModelへのマッピング
    .ToPagedList(1, 20); // そのままメソッドチェーンで即時評価

このように LINQ to Entities なら 絞り込み、ソート、マッピング、ページネーション を全て繋げて一度に実行できます。便利。

使い方(View側)

表示側はこうなります

.cshtml
@using PagedList
@using PagedList.Mvc;
@model IPagedList<App.Models.Book> // IPagedList型で渡す

...

foreach(var book in Model) {
    // IEnumerableを継承しているので、何も意識せずリストアップ可能
}

// ページ番号表示
@Html.PagedListPager(Model, page => Url.Action("Index", page))

Bootstrapに対応しているので、Bootstrapを導入しているとページ番号は次のような表示になります。

また、PagedListPager() の第3引数に PagedListRenderOptions を指定すれば、あらかじめ用意されたスタイルが簡単に使用できます。

最後に

2日連続で、IQueryable型のメリットと定番ライブラリを紹介させていただきました。
引き続き ASP.NET Advent Calendar 2015 をお楽しみください。