断天涯大虾 发表于 2016-11-23 09:26:15

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

本帖最后由 断天涯大虾 于 2016-11-23 09:49 编辑

背景在前一篇文章《【初学者指南】在ASP.NET MVC 5中创建GridView》中,我们学习了如何在 ASP.NET MVC 中实现 GridView,类似于 ASP.NET web 表单的功能。通过前文,我们已经了解到使用U jQuery 插件的数据表可以很容易地实现具有搜索、排序和分页等重要功能的表格。http://images2015.cnblogs.com/blog/139239/201611/139239-20161122121505956-1834054116.png
前文中需要注意的是,所有通过插件实现的特性都是客户端的,这意味着所有的数据都首先在页面载入,然后由插件来处理客户端搜索、分页和排序的数据。如果数据表不是特别大,这么做是可以的;但是,如果数据表很大或者数据会随着应用的使用而不断增加,就会引起问题。如果这样的问题确实发生了,从长远来讲,这种创建表格方式将不是一个好选择。
介绍在本文中,我们将会学习如何实现服务器端的分页,搜索和排序功能。从长远来讲,这是一种更好的方式来应对数据集特别大的情况。我们将会修改前文中的源代码,现在就开始吧!
Datatables.MVC5首先,我们需要从 NuGet 包管理器中安装 datatables.mvc5。这是 Stefan Nuxoll 实现的绑定在控制器上的数据集模型。我们为什么需要这个包?这是由于绑定将会提供一个附着在控制器上的强类型的模型,这将有助于我们避免读取请求参数,也会将我们从请求的参数类型转换中解救出来。请求对象中的所有参数传递都不是安全类型的,所以我们必须手动的将它们转换到目的类型,这也将有助于开发人员专注于业务逻辑,而不用总是考虑 HTTP 参数,检查参数、转化参数。绑定的好处之一是:如果业务需要,可以在请求中发送一个自定义参数。你可以通过提供 IDataTablesRequest 来实现添加自定义的参数,你也需要重写它的 BindModel 和 MapAdditionalColumns 方法。
数据库创建现在让我们创建文章中会用到的数据库和表,打开 SQL Management Studio 并运行以下脚本:CREATE DATABASE
GO
CREATE TABLE . (
                      UNIQUEIDENTIFIER NOT NULL,
                      NVARCHAR (MAX)   NULL,
               NVARCHAR (MAX)   NULL,
               NVARCHAR (MAX)   NULL,
                      NVARCHAR (MAX)   NULL,
                        NVARCHAR (MAX)   NOT NULL,
                   NVARCHAR (MAX)   NULL,
      NVARCHAR (MAX)   NULL,
    NVARCHAR (MAX)   NULL,
                     INT            NOT NULL,
               NVARCHAR (MAX)   NULL,
                  NVARCHAR (MAX)   NULL,
                     NVARCHAR (MAX)   NULL,
                        NVARCHAR (MAX)   NULL,
                     NVARCHAR (MAX)   NULL,
                     NVARCHAR (MAX)   NULL,
                        NVARCHAR (MAX)   NULL,
                  NVARCHAR (MAX)   NULL,
                     NVARCHAR (MAX)   NULL,
                     BIT            NOT NULL,
   CONSTRAINT PRIMARY KEY CLUSTERED ( ASC)
)
GO这是附属在源代码上的一个完整的 SQL 脚本文件,可以用它使用简单的数据来创建数据库和表。
设置项目现在,创建一个新的 ASP.NET MVC 5 Web 应用程序。打开 Visual Studio 2015,点击文件>>新建>>项目。http://images2015.cnblogs.com/blog/139239/201611/139239-20161122121523534-940808168.png从该对话框中,跳转到 Web,并选择 ASP.NET Web 应用程序项目,然后单击确定。http://images2015.cnblogs.com/blog/139239/201611/139239-20161122121546565-1500988117.png在模板页面,选择 MVC,如果编写了单元测试,请先做检查,然后点击确定。我们的工程都是用基本的功能创建的。现在,我们开始创建数据库上下文类,这个类将会被Data Access实体框架使用。
创建模型和数据访问首先,我们需要为 Asset 表创建一个模型,我们将会使用这个模型通过 ORM 来恢复数据。在模型文件夹中,创建一个名为 Asset 的新类:using System.ComponentModel.DataAnnotations;
namespace GridExampleMVC.Models
{
    public class Asset
    {
      public System.Guid AssetID { get; set; }
      
      public string Barcode { get; set; }
      
      public string SerialNumber { get; set; }
      
      public string FacilitySite { get; set; }
      
      public string PMGuide { get; set; }
      
      
      public string AstID { get; set; }
      
      public string ChildAsset { get; set; }
      
      public string GeneralAssetDescription { get; set; }
      
      public string SecondaryAssetDescription { get; set; }
      public int Quantity { get; set; }
      
      public string Manufacturer { get; set; }
      [Display(Name = "Model-Number")
      public string ModelNumber { get; set; }
      
      public string Building { get; set; }
      
      public string Floor { get; set; }
      
      public string Corridor { get; set; }
      
      public string RoomNo { get; set; }
      
      public string MERNo { get; set; }
      
      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 数据表的安装现在我们需要安装用于创建表格的 JQuery DataTables,进入Tools >> NuGet Package Manager >> Manage Nuget Packages for Solution,并点击它。http://images2015.cnblogs.com/blog/139239/201611/139239-20161122121616675-1019341520.png安装包管理器默认是打开的,它会在你的解决方案中显示成已安装的 nugget 包,点击浏览按钮,然后搜索 JQuery DataTables 包,选择它并检查已安装了 JQuery DataTables 的项目解决方案。在我们的案例里,我们将会以每一个需求的方式将其安装在 GridExampleMVC web 中,然后点击安装按钮。http://images2015.cnblogs.com/blog/139239/201611/139239-20161122121633081-232481813.pngVisual 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 也默认位于这里。http://images2015.cnblogs.com/blog/139239/201611/139239-20161122121702143-1046914365.png
安装 Datatables.net 包现在我们开始安装 datatables.mvc5,点击 Tools >> NuGet Package Manager >> Manage Nuget Packages for Solution,并点击它。安装包管理器默认是打开的,它会在你的解决方案中显示成已安装的 nugget 包,点击浏览按钮,然后搜索 DataTables.mvc5,选择它并检查想要安装这个包的项目解决方案。这个时候,我们开始在 GridExampleMVC Web 工程中安装 DataTables.mvc5,点进安装按钮。http://images2015.cnblogs.com/blog/139239/201611/139239-20161122121759300-1118691265.png请在搜索结果中选择正确的包并安装它。http://images2015.cnblogs.com/blog/139239/201611/139239-20161122121848987-1356184031.png如果完成了包的安装,你将会在工程中看到以下引用界面:http://images2015.cnblogs.com/blog/139239/201611/139239-20161122121859487-320356372.png
配置数据库的连接字符串在写控制器代码之前,我们需要为实体框架配置连接字符串,以便在操作数据库时来连接数据库。因此,我们的连接字符串应该被指定给一个有效的数据源,以便我们在运行时应用不会被打断。为了做到这一点,请打开 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;
    }
}
我们将会在任何需要的控制器行为中,使用这个属性查询数据库。<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": [, ],
                  });
                }
            }
            // initialize the datatables
            assetListVM.init();
      });
</script>
我们已经在 init 函数中编写了数据表初始化代码,在 init 函数中,我们设置 serverSide 属性为 true,这也就告诉表格会在服务器端进行分页,过滤和排序,现在所有的数据不会立刻加载,而是第一页数据会默认展示出来,更多的数据会当用户触发时才加载,处理的属性会在检索行为中显示这个加载过程。如果不想在数据加载时,显示这样的消息,可以将它默认状态设为 false,接下来,我们定义数据表的回调行为,在我们通过行属性指定了需要展示的行之后,lengthMenu 则会用于显示每页数据的数目。当写入 document.ready 文件时,assetListVM.init( ) 函数将会被调用。
安装 System.Linq.Dynamic 包接着,我们将在 AssetController 中编写 Get 行为的代码。首先我们需要引用 System.Linq.Dynamic,以便在行为中可以使用动态链接方法。再一次进入 NuGet 包管理器搜索 System.Linq.Dynamic,并在项目中安装它。http://images2015.cnblogs.com/blog/139239/201611/139239-20161122121927112-1046863481.png实现控制器中的排序、筛选和分页在完成安装之后,进入 AssetController,编写 Get 行为的实现代码:public ActionResult Get( 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 框来进行配置。
现在 build 这个工程并在浏览中运行,就可以查看带有服务器端过滤、分页和排序的 GridView 了。表格控件是项目开发中经常用到的控件,其中以性能著称的是FlexGrid表格控件,这是一款轻量级的高性能表格控件,加载和滚动速度比竞争对手快10倍以上,能提供丰富的功能集,而不膨胀核心控件。文章来源:by Ehsan Sajjad原文链接:http://www.codeproject.com/Artic ... ring-Sorting-and-Pa
页: [1]
查看完整版本: 在ASP.NET MVC5中实现具有服务器端过滤、排序和分页的GridView