如何在 ASP.net Core 中实现 dataTables 服务器端分页/搜索/排序
Posted
技术标签:
【中文标题】如何在 ASP.net Core 中实现 dataTables 服务器端分页/搜索/排序【英文标题】:How to implement dataTables Server side Side Paging/Searching/Sorting in ASP.net Core 【发布时间】:2020-07-20 13:38:08 【问题描述】:我正在尝试从 jQuery Datatable 的服务器端执行搜索、排序、分页,我已经写过 遵循代码,但我无法获取用于排序的参数,从数据表搜索到我的 MVC 控制器。 这是我的代码。
我的数据表看起来像...
<script>
$(document).ready(function ()
$("#newT").DataTable(
ajax:
url: '@Url.Action("Prods", "NewTest")',
method: 'post',
dataType: 'json',
dataSrc : ''
,
columns: [
title: 'Id',
data: 'id',
searchable: false,
sortable: false,
visible: false
,
title: 'Name',
data: 'name',
render: function (data, type, row)
return '<a id="' + row.id + '" href="javascript:void(0)" onclick="detailsClick(this)">' + data + '</a>'
,
....Other Columns....
],
serverSide: true,
processing: true,
language:
processing : "Please Wait ..."
)
)
</script>
这是我的 MVC 控制器
public IActionResult Prods()
int draw = Convert.ToInt32(Request.Query["draw"]);
int StartIndex = Convert.ToInt32(Request.Query["start"]);
int PageSize = Convert.ToInt32(Request.Query["length"]);
int SortCol = Convert.ToInt32(Request.Query["order[0][column]"]);
string SortDir = Request.Query["order[0][dir]"];
string SearchField = Request.Query["search[value]"].FirstOrDefault()?.Trim();
..... Further Implementation .....
return new JsonResult(new
data = filteredData,
draw = Request.Query["draw"],
recordsFiltered = filteredData.Count(),
recordsTotal = 13
);
我在 Controller 中得到了空值,请帮帮我。
【问题讨论】:
【参考方案1】:在 NuGet 中已经有几个用于 jquery 数据表的 .NET Core 实现。它具有将数据表请求连接到 MVC 所需的所有模型和绑定。
我用过这个:https://www.nuget.org/packages/DataTables.AspNet.AspNetCore/。
这是在 ASP.NET Core MVC 应用程序中使用它的方法:
1。安装 DataTables.js
使用您最喜欢的客户端包管理器安装 DataTables.js 库(以及它的依赖项 jQuery)。 DataTables 还附带couple styles,因此它们将拥有自己的包。你也需要得到它。
我用了npm
,直接在package.json
里面做了:
"version": "1.0.0",
...,
"dependencies":
...,
"jquery": "3.5.1",
"datatables.net": "1.10.21",
"datatables.net-bs4": "1.10.21"
,
"devDependencies":
...
这些包将被拉入您项目中的隐藏文件夹node_modules
。
2。将静态文件移动到 wwwroot
在 ASP.NET Core MVC 应用程序中,为了提供任何 JavaScript 或 css 文件,您需要在 Startup 类中注册 app.UseStaticFiles()
,并使用任何 Task Runner 将文件移动到 wwwroot 文件夹。
namespace DL.NetCore.EmptySolution.Web.UI
public class Startup
...
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
...
app.UseStaticFiles();
...
我使用了gulp
,但你可以使用任何你想要的东西。我在项目中只有一个gulpfile.js
,Visual Studio 的任务运行程序将获取它:
const bundleAndMinify = (srcFiles, destFileName, destPath, minifier) =>
src(srcFiles)
.pipe(concat(destFileName))
.pipe(dest(destPath))
.pipe(minifier())
.pipe(rename( suffix: '.min' ))
.pipe(dest(destPath));
;
const copyDatatablesScripts = done =>
bundleAndMinify(
[
'node_modules/datatables.net/js/jquery.dataTables.js',
'assets/js/dataTables.bootstrap4.custom.js'
],
'jquery.dataTables.js',
'wwwroot/js',
terser
);
done();
;
const copyDatatablesStyles = done =>
bundleAndMinify(
[
'node_modules/datatables.net-bs4/css/dataTables.bootstrap4.css',
'assets/css/dataTables.bootstrap4.custom.css'
],
'jquery.dataTables.css',
'wwwroot/css',
cssmin
);
done();
;
我进行了自定义设置,因为我想更改排序图标并添加搜索文件延迟扩展,因此我在资产文件夹中拥有自己的自定义 dataTables.bootstrap4.custom.js
和 assets/css/dataTables.bootstrap4.custom.css
。
但对于基本安装,您只需要:
脚本: node_modules/jquery/dist/jquery.js node_modules/datatables.net/js/jquery.dataTables.js node_modules/datatables.net-bs4/js/dataTables.bootstrap4.js 款式: node_modules/datatables.net-bs4/css/dataTables.bootstrap4.css在 wwwroot 中拥有这些静态文件后,您可以将这些脚本和样式包含在要运行 DataTables.js 库的任何页面中:
@section css
<!-- jquery.dataTables styles -->
<environment include="development">
<link rel="stylesheet" href="~/css/jquery.dataTables.css" />
</environment>
<environment exclude="development">
<link rel="stylesheet" href="~/css/jquery.dataTables.min.css" />
</environment>
@section scripts
<!-- jquery.dataTables scripts -->
<environment include="development">
<script src="~/js/jquery.dataTables.js"></script>
</environment>
<environment exclude="development">
<script src="~/js/jquery.dataTables.min.js"></script>
</environment>
...
注意:在gulpfile.js
中,您可以看到我将脚本文件捆绑到一个名为jquery.dataTables.js
的单个文件中,并将样式打包到一个名为jquery.dataTables.css
的单个文件中。这就是为什么我在页面上只引用这两个文件的原因。
3。安装 DataTables NuGet 包
右键单击您的项目并打开 NuGet 管理器。搜索“DataTables.AspNet.AspNetCore”并单击安装。它也会自动下载其依赖项。
4。注册 DataTables NuGet 包
在您可以使用 NuGet 包之前,您需要注册它。这可能是您的错误的来源:
namespace DL.NetCore.EmptySolution.Web.UI
public class Startup
...
public void ConfigureServices(IServiceCollection services)
services
.AddRouting(options => options.LowercaseUrls = true)
.AddControllersWithViews();
services.RegisterDataTables();
它会为你添加模态绑定,这样你就不必自己手动绑定那么多DataTables请求参数了。
5。玩得开心!
现在,您可以使用 IDataTablesRequest
参数从 DataTables.js 库中简单地声明任何用作 AJAX 调用的 MVC 操作。这将捕获 Request.Query["start"]
、Request.Query["length"]
等内容。感谢 DataTables NuGet 包!
在你处理完数据后,你只需要创建一个DataTablesJsonResult()
返回给客户端:
namespace DL.NetCore.EmptySolution.Web.UI.Controllers
public class ProductController : Controller
public IActionResult Index()
return View();
[HttpPost]
public IActionResult GetList(IDataTablesRequest request)
// Get products from your persistance store
var products = GetFakeProducts();
// Convert them into view models
var rows = new List<ProductListRowViewModel>();
// foreach product in products ...
// Filter them
var filteredRows = rows
.AsQueryable()
.GlobalFilterBy(request.Search, request.Columns);
// Sort and paginate them
var pagedRows = filteredRows
.SortBy(request.Columns)
.Skip(request.Start)
.Take(request.Length);
var response = DataTablesResponse.Create(request, rows.Count,
filteredRows.Count(), pagedRows);
return new DataTablesJsonResult(response);
您可以看到DataTables.js从客户端发送的所有信息都被捕获并转换为IDataTablesRequest
,您可以获取任何您需要的信息:
@
ViewBag.Title = "Products";
<h2>Products</h2>
...
<div class="table-responsive">
<table id="table-products" class="table">
...
</table>
</div>
...
@section scripts
...
<script type="text/javascript">
$(function()
$('#table-products').dataTable(
serverSide: true,
ajax:
url: '@Url.Action("getList", "product", new area = "" )',
type: 'POST'
,
processing: true,
order: [1, 'asc'],
columns: [...]
).fnSetFilteringDelay(1000);
);
</script>
截图
工作演示
https://github.com/davidliang2008/DL.NetCore.EmptySolution
奖励:应用 DataTables 过滤和排序的扩展方法
我还针对 IQueryable
集合创建了 2 个扩展方法来处理 DataTables.js 中的过滤和排序:
namespace DL.NetCore.EmptySolution.Web.Common.DataTables.Extensions
public static class QueryableExtensions
public static IQueryable<T> SortBy<T>(this IQueryable<T> source,
IEnumerable<IColumn> columns)
Expression expression = source.Expression;
bool firstTime = true;
var sortedColumns = columns
.Where(x => x.IsSortable && x.Sort != null)
.OrderBy(x => x.Sort.Order);
foreach (var sortedColumn in sortedColumns)
var parameter = Expression.Parameter(typeof(T), "x");
var selector = Expression.PropertyOrField(parameter, sortedColumn.Field);
var lambda = Expression.Lambda(selector, parameter);
var method = sortedColumn.Sort.Direction == SortDirection.Descending
? firstTime ? "OrderByDescending" : "ThenByDescending"
: firstTime ? "OrderBy" : "ThenBy";
expression = Expression.Call(
typeof(Queryable),
method,
new Type[] source.ElementType, selector.Type ,
expression,
Expression.Quote(lambda)
);
firstTime = false;
return firstTime
? source
: source.Provider.CreateQuery<T>(expression);
public static IQueryable<T> GlobalFilterBy<T>(this IQueryable<T> source,
ISearch search, IEnumerable<IColumn> columns)
if (search == null || String.IsNullOrWhiteSpace(search.Value))
return source;
var searchableColumns = columns
.Where(x => x.IsSearchable);
if (!searchableColumns.Any())
return source;
Expression predicateBody = null;
var parameter = Expression.Parameter(typeof(T), "x");
foreach (var column in searchableColumns)
// We want to build
// x.Field != default
// && x.Field.ToString().IndexOf(search.Value, StringComparison.InvariantCultureIgnoreCase) >= 0
// for each searchable column
var selector = Expression.PropertyOrField(parameter, column.Field);
var left = Expression.NotEqual(
selector,
Expression.Default(selector.Type)
);
var toString = Expression.Call(
selector,
selector.Type.GetMethod("ToString", System.Type.EmptyTypes)
);
var indexOf = Expression.Call(
toString,
typeof(string).GetMethod("IndexOf", new Type[] typeof(string), typeof(StringComparison) ),
Expression.Constant(search.Value),
Expression.Constant(StringComparison.InvariantCultureIgnoreCase)
);
var right = Expression.GreaterThanOrEqual(
indexOf,
Expression.Constant(0)
);
var andExpression = Expression.AndAlso(left, right);
predicateBody = predicateBody == null
? andExpression
: Expression.OrElse(predicateBody, andExpression);
if (predicateBody == null)
return source;
var lambda = Expression.Lambda<Func<T, bool>>(predicateBody, parameter);
var whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] source.ElementType ,
source.Expression,
lambda
);
return source.Provider.CreateQuery<T>(whereCallExpression);
它们非常方便地从 DataTables.js 中获取可搜索和可排序的列,动态构建表达式树并应用于您的源集合!
抱歉,这里太长了……
【讨论】:
谢谢,大卫,这将有很大帮助,但你能否提供任何有效的演示,我可以联系到我收到一个错误 ::InvalidOperationException: Could not create an instance of type 'DataTables.AspNet.Core.IDataTablesRequest'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the 'request' parameter a non-null default value.
@MaulikDave:我正在做一个演示,但工作太忙了。会及时通知您。
@MaulikDave:对不起,我太忙了,但你来了!我已经用详细说明更新了我的答案,并在我的 Github 中提供了我工作演示的链接。玩得开心。
非常感谢您提供如此广泛的演示,这将有很大帮助,对此非常感谢。【参考方案2】:
我无法获取排序参数,从数据表搜索到我的 MVC 控制器。
如果你使用F12开发工具Network抓取到NewTest/Prods
action方法的请求,你会发现服务端处理相关数据是通过表单数据传递的,而不是在url的查询字符串部分。
要在控制器操作中获取这些数据,您可以尝试:
int draw = Convert.ToInt32(Request.Form["draw"]);
int StartIndex = Convert.ToInt32(Request.Form["start"]);
int PageSize = Convert.ToInt32(Request.Form["length"]);
int SortCol = Convert.ToInt32(Request.Form["order[0][column]"]);
string SortDir = Request.Form["order[0][dir]"];
string SearchField = Request.Form["search[value]"].FirstOrDefault()?.Trim();
测试结果
【讨论】:
我知道这是旧版本并且有更新的版本,但是当我检查我的 Chrome 开发工具时,我看到像“搜索[对象对象]”和“列”这样发布的值[object object]”而不是您在屏幕截图中显示的内容。有谁知道为什么会这样?编辑:我应该补充一点,因为它们只是“[object object]”的字符串值,它们无法在后端解析。 上述问题的解决方案是我发现我们在使用 DataTables 测试的文件中使用了“jQuery.ajaxSettings.traditional = true”。删除/评论解决了发布值的问题。以上是关于如何在 ASP.net Core 中实现 dataTables 服务器端分页/搜索/排序的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ASP.net Core 中实现 dataTables 服务器端分页/搜索/排序
在 ASP.NET Core 2.1 Web API 中实现分页