ASP.NET Core 3.1 中的数据表服务器端处理
Posted
技术标签:
【中文标题】ASP.NET Core 3.1 中的数据表服务器端处理【英文标题】:Datatables server-side processing in ASP.NET Core 3.1 【发布时间】:2021-01-25 06:31:46 【问题描述】:我是 Datatables 的 AJAX 调用新手。我需要为数千条记录实现服务器端处理。我正在学习一个教程,但我在某处对服务器端处理感到困惑。
我在尝试从数据源呈现数据时遇到错误。让我发布所有相关代码,希望你能帮助我找出我哪里出错了。由于我是 Datatables 和 Ajax 的新手,我将感谢更多的示例、文本答案以及代码或链接到在 ASP.NET CORE 3.1 中演示服务器端处理的教程。
感谢您的宝贵时间和帮助。
注意。我从教程中获取了实现和配置,并尝试对其进行自定义。
下面是 HTML 表格及其模型:
@model IEnumerable<StudentApplications>
<table id="custom-datatable" class="mb-5 display table table-bordered" style="width:100%">
<thead>
<tr>
<th>
@html.DisplayNameFor(model => model.ApplicationId)
</th>
<th>
@Html.DisplayNameFor(model => model.Firstname)
</th>
<th>
@Html.DisplayNameFor(model => model.Surname)
</th>
<th>
@Html.DisplayNameFor(model => model.ApplicationFor)
</th>
<th>
@Html.DisplayNameFor(model => model.SubmissionDate)
</th>
<th></th>
</tr>
</thead>
<tfoot>
<tr>
<th>
@Html.DisplayNameFor(model => model.ApplicationId)
</th>
<th>
@Html.DisplayNameFor(model => model.Firstname)
</th>
<th>
@Html.DisplayNameFor(model => model.Surname)
</th>
<th>
@Html.DisplayNameFor(model => model.ApplicationFor)
</th>
<th>
@Html.DisplayNameFor(model => model.SubmissionDate)
</th>
<th></th>
</tr>
</tfoot>
</table>
以下是将 HTML 表初始化为数据表的 javascript 文件和一些配置:
$(document).ready(function ()
$('#custom-datatable').DataTable(
// Design Assets
stateSave: true,
autoWidth: true,
// ServerSide Setups
processing: true,
serverSide: true,
// Paging Setups
paging: true,
// Searching Setups
searching: regex: true ,
// Ajax Filter
ajax:
url: "/myapplications/data",
type: "POST",
contentType: "application/json",
dataType: "json",
data: function (d)
return JSON.stringify(d);
,
// Columns Setups
columns: [
data: "ApplicationId" ,
data: "Firstname" ,
data: "Surname" ,
data: "ApplicationFor" ,
data: "SubmissionDate"
//// For Student.Id
// "data": "applicationId", "name": "ApplicationId" ,
//// For Student.Firstname
// "data": "firstname", "name": "Firstname" ,
//// For Student.Surname
// "data": "surname", "name": "Surname" ,
//// For Student.ApplicationFor
// "data": "applicationFor", "name": "ApplicationFor" ,
//// For Student.SubmissionDate
// "data": "submissionDate", "name": "SubmissionDate"
],
// Column Definitions
columnDefs: [
targets: "no-sort", orderable: false ,
targets: "no-search", searchable: false ,
targets: "trim",
render: function (data, type, full, meta)
if (type === "display")
data = strtrunc(data, 10);
return data;
,
targets: "date-type", type: "date-eu" ,
targets: 10,
data: null,
orderable: false
,
]
);
);
以下是获取数据的方法:
// loading datatable
[HttpPost]
[Route("myapplications/data")]
public async Task<IActionResult> Data([FromBody] DtParameters dtParameters)
searchBy = dtParameters.Search?.Value;
// if we have an empty search then just order the results by Id ascending
var orderCriteria = "ApplicationId";
var orderAscendingDirection = true;
if (dtParameters.Order != null)
// in this example we just default sort on the 1st column
orderCriteria = dtParameters.Columns[dtParameters.Order[0].Column].Data;
orderAscendingDirection = dtParameters.Order[0].Dir.ToString().ToLower() == "asc";
var result = context.AspNetStudentApplications.AsQueryable();
if (!string.IsNullOrEmpty(searchBy))
result = result.Where(r => r.ApplicationId != null && r.ApplicationId.ToUpper().Contains(searchBy.ToUpper()) ||
r.Firstname != null && r.Firstname.ToUpper().Contains(searchBy.ToUpper()) ||
r.Surname != null && r.Surname.ToUpper().Contains(searchBy.ToUpper()) ||
r.ApplicationFor != null && r.ApplicationFor.ToUpper().Contains(searchBy.ToUpper()) ||
r.SubmissionDate != null && r.SubmissionDate.ToUpper().Contains(searchBy.ToUpper()));
result = orderAscendingDirection ? result.OrderByDynamic(orderCriteria, DtOrderDir.Asc) : result.OrderByDynamic(orderCriteria, DtOrderDir.Desc);
// now just get the count of items (without the skip and take) - eg how many could be returned with filtering
var filteredResultsCount = await result.CountAsync();
var totalResultsCount = await context.AspNetStudentApplications.CountAsync();
return Json(new DtResult<StudentApplications>
Draw = dtParameters.Draw,
RecordsTotal = totalResultsCount,
RecordsFiltered = filteredResultsCount,
Data = await result
.Skip(dtParameters.Start)
.Take(dtParameters.Length)
.ToListAsync()
);
下面是 DtParameters 类和其他与 Datatables 相关的类:
/// <summary>
/// A full result, as understood by jQuery DataTables.
/// </summary>
/// <typeparam name="T">The data type of each row.</typeparam>
public class DtResult<T>
/// <summary>
/// The draw counter that this object is a response to - from the draw parameter sent as part of the data request.
/// Note that it is strongly recommended for security reasons that you cast this parameter to an integer, rather than simply echoing back to the client what it sent in the draw parameter, in order to prevent Cross Site Scripting (XSS) attacks.
/// </summary>
[JsonProperty("draw")]
public int Draw get; set;
/// <summary>
/// Total records, before filtering (i.e. the total number of records in the database)
/// </summary>
[JsonProperty("recordsTotal")]
public int RecordsTotal get; set;
/// <summary>
/// Total records, after filtering (i.e. the total number of records after filtering has been applied - not just the number of records being returned for this page of data).
/// </summary>
[JsonProperty("recordsFiltered")]
public int RecordsFiltered get; set;
/// <summary>
/// The data to be displayed in the table.
/// This is an array of data source objects, one for each row, which will be used by DataTables.
/// Note that this parameter's name can be changed using the ajax option's dataSrc property.
/// </summary>
[JsonProperty("data")]
public IEnumerable<T> Data get; set;
/// <summary>
/// Optional: If an error occurs during the running of the server-side processing script, you can inform the user of this error by passing back the error message to be displayed using this parameter.
/// Do not include if there is no error.
/// </summary>
[JsonProperty("error", NullValueHandling = NullValueHandling.Ignore)]
public string Error get; set;
public string PartialView get; set;
/// <summary>
/// The additional columns that you can send to jQuery DataTables for automatic processing.
/// </summary>
public abstract class DtRow
/// <summary>
/// Set the ID property of the dt-tag tr node to this value
/// </summary>
[JsonProperty("DT_RowId")]
public virtual string DtRowId => null;
/// <summary>
/// Add this class to the dt-tag tr node
/// </summary>
[JsonProperty("DT_RowClass")]
public virtual string DtRowClass => null;
/// <summary>
/// Add the data contained in the object to the row using the jQuery data() method to set the data, which can also then be used for later retrieval (for example on a click event).
/// </summary>
[JsonProperty("DT_RowData")]
public virtual object DtRowData => null;
/// <summary>
/// Add the data contained in the object to the row dt-tag tr node as attributes.
/// The object keys are used as the attribute keys and the values as the corresponding attribute values.
/// This is performed using using the jQuery param() method.
/// Please note that this option requires DataTables 1.10.5 or newer.
/// </summary>
[JsonProperty("DT_RowAttr")]
public virtual object DtRowAttr => null;
/// <summary>
/// The parameters sent by jQuery DataTables in AJAX queries.
/// </summary>
public class DtParameters
/// <summary>
/// Draw counter.
/// This is used by DataTables to ensure that the Ajax returns from server-side processing requests are drawn in sequence by DataTables (Ajax requests are asynchronous and thus can return out of sequence).
/// This is used as part of the draw return parameter (see below).
/// </summary>
public int Draw get; set;
/// <summary>
/// An array defining all columns in the table.
/// </summary>
public DtColumn[] Columns get; set;
/// <summary>
/// An array defining how many columns are being ordering upon - i.e. if the array length is 1, then a single column sort is being performed, otherwise a multi-column sort is being performed.
/// </summary>
public DtOrder[] Order get; set;
/// <summary>
/// Paging first record indicator.
/// This is the start point in the current data set (0 index based - i.e. 0 is the first record).
/// </summary>
public int Start get; set;
/// <summary>
/// Number of records that the table can display in the current draw.
/// It is expected that the number of records returned will be equal to this number, unless the server has fewer records to return.
/// Note that this can be -1 to indicate that all records should be returned (although that negates any benefits of server-side processing!)
/// </summary>
public int Length get; set;
/// <summary>
/// Global search value. To be applied to all columns which have searchable as true.
/// </summary>
public DtSearch Search get; set;
/// <summary>
/// Custom column that is used to further sort on the first Order column.
/// </summary>
public string SortOrder => Columns != null && Order != null && Order.Length > 0
? (Columns[Order[0].Column].Data +
(Order[0].Dir == DtOrderDir.Desc ? " " + Order[0].Dir : string.Empty))
: null;
/// <summary>
/// For Posting Additional Parameters to Server
/// </summary>
public IEnumerable<string> AdditionalValues get; set;
/// <summary>
/// A jQuery DataTables column.
/// </summary>
public class DtColumn
/// <summary>
/// Column's data source, as defined by columns.data.
/// </summary>
public string Data get; set;
/// <summary>
/// Column's name, as defined by columns.name.
/// </summary>
public string Name get; set;
/// <summary>
/// Flag to indicate if this column is searchable (true) or not (false). This is controlled by columns.searchable.
/// </summary>
public bool Searchable get; set;
/// <summary>
/// Flag to indicate if this column is orderable (true) or not (false). This is controlled by columns.orderable.
/// </summary>
public bool Orderable get; set;
/// <summary>
/// Search value to apply to this specific column.
/// </summary>
public DtSearch Search get; set;
/// <summary>
/// An order, as sent by jQuery DataTables when doing AJAX queries.
/// </summary>
public class DtOrder
/// <summary>
/// Column to which ordering should be applied.
/// This is an index reference to the columns array of information that is also submitted to the server.
/// </summary>
public int Column get; set;
/// <summary>
/// Ordering direction for this column.
/// It will be dt-string asc or dt-string desc to indicate ascending ordering or descending ordering, respectively.
/// </summary>
public DtOrderDir Dir get; set;
/// <summary>
/// Sort orders of jQuery DataTables.
/// </summary>
public enum DtOrderDir
Asc,
Desc
/// <summary>
/// A search, as sent by jQuery DataTables when doing AJAX queries.
/// </summary>
public class DtSearch
/// <summary>
/// Global search value. To be applied to all columns which have searchable as true.
/// </summary>
public string Value get; set;
/// <summary>
/// true if the global filter should be treated as a regular expression for advanced searching, false otherwise.
/// Note that normally server-side processing scripts will not perform regular expression searching for performance reasons on large data sets, but it is technically possible and at the discretion of your script.
/// </summary>
public bool Regex get; set;
这是我的空表:
以下是我在尝试加载数据时遇到的错误:
我哪里弄错了?
这里是发生异常的地方:
@HMZ 实施,我看到空记录(下图):
我看到这个警报
卡在处理中
当行数改变时,我看到这个空表:
【问题讨论】:
请显示控制台错误而不是警报,并确保在服务器端包含任何异常。 @HMZ:我已经更新了问题并发布了第一次发生异常的位置 您需要一个自定义模型绑定器。我将发布一个工作示例。 @HMZ:我很期待。我真的很感谢你的时间 嗨@RussellChidhakwa,你能提供教程的链接吗 【参考方案1】:我找到了问题。我缺少一个 JsonSerializer,我将它添加到我的 Startup.cs 类中。
这个方法很好用:
[HttpPost]
public async Task<IActionResult> LoadTable([FromBody] DtParameters dtParameters)
var searchBy = dtParameters.Search?.Value;
// if we have an empty search then just order the results by Id ascending
var orderCriteria = "Id";
var orderAscendingDirection = true;
if (dtParameters.Order != null)
// in this example we just default sort on the 1st column
orderCriteria = dtParameters.Columns[dtParameters.Order[0].Column].Data;
orderAscendingDirection = dtParameters.Order[0].Dir.ToString().ToLower() == "asc";
var result = context.TestRegisters.AsQueryable();
if (!string.IsNullOrEmpty(searchBy))
result = result.Where(r => r.Name != null && r.Name.ToUpper().Contains(searchBy.ToUpper()) ||
r.FirstSurname != null && r.FirstSurname.ToUpper().Contains(searchBy.ToUpper()) ||
r.SecondSurname != null && r.SecondSurname.ToUpper().Contains(searchBy.ToUpper()) ||
r.Street != null && r.Street.ToUpper().Contains(searchBy.ToUpper()) ||
r.Phone != null && r.Phone.ToUpper().Contains(searchBy.ToUpper()) ||
r.ZipCode != null && r.ZipCode.ToUpper().Contains(searchBy.ToUpper()) ||
r.Country != null && r.Country.ToUpper().Contains(searchBy.ToUpper()) ||
r.Notes != null && r.Notes.ToUpper().Contains(searchBy.ToUpper()));
result = orderAscendingDirection ? result.OrderByDynamic(orderCriteria, DtOrderDir.Asc) : result.OrderByDynamic(orderCriteria, DtOrderDir.Desc);
// now just get the count of items (without the skip and take) - eg how many could be returned with filtering
var filteredResultsCount = await result.CountAsync();
var totalResultsCount = await context.TestRegisters.CountAsync();
return Json(new DtResult<TestRegister>
Draw = dtParameters.Draw,
RecordsTotal = totalResultsCount,
RecordsFiltered = filteredResultsCount,
Data = await result
.Skip(dtParameters.Start)
.Take(dtParameters.Length)
.ToListAsync()
);
这些 DtParameters 是正确的:
public class DtResult<T>
/// <summary>
/// The draw counter that this object is a response to - from the draw parameter sent as part of the data request.
/// Note that it is strongly recommended for security reasons that you cast this parameter to an integer, rather than simply echoing back to the client what it sent in the draw parameter, in order to prevent Cross Site Scripting (XSS) attacks.
/// </summary>
[JsonProperty("draw")]
public int Draw get; set;
/// <summary>
/// Total records, before filtering (i.e. the total number of records in the database)
/// </summary>
[JsonProperty("recordsTotal")]
public int RecordsTotal get; set;
/// <summary>
/// Total records, after filtering (i.e. the total number of records after filtering has been applied - not just the number of records being returned for this page of data).
/// </summary>
[JsonProperty("recordsFiltered")]
public int RecordsFiltered get; set;
/// <summary>
/// The data to be displayed in the table.
/// This is an array of data source objects, one for each row, which will be used by DataTables.
/// Note that this parameter's name can be changed using the ajax option's dataSrc property.
/// </summary>
[JsonProperty("data")]
public IEnumerable<T> Data get; set;
/// <summary>
/// Optional: If an error occurs during the running of the server-side processing script, you can inform the user of this error by passing back the error message to be displayed using this parameter.
/// Do not include if there is no error.
/// </summary>
[JsonProperty("error", NullValueHandling = NullValueHandling.Ignore)]
public string Error get; set;
public string PartialView get; set;
/// <summary>
/// The additional columns that you can send to jQuery DataTables for automatic processing.
/// </summary>
public abstract class DtRow
/// <summary>
/// Set the ID property of the dt-tag tr node to this value
/// </summary>
[JsonProperty("DT_RowId")]
public virtual string DtRowId => null;
/// <summary>
/// Add this class to the dt-tag tr node
/// </summary>
[JsonProperty("DT_RowClass")]
public virtual string DtRowClass => null;
/// <summary>
/// Add the data contained in the object to the row using the jQuery data() method to set the data, which can also then be used for later retrieval (for example on a click event).
/// </summary>
[JsonProperty("DT_RowData")]
public virtual object DtRowData => null;
/// <summary>
/// Add the data contained in the object to the row dt-tag tr node as attributes.
/// The object keys are used as the attribute keys and the values as the corresponding attribute values.
/// This is performed using using the jQuery param() method.
/// Please note that this option requires DataTables 1.10.5 or newer.
/// </summary>
[JsonProperty("DT_RowAttr")]
public virtual object DtRowAttr => null;
/// <summary>
/// The parameters sent by jQuery DataTables in AJAX queries.
/// </summary>
public class DtParameters
//public DtParameters()
//
// Search = new DtSearch();
// Search.Value = "";
//
/// <summary>
/// Draw counter.
/// This is used by DataTables to ensure that the Ajax returns from server-side processing requests are drawn in sequence by DataTables (Ajax requests are asynchronous and thus can return out of sequence).
/// This is used as part of the draw return parameter (see below).
/// </summary>
public int Draw get; set;
/// <summary>
/// An array defining all columns in the table.
/// </summary>
public DtColumn[] Columns get; set;
/// <summary>
/// An array defining how many columns are being ordering upon - i.e. if the array length is 1, then a single column sort is being performed, otherwise a multi-column sort is being performed.
/// </summary>
public DtOrder[] Order get; set;
/// <summary>
/// Paging first record indicator.
/// This is the start point in the current data set (0 index based - i.e. 0 is the first record).
/// </summary>
public int Start get; set;
/// <summary>
/// Number of records that the table can display in the current draw.
/// It is expected that the number of records returned will be equal to this number, unless the server has fewer records to return.
/// Note that this can be -1 to indicate that all records should be returned (although that negates any benefits of server-side processing!)
/// </summary>
public int Length get; set;
/// <summary>
/// Global search value. To be applied to all columns which have searchable as true.
/// </summary>
public DtSearch Search get; set;
/// <summary>
/// Custom column that is used to further sort on the first Order column.
/// </summary>
public string SortOrder => Columns != null && Order != null && Order.Length > 0
? (Columns[Order[0].Column].Data +
(Order[0].Dir == DtOrderDir.Desc ? " " + Order[0].Dir : string.Empty))
: null;
/// <summary>
/// For Posting Additional Parameters to Server
/// </summary>
public IEnumerable<string> AdditionalValues get; set;
/// <summary>
/// A jQuery DataTables column.
/// </summary>
public class DtColumn
/// <summary>
/// Column's data source, as defined by columns.data.
/// </summary>
public string Data get; set;
/// <summary>
/// Column's name, as defined by columns.name.
/// </summary>
public string Name get; set;
/// <summary>
/// Flag to indicate if this column is searchable (true) or not (false). This is controlled by columns.searchable.
/// </summary>
public bool Searchable get; set;
/// <summary>
/// Flag to indicate if this column is orderable (true) or not (false). This is controlled by columns.orderable.
/// </summary>
public bool Orderable get; set;
/// <summary>
/// Search value to apply to this specific column.
/// </summary>
public DtSearch Search get; set;
/// <summary>
/// An order, as sent by jQuery DataTables when doing AJAX queries.
/// </summary>
public class DtOrder
/// <summary>
/// Column to which ordering should be applied.
/// This is an index reference to the columns array of information that is also submitted to the server.
/// </summary>
public int Column get; set;
/// <summary>
/// Ordering direction for this column.
/// It will be dt-string asc or dt-string desc to indicate ascending ordering or descending ordering, respectively.
/// </summary>
public DtOrderDir Dir get; set;
/// <summary>
/// Sort orders of jQuery DataTables.
/// </summary>
public enum DtOrderDir
Asc,
Desc
/// <summary>
/// A search, as sent by jQuery DataTables when doing AJAX queries.
/// </summary>
public class DtSearch
/// <summary>
/// Global search value. To be applied to all columns which have searchable as true.
/// </summary>
public string Value get; set;
/// <summary>
/// true if the global filter should be treated as a regular expression for advanced searching, false otherwise.
/// Note that normally server-side processing scripts will not perform regular expression searching for performance reasons on large data sets, but it is technically possible and at the discretion of your script.
/// </summary>
public bool Regex get; set;
此 Datatable 配置正确:
$(document).ready(function ()
$("#demoTable").DataTable(
// Design Assets
stateSave: true,
autoWidth: true,
// ServerSide Setups
processing: true,
serverSide: true,
// Paging Setups
paging: true,
// Searching Setups
searching: regex: true ,
// Ajax Filter
ajax:
url: "/TestRegisters/LoadTable",
type: "POST",
contentType: "application/json",
dataType: "json",
data: function (d)
return JSON.stringify(d);
,
// Columns Setups
columns: [
data: "id" ,
data: "name" ,
data: "firstSurname" ,
data: "secondSurname" ,
data: "street" ,
data: "phone" ,
data: "zipCode" ,
data: "country" ,
data: "notes" ,
data: "creationDate"
]
);
);
这是我在启动时缺少的单行代码:
services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
添加 JsonSerializer 后,我得到了这样的结果:
【讨论】:
惊人的代码,它在第一次执行时执行。我只需要知道一件事。我添加了一个自定义类来分配一些值。但是该类在 DTParameters 中不可访问 @Asad Naeem:您可以发布您的代码并解释您所做的事情、您想要实现的目标以及您遇到的问题。这样,开发人员将能够重新创建您的场景并提供实用的解决方案。【参考方案2】:您的代码需要改进:
asp.net core中的DataTable默认以小写首字母呈现json数据,所以需要修改如下:
列:[ 数据:“应用程序ID”, 数据:“名字”, 数据:“姓”, 数据:“应用程序”, 数据:“提交日期” ]
默认DataTable包含分页、排序和搜索。
当我测试您的代码时,它会在前端收到以下错误消息(您可以在浏览器中按F12
来查看错误消息)。不确定您是否会收到此错误,因为 DataTable 的版本可能是不同:
TypeError:无法设置未定义的属性“nTf”
我搜索错误并得出结论,它是由表尾中th
元素的数量与表头中th
元素的数量不同造成的。但我发现thead
和@的数量987654328@ 在你的代码中是一样的。
与传统的DataTable有点不同的是thead
和tfoot
的两端都有空的th
。所以我试了一下,当我删除@987654333中的th
时它就可以工作了@ 但在thead
中保持th
:
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.ApplicationId)
</th>
...
<th></th>
</tr>
</thead>
<tfoot>
<tr>
<th>
@Html.DisplayNameFor(model => model.ApplicationId)
</th>
....
@*<th></th>*@ //remove this...
</tr>
</tfoot>
这是一个如下所示的工作演示:
型号:
public class StudentApplications
public int ApplicationId get; set;
public string Firstname get; set;
public string Surname get; set;
public string ApplicationFor get; set;
public string SubmissionDate get; set;
查看:
@model IEnumerable<StudentApplications>
<table id="custom-datatable" class="mb-5 display table table-bordered" style="width:100%">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.ApplicationId)
</th>
<th>
@Html.DisplayNameFor(model => model.Firstname)
</th>
<th>
@Html.DisplayNameFor(model => model.Surname)
</th>
<th>
@Html.DisplayNameFor(model => model.ApplicationFor)
</th>
<th>
Date
</th>
<th></th>
</tr>
</thead>
<tfoot>
<tr>
<th>
@Html.DisplayNameFor(model => model.ApplicationId)
</th>
<th>
@Html.DisplayNameFor(model => model.Firstname)
</th>
<th>
@Html.DisplayNameFor(model => model.Surname)
</th>
<th>
@Html.DisplayNameFor(model => model.ApplicationFor)
</th>
<th>
@Html.DisplayNameFor(model => model.SubmissionDate)
</th>
@*<th></th>*@
</tr>
</tfoot>
</table>
@section Scripts
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js"></script>
<script>
$(document).ready(function ()
$('#custom-datatable').DataTable(
ajax:
url: "/Home/data",
type:"POST"
,
columns: [
data: "applicationId" ,
data: "firstname" ,
data: "surname" ,
data: "applicationFor" ,
data: "submissionDate"
]
);
);
</script>
控制器:
[HttpPost]
public ActionResult Data()
var model = new List<StudentApplications>()
new StudentApplications() ApplicationId=1, ApplicationFor="aa", Firstname="Rena", SubmissionDate="2020-8-9", Surname="Ni",
new StudentApplications() ApplicationId=2, ApplicationFor="bb", Firstname="Sherry", SubmissionDate="2020-10-7", Surname="Chen",
new StudentApplications() ApplicationId=3, ApplicationFor="cc", Firstname="Xing", SubmissionDate="2020-5-10", Surname="Zou",
new StudentApplications() ApplicationId=4, ApplicationFor="dd", Firstname="a", SubmissionDate="2020-5-10", Surname="Zou",
new StudentApplications() ApplicationId=5, ApplicationFor="ee", Firstname="b", SubmissionDate="2020-5-10", Surname="sd",
new StudentApplications() ApplicationId=6, ApplicationFor="ff", Firstname="c", SubmissionDate="2020-5-10", Surname="df",
new StudentApplications() ApplicationId=7, ApplicationFor="gg", Firstname="d", SubmissionDate="2020-5-10", Surname="Zdfgou",
new StudentApplications() ApplicationId=8, ApplicationFor="hh", Firstname="e", SubmissionDate="2020-5-10", Surname="dfg",
new StudentApplications() ApplicationId=9, ApplicationFor="ii", Firstname="f", SubmissionDate="2020-5-10", Surname="dfg",
new StudentApplications() ApplicationId=10, ApplicationFor="jj", Firstname="g", SubmissionDate="2020-5-10", Surname="vbc",
new StudentApplications() ApplicationId=11, ApplicationFor="kk", Firstname="h", SubmissionDate="2020-5-10", Surname="hj",
new StudentApplications() ApplicationId=12, ApplicationFor="ll", Firstname="i", SubmissionDate="2020-5-10", Surname="hjk",
new StudentApplications() ApplicationId=13, ApplicationFor="mm", Firstname="j", SubmissionDate="2020-5-10", Surname="tyu",
;
return Json(new Data = model);
Startup.cs:
public class Startup
public Startup(IConfiguration configuration)
Configuration = configuration;
public IConfiguration Configuration get;
public void ConfigureServices(IServiceCollection services)
services.AddControllersWithViews();
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
else
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
endpoints.MapControllerRoute(
name: "default",
pattern: "controller=Home/action=Index/id?");
);
结果:
【讨论】:
让我试试你的建议和实施。非常感谢您的宝贵时间。 嗨@RussellChidhakwa,祝您成功!等待您的回复。 您好@Rena,抱歉回复晚了。现在我正在从头开始尝试您的解决方案。我搞砸了代码。今天我会更新你。 我创建了一个新的测试项目,将命名约定更改为 camelCasing 并删除了空列。现在我被困在处理中。我将获取数据的方法作为 Json 放在 try catch 块中,没有例外。数据仍未显示。因为我做了一个新项目,所以我将这个问题作为一个新问题来避免混淆,然后邀请您查看代码。 你好@Rena!我在这里重新发布了这个问题并提供了所有代码。请看:***.com/questions/64359301/…【参考方案3】:这是Datatables 服务器端处理的工作示例。这是一个示例,可能需要修改才能在您的应用程序中工作。
代码
Datatables表参数:
[ModelBinder(BinderType = typeof(DataTableModelBinder))]
public class DataTablesResult
public int Draw get; set;
public int Start get; set;
public int Length get; set;
public Search Search get; set;
public List<ColumnOrder> Order get; set;
public List<Column> Columns get; set;
public class Search
public string Value get; set;
public bool Regex get; set;
public class Column
public string Data get; set;
public string Name get; set;
public bool Searchable get; set;
public bool Orderable get; set;
public Search Search get; set;
public class ColumnOrder
public int Column get; set;
public string Dir get; set;
一个自定义模型绑定器,以便在服务器端将您的表参数与DataTablesResult
正确绑定:
public class DataTableModelBinder : IModelBinder
public Task BindModelAsync(ModelBindingContext bindingContext)
var request = bindingContext.HttpContext.Request;
// Retrieve request data
var draw = Convert.ToInt32(request.Query["draw"]);
var start = Convert.ToInt32(request.Query["start"]);
var length = Convert.ToInt32(request.Query["length"]);
// Search
var search = new Search
Value = request.Query["search[value]"],
Regex = Convert.ToBoolean(request.Query["search[regex]"])
;
// Order
var o = 0;
var order = new List<ColumnOrder>();
while (!StringValues.IsNullOrEmpty(request.Query["order[" + o + "][column]"]))
order.Add(new ColumnOrder
Column = Convert.ToInt32(request.Query["order[" + o + "][column]"]),
Dir = request.Query["order[" + o + "][dir]"]
);
o++;
// Columns
var c = 0;
var columns = new List<Column>();
while (!StringValues.IsNullOrEmpty(request.Query["columns[" + c + "][name]"]))
columns.Add(new Column
Data = request.Query["columns[" + c + "][data]"],
Name = request.Query["columns[" + c + "][name]"],
Orderable = Convert.ToBoolean(request.Query["columns[" + c + "][orderable]"]),
Searchable = Convert.ToBoolean(request.Query["columns[" + c + "][searchable]"]),
Search = new Search
Value = request.Query["columns[" + c + "][search][value]"],
Regex = Convert.ToBoolean(request.Query["columns[" + c + "][search][regex]"])
);
c++;
var result = new DataTablesResult
Draw = draw,
Start = start,
Length = length,
Search = search,
Order = order,
Columns = columns
;
bindingContext.Result = ModelBindingResult.Success(result);
return Task.CompletedTask;
服务器端操作:
[HttpGet]
public async Task<IActionResult> DataAjax(DataTablesResult tableParams)
var query = dataWrapper.YourDataSet.GetAll();
var totalCount = await query.CountAsync();
if (tableParams.Search != null)
query = query.Where(c => c.Firstname.Contains(tableParams.Search.Value)
|| c.Surname.Contains(tableParams.Search.Value));
//Other search queries goes here
if (tableParams.Order.Count > 0)
if (tableParams.Order[0].Dir == "asc")
query = query.OrderBy(c => EF.Property<string>(c, tableParams.Columns[tableParams.Order[0].Column].Name));
else
query = query.OrderByDescending(c => EF.Property<string>(c, tableParams.Columns[tableParams.Order[0].Column].Name));
//In this example multi order is disabled so we can order by any column dynamically
var result = await query.AsNoTracking().Select(E => new Count = query.Count(), E = E ).Skip(tableParams.Start).Take(tableParams.Length).ToListAsync();
var pureData = result.Select(E => E.E);
if (result.Count == 0)
return Ok(new tableParams.Draw, recordsTotal = 0, recordsFiltered = 0, data = Enumerable.Empty<string>() );
return Ok(new tableParams.Draw, recordsTotal = totalCount, recordsFiltered = result.Select(c => c.Count).FirstOrDefault(), data = pureData );
数据表配置:
var table = $("#dataTable").DataTable(
serverSide: true,
processing: true,
ajax:
url: "/Controller/DataAjax",
method: "GET",
dataType: "json"
,
select: true,
orderMulti: false, //Multi column order is disabled
columnDefs: [
targets: [], //Here you can specify targets for cell ellipsis
render: $.fn.dataTable.render.ellipsis(10, true)
,
targets: [], //Disable search on targeted columns
searchable: false
,
targets: [], //Disable order on targeted columns
orderable: false
],
columns: [
"name": "ApplicationId" //Here your column names should match your db columns in order to have dynamic order.
]
);
【讨论】:
我很感激。让我看看 我正在实现你的代码。我在这里可能需要帮助:'var query = dataWrapper.YourDataSet.GetAll();'这种情况下的dataWrapper是什么? @RussellChidhakwa 在你的情况下,这将是DBContext
: context.AspNetStudentApplications.AsQueryable()
。
我很感激。让我继续实施
我已经实施了您的解决方案,但我现在面临另一个问题。我不再在输出中看到任何异常。在初始重新加载时,我被困在“处理”上,当我更改要显示的行数时,我看到一个带有空行的警报。我可以看到正在提取数据但未显示。让我张贴图片。我已经发布了一些图片。在输出中我看不到任何错误以上是关于ASP.NET Core 3.1 中的数据表服务器端处理的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core 3.1 中的 Ocelot API Gateway 自定义聚合器问题
忽略 ASP.NET Core 3.1 中的 WCF 证书错误
通过 ASP.NET Core 3.1/5.0 MVC 中的脚本使用选定的 ''value='' 填充数据库
ASP.NET Core api 项目 3.1 在 IIS 上发布