在前一篇文章《【初學者指南】在ASP.NET MVC 5中建立GridView》中,咱們學習瞭如何在 ASP.NET MVC 中實現 GridView,相似於 ASP.NET web 表單的功能。經過前文,咱們已經瞭解到使用 jQuery 插件的數據表能夠很容易地實現具備搜索、排序和分頁等重要功能的表格。javascript
前文中須要注意的是,全部經過插件實現的特性都是客戶端的,這意味着全部的數據都首先在頁面載入,而後由插件來處理客戶端搜索、分頁和排序的數據。若是數據表不是特別大,這麼作是能夠的;可是,若是數據表很大或者數據會隨着應用的使用而不斷增長,就會引發問題。若是這樣的問題確實發生了,從長遠來說,這種建立表格方式將不是一個好選擇。css
在本文中,咱們將會學習如何實現服務器端的分頁,搜索和排序功能。從長遠來說,這是一種更好的方式來應對數據集特別大的狀況。html
咱們將會修改前文中的源代碼,如今就開始吧!java
首先,咱們須要從 NuGet 包管理器中安裝 datatables.mvc5。這是 Stefan Nuxoll 實現的綁定在控制器上的數據集模型。咱們爲何須要這個包?這是因爲綁定將會提供一個附着在控制器上的強類型的模型,這將有助於咱們避免讀取請求參數,也會將咱們從請求的參數類型轉換中解救出來。請求對象中的全部參數傳遞都不是安全類型的,因此咱們必須手動的將它們轉換到目的類型,這也將有助於開發人員專一於業務邏輯,而不用老是考慮 HTTP 參數,檢查參數、轉化參數。jquery
綁定的好處之一是:若是業務須要,能夠在請求中發送一個自定義參數。web
你能夠經過提供 IDataTablesRequest 來實現添加自定義的參數,你也須要重寫它的 BindModel 和 MapAdditionalColumns 方法。ajax
如今讓咱們建立文章中會用到的數據庫和表,打開 SQL Management Studio 並運行如下腳本:數據庫
CREATE DATABASE [GridExampleMVC] GO CREATE TABLE [dbo].[Assets] ( [AssetID] UNIQUEIDENTIFIER NOT NULL, [Barcode] NVARCHAR (MAX) NULL, [SerialNumber] NVARCHAR (MAX) NULL, [FacilitySite] NVARCHAR (MAX) NULL, [PMGuide] NVARCHAR (MAX) NULL, [AstID] NVARCHAR (MAX) NOT NULL, [ChildAsset] NVARCHAR (MAX) NULL, [GeneralAssetDescription] NVARCHAR (MAX) NULL, [SecondaryAssetDescription] NVARCHAR (MAX) NULL, [Quantity] INT NOT NULL, [Manufacturer] NVARCHAR (MAX) NULL, [ModelNumber] NVARCHAR (MAX) NULL, [Building] NVARCHAR (MAX) NULL, [Floor] NVARCHAR (MAX) NULL, [Corridor] NVARCHAR (MAX) NULL, [RoomNo] NVARCHAR (MAX) NULL, [MERNo] NVARCHAR (MAX) NULL, [EquipSystem] NVARCHAR (MAX) NULL, [Comments] NVARCHAR (MAX) NULL, [Issued] BIT NOT NULL, CONSTRAINT [PK_dbo.Assets] PRIMARY KEY CLUSTERED ([AssetID] ASC) ) GO
這是附屬在源代碼上的一個完整的 SQL 腳本文件,能夠用它使用簡單的數據來建立數據庫和表。bootstrap
如今,建立一個新的 ASP.NET MVC 5 Web 應用程序。打開 Visual Studio 2015,點擊文件>>新建>>項目。安全
從該對話框中,跳轉到 Web,並選擇 ASP.NET Web 應用程序項目,而後單擊肯定。
在模板頁面,選擇 MVC,若是編寫了單元測試,請先作檢查,而後點擊肯定。
咱們的工程都是用基本的功能建立的。如今,咱們開始建立數據庫上下文類,這個類將會被Data Access實體框架使用。
首先,咱們須要爲 Asset 表建立一個模型,咱們將會使用這個模型經過 ORM 來恢復數據。
在模型文件夾中,建立一個名爲 Asset 的新類:
using System.ComponentModel.DataAnnotations; namespace GridExampleMVC.Models { public class Asset { public System.Guid AssetID { get; set; } [Display(Name = "Barcode")] public string Barcode { get; set; } [Display(Name = "Serial-Number")] public string SerialNumber { get; set; } [Display(Name = "Facility-Site")] public string FacilitySite { get; set; } [Display(Name = "PM-Guide-ID")] public string PMGuide { get; set; } [Required] [Display(Name = "Asset-ID")] public string AstID { get; set; } [Display(Name = "Child-Asset")] public string ChildAsset { get; set; } [Display(Name = "General-Asset-Description")] public string GeneralAssetDescription { get; set; } [Display(Name = "Secondary-Asset-Description")] public string SecondaryAssetDescription { get; set; } public int Quantity { get; set; } [Display(Name = "Manufacturer")] public string Manufacturer { get; set; } [Display(Name = "Model-Number") public string ModelNumber { get; set; } [Display(Name = "Main-Location (Building)")] public string Building { get; set; } [Display(Name = "Sub-Location 1 (Floor)")] public string Floor { get; set; } [Display(Name = "Sub-Location 2 (Corridor)")] public string Corridor { get; set; } [Display(Name = "Sub-Location 3 (Room No)")] public string RoomNo { get; set; } [Display(Name = "Sub-Location 4 (MER#)")] public string MERNo { get; set; } [Display(Name = "Sub-Location 5 (Equip/System)")] public string EquipSystem { get; set; } public string Comments { get; set; } public bool Issued { get; set; } } }
如今從解決方案資源管理器跳轉到模型文件夾,並打開 IdentityModels.cs 文件。咱們將在數據庫上下文中爲 Asset 表添加一個屬性,這個屬性將會成爲 Asset 表的實體框架表明,用來建立腳本。在 ApplicationDbContext 類中添加新的屬性:
public class ApplicationDbContext : IdentityDbContext<applicationuser> { public ApplicationDbContext(): base("DefaultConnection", throwIfV1Schema: false) { } public DbSet<asset> Assets { get; set; } public static ApplicationDbContext Create() { return new ApplicationDbContext(); } }
以上是 ASP.NET identity 2.0 的默認實體框架設置,咱們經過爲 Asset 表添加新的 DbSet 來擴展它。
如今,在控制器文件夾中添加一個空的名爲 AssetController 的控制器,這個控制器件將用於全部 Asset 的相關工做。
public class AssetController : Controller { // GET: Asset public ActionResult Index() { return View(); }
如今咱們須要安裝用於建立表格的 JQuery DataTables,進入Tools >> NuGet Package Manager >> Manage Nuget Packages for Solution,並點擊它。
安裝包管理器默認是打開的,它會在你的解決方案中顯示成已安裝的 nugget 包,點擊瀏覽按鈕,而後搜索 JQuery DataTables 包,選擇它並檢查已安裝了 JQuery DataTables 的項目解決方案。在咱們的案例裏,咱們將會以每個需求的方式將其安裝在 GridExampleMVC web 中,而後點擊安裝按鈕。
Visual Studio 將會提示是否要修改解決方案,你須要點擊 Ok 來繼續安裝 JQuery DataTables 包。
在 nugget 包安裝成功後,咱們須要在視圖中引入 jQuery DataTables 的必要的 JS 和 CSS,爲此,咱們須要註冊 jQuery DataTables,請打開位於 App_Start 文件夾中的 BundleConfig.cs 文件並在 CSS 和 JS 文件的結尾處添加如下代碼:
bundles.Add(new ScriptBundle("~/bundles/datatables").Include( "~/Scripts/DataTables/jquery.dataTables.min.js", "~/Scripts/DataTables/dataTables.bootstrap.js")); bundles.Add(new StyleBundle("~/Content/datatables").Include( "~/Content/DataTables/css/dataTables.bootstrap.css"));
在爲數據表添加了腳本和 CSS 以後,咱們須要在整體佈局中添加它們,默認狀況下, _Layout.cshtml 位於 Views >> Shared 中,_ViewStart.cshtml 也默認位於這裏。
如今咱們開始安裝 datatables.mvc5,點擊 Tools >> NuGet Package Manager >> Manage Nuget Packages for Solution,並點擊它。
安裝包管理器默認是打開的,它會在你的解決方案中顯示成已安裝的 nugget 包,點擊瀏覽按鈕,而後搜索 DataTables.mvc5,選擇它並檢查想要安裝這個包的項目解決方案。這個時候,咱們開始在 GridExampleMVC Web 工程中安裝 DataTables.mvc5,點進安裝按鈕。
請在搜索結果中選擇正確的包並安裝它。
若是完成了包的安裝,你將會在工程中看到如下引用界面:
在寫控制器代碼以前,咱們須要爲實體框架配置鏈接字符串,以便在操做數據庫時來鏈接數據庫。所以,咱們的鏈接字符串應該被指定給一個有效的數據源,以便咱們在運行時應用不會被打斷。
爲了作到這一點,請打開 web.config 併爲數據庫提供鏈接字符串。在配置文件中,你會發現下面配置節點中的鏈接字符串,你須要在節點中根據你的系統來修改鏈接字符串。
<connectionstrings> <add connectionstring="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=GridExampleMVC; Integrated Security=True;MultipleActiveResultSets=true" name="DefaultConnection" providername="System.Data.SqlClient"/> </connectionstrings>
如今,請在控制器中添加數據庫上下文的屬性,以便咱們恩給你夠在數據庫中執行請求。
private ApplicationDbContext _dbContext; public ApplicationDbContext DbContext { get { return _dbContext ?? HttpContext.GetOwinContext().Get<applicationdbcontext>(); } private set { _dbContext = value; } }
咱們將會在任何須要的控制器行爲中,使用這個屬性查詢數據庫。
進入 Index.cshtml 文件並經過移除表單的 thead 和 tbody 元素來更新 HTML,更新 HTML 以下所示:
<div class="row"> <div class="col-md-12"> <div class="panel panel-primary list-panel" id="list-panel"> <div class="panel-heading list-panel-heading"> <h1 class="panel-title list-panel-title">Assets</h1> </div> <div class="panel-body"> <table id="assets-data-table" class="table table-striped table-bordered" style="width:100%;"> </table> </div> </div> </div> </div>
咱們刪除了表單的 head 和 body 元素,由於這些會經過數據表插件自身生成。如今咱們必須升級 jQuery 數據表初始化,以便它可以用過服務器端的 ajaxing 來加載數據。
爲此,在 Index.cshtml 視圖中添加一下代碼:
@section Scripts { <script type="text/javascript"> var assetListVM; $(function () { assetListVM = { dt: null, init: function () { dt = $('#assets-data-table').DataTable({ "serverSide": true, "processing": true, "ajax": { "url": "@Url.Action("Get","Asset")" }, "columns": [ { "title": "Bar Code", "data": "BarCode", "searchable": true }, { "title": "Manufacturer", "data": "Manufacturer", "searchable": true }, { "title": "Model", "data": "ModelNumber", "searchable": true }, { "title": "Building", "data": "Building", "searchable": true }, { "title": "Room No", "data": "RoomNo" }, { "title": "Quantity", "data": "Quantity" } ], "lengthMenu": [[10, 25, 50, 100], [10, 25, 50, 100]], }); } } // initialize the datatables assetListVM.init(); }); </script>
咱們已經在 init 函數中編寫了數據表初始化代碼,在 init 函數中,咱們設置 serverSide 屬性爲 true,這也就告訴表格會在服務器端進行分頁,過濾和排序,如今全部的數據不會馬上加載,而是第一頁數據會默認展現出來,更多的數據會當用戶觸發時才加載,處理的屬性會在檢索行爲中顯示這個加載過程。若是不想在數據加載時,顯示這樣的消息,能夠將它默認狀態設爲 false,接下來,咱們定義數據表的回調行爲,在咱們經過行屬性指定了須要展現的行以後,lengthMenu 則會用於顯示每頁數據的數目。當寫入 document.ready 文件時,assetListVM.init( ) 函數將會被調用。
接着,咱們將在 AssetController 中編寫 Get 行爲的代碼。首先咱們須要引用 System.Linq.Dynamic,以便在行爲中可使用動態連接方法。再一次進入 NuGet 包管理器搜索 System.Linq.Dynamic,並在項目中安裝它。
在完成安裝以後,進入 AssetController,編寫 Get 行爲的實現代碼:
public ActionResult Get([ModelBinder(typeof(DataTablesBinder))] IDataTablesRequest requestModel) { IQueryable<asset> query = DbContext.Assets; var totalCount = query.Count(); #region Filtering // Apply filters for searching if (requestModel.Search.Value != string.Empty) { var value = requestModel.Search.Value.Trim(); query = query.Where(p => p.Barcode.Contains(value) || p.Manufacturer.Contains(value) || p.ModelNumber.Contains(value) || p.Building.Contains(value) ); } var filteredCount = query.Count(); #endregion Filtering #region Sorting // Sorting var sortedColumns = requestModel.Columns.GetSortedColumns(); var orderByString = String.Empty; foreach (var column in sortedColumns) { orderByString += orderByString != String.Empty ? "," : ""; orderByString += (column.Data) + (column.SortDirection == Column.OrderDirection.Ascendant ? " asc" : " desc"); } query = query.OrderBy(orderByString == string.Empty ? "BarCode asc" : orderByString); #endregion Sorting // Paging query = query.Skip(requestModel.Start).Take(requestModel.Length); var data = query.Select(asset => new { AssetID = asset.AssetID, BarCode = asset.Barcode, Manufacturer = asset.Manufacturer, ModelNumber = asset.ModelNumber, Building = asset.Building, RoomNo = asset.RoomNo, Quantity = asset.Quantity }).ToList(); return Json(new DataTablesResponse(requestModel.Draw, data, filteredCount, totalCount), JsonRequestBehavior.AllowGet); }
咱們正在使用實體框架來訪問數據,但它不是強制性的,你也能夠經過 ADO.Net 來實現,惟一須要作的,就是從 DataTableResponse 實例行爲中返回 JSON , 若是在腳本中正肯定義了行,數據表就會正確的顯示數據。
咱們正在獲取 Assets 的引用,以便可以連接到實體框架請求數據,咱們能夠經過 Count()函數來獲取數據集表的數據數目,這個數據將會傳遞到 DataTablesResponse 構造函數中,成爲行爲方法的最後一行。
IQueryable<asset> query = DbContext.Assets; var totalCount = query.Count();
在這以後,咱們就有了經過用戶定義的標準來過濾數據的過濾邏輯了,如下的代碼具備自注釋:
if (requestModel.Search.Value != string.Empty) { var value = requestModel.Search.Value.Trim(); query = query.Where(p => p.Barcode.Contains(value) || p.Manufacturer.Contains(value) || p.ModelNumber.Contains(value) || p.Building.Contains(value) ); }
因此,咱們須要作的就是檢查用戶是否在文本框中設定了搜索標準,而後檢查全部列中是否符合標準的數據都返回了。
在這以後,咱們就實現了排序邏輯,排序列的信息附帶在使用自定義模型綁定的模型中,使用 System.Linq.Dynamic 咱們可以避免 if 和 switch 語句,咱們將列迭代在用戶請求的排序上,而且經過如下代碼排列行:
var sortedColumns = requestModel.Columns.GetSortedColumns(); var orderByString = String.Empty; foreach (var column in sortedColumns) { orderByString += orderByString != String.Empty ? "," : ""; orderByString += (column.Data) + (column.SortDirection == Column.OrderDirection.Ascendant ? " asc" : " desc"); } query = query.OrderBy(orderByString == string.Empty ? "BarCode asc" : orderByString);
最後,咱們應用分頁部分的功能,並檢查用戶選擇的頁面,默認會加載第一頁,在這以後,咱們將會經過 requestModel.Start 追蹤用戶點擊的每個頁面。requestModel.Length 將會告訴用戶查看的頁面有多少行數據,這個用戶可使用頁面中的 combo 框來進行配置。
在服務器端實現表格的過濾、分頁和排序等功能,可以減小客戶端數據處理的任務量,方便更好更快的加載並顯示數據。表格控件是項目開發中常常用到的控件,其中以性能著稱的是FlexGrid表格控件,這是一款輕量級的高性能表格控件,加載和滾動速度比競爭對手快10倍以上,能提供豐富的功能集,而不膨脹核心控件。
如今 build 這個工程並在瀏覽中運行,就能夠查看帶有服務器端過濾、分頁和排序的 GridView 了。
文章來源:by Ehsan Sajjad
原文連接:http://www.codeproject.com/Articles/1118363/GridView-with-Server-Side-Filtering-Sorting-and-Pa