背景

在前一篇文章《【初学者指南】在ASP.NET MVC 5中创建GridView》中,我们学习了如何在 ASP.NET MVC 中实现 GridView,类似于 ASP.NET web 表单的功能。通过前文,我们已经了解到使用 jQuery 插件的数据表可以很容易地实现具有搜索、排序和分页等重要功能的表格。

前文中需要注意的是,所有通过插件实现的特性都是客户端的,这意味着所有的数据都首先在页面载入,然后由插件来处理客户端搜索、分页和排序的数据。如果数据表不是特别大,这么做是可以的;但是,如果数据表很大或者数据会随着应用的使用而不断增加,就会引起问题。如果这样的问题确实发生了,从长远来讲,这种创建表格方式将不是一个好选择。

介绍

在本文中,我们将会学习如何实现服务器端的分页,搜索和排序功能。从长远来讲,这是一种更好的方式来应对数据集特别大的情况。

我们将会修改前文中的源代码,现在就开始吧!

Datatables.MVC5

首先,我们需要从 NuGet 包管理器中安装 datatables.mvc5。这是 Stefan Nuxoll 实现的绑定在控制器上的数据集模型。我们为什么需要这个包?这是由于绑定将会提供一个附着在控制器上的强类型的模型,这将有助于我们避免读取请求参数,也会将我们从请求的参数类型转换中解救出来。请求对象中的所有参数传递都不是安全类型的,所以我们必须手动的将它们转换到目的类型,这也将有助于开发人员专注于业务逻辑,而不用总是考虑 HTTP 参数,检查参数、转化参数。

绑定的好处之一是:如果业务需要,可以在请求中发送一个自定义参数。

你可以通过提供 IDataTablesRequest 来实现添加自定义的参数,你也需要重写它的 BindModel 和 MapAdditionalColumns 方法。

数据库创建

现在让我们创建文章中会用到的数据库和表,打开 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 脚本文件,可以用它使用简单的数据来创建数据库和表。

设置项目

现在,创建一个新的 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: Assetpublic ActionResult Index(){return View();}

jQuery 数据表的安装

现在我们需要安装用于创建表格的 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.net 包

现在我们开始安装 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>

jQuery 数据表初始化

我们删除了表单的 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 datatablesassetListVM.init();});
</script>

我们已经在 init 函数中编写了数据表初始化代码,在 init 函数中,我们设置 serverSide 属性为 true,这也就告诉表格会在服务器端进行分页,过滤和排序,现在所有的数据不会立刻加载,而是第一页数据会默认展示出来,更多的数据会当用户触发时才加载,处理的属性会在检索行为中显示这个加载过程。如果不想在数据加载时,显示这样的消息,可以将它默认状态设为 false,接下来,我们定义数据表的回调行为,在我们通过行属性指定了需要展示的行之后,lengthMenu 则会用于显示每页数据的数目。当写入 document.ready 文件时,assetListVM.init( ) 函数将会被调用。

安装 System.Linq.Dynamic 包

接着,我们将在 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 searchingif (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// Sortingvar 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// Pagingquery = 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 框来进行配置。

现在 build 这个工程并在浏览中运行,就可以查看带有服务器端过滤、分页和排序的 GridView 了。

在服务器端实现表格的过滤、分页和排序等功能,能够减少客户端数据处理的任务量,方便更好更快的加载并显示数据。表格控件是项目开发中经常用到的控件,其中以性能著称的是FlexGrid表格控件,这是一款轻量级的高性能表格控件,加载和滚动速度比竞争对手快10倍以上,能提供丰富的功能集,而不膨胀核心控件。

文章来源:by Ehsan Sajjad

原文链接:http://www.codeproject.com/Articles/1118363/GridView-with-Server-Side-Filtering-Sorting-and-Pa

相关阅读:

是什么让C#成为最值得学习的编程语言

从Visual Studio看微软20年技术变迁

C#开发人员应该知道的13件事情

Visual Studio 2017正式版发布全纪录

在ASP.NET MVC5中实现具有服务器端过滤、排序和分页的GridView相关推荐

  1. mvc5中在 html,解决ASP.NET MVC5中出现在XX 字段是必需的错误。@Html.ValidationSummary()...

    ASP.NET mvc5中的Model有内置的一套验证机制尤其是一些非字符串类型的字段,如时间类型. 当使用@Html.ValidationSummary()时,如果你自己加了一些验证手动加Model ...

  2. 在ASP.NET MVC5中使用特性路由

    首先在RegisterRoutes时开启特性路由功能: routes.MapMvcAttributeRoutes(); 然后,就可以使用了. 更多内容请详阅:http://blogs.msdn.com ...

  3. MVC5中Model层开发数据注解

    ASP.NET MVC5中Model层开发,使用的数据注解有三个作用: 数据映射(把Model层的类用EntityFramework映射成对应的表) 数据验证(在服务器端和客户端验证数据的有效性) 数 ...

  4. 在 asp.net mvc中的简单分页算法 (续)

    在上个月发表的 http://www.cnblogs.com/bwangel/p/mvcpager.html 中,讨论了一下asp.net mvc中结合Entity framework框架进行的分页, ...

  5. ASP.NET MVC5使用Area区域

    转载:http://www.lanhusoft.com/Article/217.html 在大型的ASP.NET mvc5项目中一般都有许多个功能模块,这些功能模块可以用Area(中文翻译为区域)把它 ...

  6. asp.net 2中的图片上传

    BETA 2出来了,暂时还没得到,因此还是用BETA 1研究.在asp.net 2中,如何实现图片的上传展示呢?下面,我用GRIDVIEW搭配文件上传功能进行实现(而实现文件上传的原理大致一样).在A ...

  7. ASP.NET MVC5 + EF6 入门教程 (6) View中的Razor使用

    ASP.NET MVC5 + EF6 入门教程 (6) View中的Razor使用 原文:ASP.NET MVC5 + EF6 入门教程 (6) View中的Razor使用 文章来源: Slark.N ...

  8. 现存问题以及解决方案:在ASP.NET AJAX中从客户端向服务器端传送DataTable

    摘要 在<现存问题以及解决方案:在ASP.NET AJAX客户端得到服务器端的DataTable>这篇文章中,我给出了一个在ASP.NET AJAX中从服务器端得到客户端DataTable ...

  9. ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(持续更新中...)

    开发工具:VS2015(2012以上)+SQL2008R2以上数据库  您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB  升级后界面效果如下: 日程管理   http:// ...

最新文章

  1. 网页MSN,QQ,Skype,贸易通,雅虎通在线客服代码合集
  2. QDoc标记命令Markup Commands
  3. JVM笔记(JVM内存+垃圾回收器)详解
  4. Chrome浏览器报错:Origin null is not allowed by Access-Control-Allow-Origin.
  5. 像亲和数一样亲密无间(洛谷P1851题解,Java语言描述)
  6. 西安外国语大学计算机基础,西安外国语大学教务处.PDF
  7. python 字典默认会引用 除非深拷贝
  8. jpa 原生sql 查询返回一个实体_JPA查询--使用原生sql 并且把查询结果转为实体对象...
  9. No module named ‘win32gui‘ 的解决方法(踩坑之旅)
  10. Matlab中(),[],与{}的用法认识
  11. 诗意的边缘(PHP顶级框架Zend Fr
  12. 用vue写一个仿简书的轮播图
  13. ES6、7学习笔记(尚硅谷)-6-形参默认值的设置
  14. sas 安装后处理出错
  15. 以太网转串口代码C语言,基于STM32 串口转以太网收发数据(stm32移植代码+网络调试助手等)...
  16. 数学建模笔记(三)论文写作:论文排版
  17. P2P网贷黎明前夕的黑夜---P2P是否要被封杀呢
  18. bcdedit添加linux引导,利用Bcdedit创建Linux系统引导
  19. Linux下载ncbi的SRA文件
  20. 阿里聚安全发布 企业可享淘宝同款防护

热门文章

  1. java reduce 分组_使用JAVA8 stream中三个参数的reduce方法对List进行分组统计
  2. 安卓 App 库存系统开发 开发成本估计
  3. 计算机做减法运算的过程,32位汇编基础_计算机做加减乘除
  4. 浅谈智能卡加密芯片在智能设备领域的技术运用
  5. 浅谈过程和结果的关系
  6. VB 子类化技术详解
  7. 80后的十三种最深寂寞
  8. 网络中的那些事儿(二)之总体规划
  9. 围观电动车极端测试,是一种怎样的体验?
  10. 零基础入门神经网络:从原理、主要类型到行业应用