.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:N160417002
出刊日期:2016/4/20
開發工具:Visual Studio 2015 Enterprise Update 1
版本:.NET Framework 4.6、ASP.NET MVC5
在這篇文章之中,我們將以Step - by - Step的方式,來介紹如何在ASP.NET MVC5 檢視,設計資料分頁功能,以免一次在網頁中顯示過多的資料。我們將利用Entity Framework從SQL Server Northwind資料庫中,取出Customers資料表的資料來進行測試。
啟動Visual Studio 2015開發環境,從「File」-「New」-「Project」,在「New Project」對話盒中,確認視窗上方.NET Framework的目標版本為「.NET Framework 4.6,或以上版本」,選取左方「Installed」-「Templates」-「Visual C#」,從「Web」分類中,選取「ASP.NET Web Application」。設定專案名稱為「MVCPageDemo」,設定專案存放路徑,並按下「OK」鍵,請參考下圖所示:

圖 1:建立測試專案。
在「New ASP.NET Project」對話盒中選取「Empty」節點,勾選下方的「MVC」項目,清除右下方的「Host in the cloud」核取方塊,然後按下「OK」按鈕,建立專案,請參考下圖所示:

圖 2:建立空白的MVC測試專案。
使用反向工程建立ADO.NET實體資料模型
下一步是使用反向工程的功能來定義模型,我們想要從SQL Server的Northwind範例資料庫來建立模型。在MVC的專案之中,通常將ADO.NET實體資料模型的相關程式置於Models資料夾之中。從Visual Studio 2015開發工具-「Solution Explorer」- 專案-「Models」目錄上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Item」,開啟「Add New Item」對話盒,從右上方文字方塊輸入「ado.net」搜尋,選取「ADO.NET Entity Data Model」,設定名稱為「Model1」,請參考下圖所示:

圖 3:建立ADO.NET實體資料模型。
然後選取「Code First from database」項目,接著按下「Next」按鈕,使用精靈來建立ADO.NET實體資料模型,請參考下圖所示:

圖 4:建立ADO.NET實體資料模型。
在下一個畫面,選取「New Connection」建立資料庫連接,在「Connection Properties」視窗中,設以下屬性:
- Data Source (資料來源) :Microsoft SQL Server (SQLClient)。
- Server name欄位:資料庫伺服器的名稱,此例輸入「.\SQLExpress」。
- Log on to server:選取「Use Windows Authentication」。
- Select or enter a database name欄位:選擇「Northwind」資料庫。
目前畫面應如下圖所示,完成後按下「OK」按鈕:

圖 5:建立資料庫連接。
接著會回到設定連結的畫面,請參考下圖所示:

圖 6:設定連結。
按「Next」按鈕進入到下一個畫面,以選取資料庫物件,勾選「Customers」資料表,以及「Pluralize or dingularize generated object names」項目,請參考下圖所示:

圖 7:選取資料庫物件。
最後按下「Finish」按鈕,當精靈完成之後,專案中Models資料夾內將產生兩個檔案,內含模型與Entity Framework相關的類別程式碼。
建立控制器與檢視
下一步我們來透過Visual Studio 2015的「Add Scaffold」功能來建立控制器,以及展現資料的檢視(View)。在「Solution Explorer」視窗,專案的「Controllers」資料夾上方,按滑鼠右鍵,選取「Add」-「Controller」,此時會開啟「Add Scaffold」視窗,選取「MVC 5 Controller with views, using Entity Framework」,然後按下「Add」按鈕,請參考下圖所示:

圖 8:建立控制器。
在「Add Controller」視窗設定以下資料:
- Model Class :「Customer (MVCPageDemo.Models)」。
- Data context class:「Model1 (MVCPageDemo.Models)」。
- 勾選中間的「Generate views」與「Reference script libraries」,清除勾選其它核取方塊
- Controller Name:「CustomersController」。
完成的結果,請參考下圖所示,然後按下「Add」按鈕:

圖 9:加入控制器。
Visual Studio 2015會自動在專案中「Views\ Customers」資料夾下,產生Index.cshtml、Edit.cshtml、Details.cshtml、Delete.cshtml與Create.cshtml檔案,以及顯示資料的程式碼。
最後測試一下首頁,從「Solution Explorer」視窗- 選取Views\ Customers資料夾下的Index.cshtml檔案,按CTRL+F5執行Index 檢視,執行結果參考如下,資料表所有內容表列在網頁之中,資料筆數超過瀏覽器的長度:

圖 10:顯示資料表資料。
下載PagedList.Mvc套件
我們可以在MVC專案中,使用PagedList.Mvc套件來設計資料分頁功能。在專案中需要先使用Nuget套件管理員下載「PagedList.Mvc」函式庫。在「Solution Explorer」視窗選取專案名稱。從Visual Studio 2015開發工具「Tools」-「NuGet Package Manager」-「Package Manager Console」開啟「Package Manager Console」視窗,然後在提示字元中輸入install-package指令,並使用「-version」指定安裝PagedList.Mvc 4.5.0版本:
Install-Package PagedList.Mvc -Version 4.5.0
套件下載完成之後,會在bin資料夾加入PagedList.dll與PagedList.Mvc.dll檔案,並且在Content資料夾中,加入一個PagedList.css檔案,用來設定分頁超連結的樣式。
修改控制器程式碼
接著修改CustomersController.cs檔案中的程式碼,啟用資料分頁的功能,先在檔案上方引用以下命名空間:
using PagedList;
在CustomersController類別階層宣告一個數值型別,名為pageSize的變數,初始化為「5」,表示一頁要顯示五筆資料:
int pageSize = 5;
修改Index方法,傳入一個可為Null的數值型別變數page:
public ActionResult Index( int? page ) {
在Index方法中宣告一個數值型別,名為pageNumber的變數,用來記錄目前要顯示的頁數,若沒有設定則預設顯示第一頁:
int pageNumber = ( page ?? 1 );
使用var宣告一個data變數,用來存放要顯示的資料,我們先將資料根據CustomerID屬性來排序,接著叫用ToPagedList方法,傳入要顯示的頁碼與一頁的資料筆數,然後將data變數傳入View方法之中:
var data = db.Customers.OrderBy( c => c.CustomerID ).ToPagedList( pageNumber , pageSize );
return View( data );
目前CustomersController控制器的程式碼看起來如下:
public class CustomersController : Controller {
private Model1 db = new Model1( );
int pageSize = 5;
public ActionResult Index( int? page ) {
int pageNumber = ( page ?? 1 );
var data = db.Customers.OrderBy( c => c.CustomerID ).ToPagedList( pageNumber , pageSize );
return View( data );
}
//以下省略
}
到目前為止我們可以測試一下首頁,從「Solution Explorer」視窗- 選取Views\ Customers資料夾下的Index.cshtml檔案,按CTRL+F5執行Index 檢視,執行結果參考如下,目前顯示第一頁的資料:

圖 12:測試首頁分頁功能。
讓我們直接修改一下URL,附加查詢字串測試,傳入「?page=2」,將第二頁的資料擷取出來:
http://localhost:47651/Customers/Index?page=2
執行結果請參考下圖所示:

圖 13:使用查詢字串顯示第二頁的資料。
顯示分頁超連結
最後,修改Index.cshtml,讓網頁最下方可以顯示出分頁超連結,這樣使用者便可以點選分頁超連結來進行跳頁的動作。在Index檢視第一行先引用PagedList.Mvc命名空間:
@using PagedList.Mvc;
接下來修改@model這行程式碼:
@model PagedList.IPagedList<MVCPageDemo.Models.Customer>
修改每一個<th>標籤中的Html.DisplayNameFor這行程式碼,先叫用First()方法取回PagedList.IPagedList<MVCPageDemo.Models.Customer>中第一個Customer物件,再利用屬性取回DisplayName:
<th>
@Html.DisplayNameFor(model => model.First().CompanyName )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).ContactName )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).ContactTitle )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).Address )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).City )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).Region )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).PostalCode )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).Country )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).Phone )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).Fax )
</th>
在檢視最下方加入以下程式碼,印出目前的頁碼,PageCount屬性可得知分頁數量,PageNumber則儲存目前的頁碼:
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of
@Model.PageCount
最後利用PagedListPager產生分頁超連結:
@Html.PagedListPager( Model , page => Url.Action( "Index" ,new { page} ) )
完整的Index檢視的程式碼看起來如下:
@using PagedList.Mvc;
@model PagedList.IPagedList<MVCPageDemo.Models.Customer>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link href="~/Content/PagedList.css" rel="stylesheet" />
</head>
<body>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.First().CompanyName )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).ContactName )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).ContactTitle )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).Address )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).City )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).Region )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).PostalCode )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).Country )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).Phone )
</th>
<th>
@Html.DisplayNameFor(model => model.First( ).Fax )
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.CompanyName)
</td>
<td>
@Html.DisplayFor(modelItem => item.ContactName)
</td>
<td>
@Html.DisplayFor(modelItem => item.ContactTitle)
</td>
<td>
@Html.DisplayFor(modelItem => item.Address)
</td>
<td>
@Html.DisplayFor(modelItem => item.City)
</td>
<td>
@Html.DisplayFor(modelItem => item.Region)
</td>
<td>
@Html.DisplayFor(modelItem => item.PostalCode)
</td>
<td>
@Html.DisplayFor(modelItem => item.Country)
</td>
<td>
@Html.DisplayFor(modelItem => item.Phone)
</td>
<td>
@Html.DisplayFor(modelItem => item.Fax)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.CustomerID }) |
@Html.ActionLink("Details", "Details", new { id=item.CustomerID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.CustomerID })
</td>
</tr>
}
</table>
<br />
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of
@Model.PageCount
@Html.PagedListPager( Model , page => Url.Action( "Index" ,new { page} ) )
</body>
</html>
從「Solution Explorer」視窗- 選取Views\ Customers資料夾下的Index.cshtml檔案,按CTRL+F5執行Index 檢視,執行結果請參考下圖所示:

圖 14:自動分頁範例。