So long story short, I'm trying to show a table with MVC structure and show it with Datatable.js. Since the DB here can be quite huge, I thus want to make the most of data processing stay in my back-end, which means the only time it actually response is when users click the supposed page. My current code looks like this:
My controller:
public ActionResult Index() {
//To send data to my drop-down list. Currently work as intended
M_BussinessLogics Builder = new M_BussinessLogics();
List<VM_PublicatorInfo> Dlist = Builder.GetPublicationList();
SelectList P_List = new SelectList(Dlist, "PublicationID", "DataDesc");
ViewBag.TheList = P_List;
return View();
}
//Response after user selected a certain option from the drop-down list
[HttpPost]
public ActionResult index(string PubID, int? draw, int? start, int? pageNumber, int length=10) {
try {
if (pageNumber == null) {
pageNumber = 0;
}
//Model for data digging (with SQL), should be irrelevant to my problem here
M_BussinessLogics FormBuilder = new M_BussinessLogics();
List<VM_Column> Form_Col_List = FormBuilder.GetTablesInfo(PubID, pageNumber);
//Model to get the whole counts of data so Datatable.js knows how many pages are there, should be irrelevant to my problem here
int CountTest = FormBuilder.GetDataCount(PubID);
List<VM_PublicatorInfo> Dlist = FormBuilder.GetPublicationList();
SelectList P_List = new SelectList(Dlist, "PublicationID", "DataDesc");
ViewBag.TheList = P_List;
return Json(new {
draw = draw,
//The following three lines work, but not entirely fit into my actual goal
//recordsTotal = Form_Col_List.Count(),
//recordsFiltered = Form_Col_List.Count(),
//data = Form_Col_List.Skip(start ?? 0).Take(length).ToList()
recordsTotal = CountTest,
recordsFiltered = CountTest,
data = Form_Col_List
}, JsonRequestBehavior.AllowGet);
}
catch (Exception) {
return null;
}
}
My viewmodel:
//For table
public class VM_Column
{
public int No { get; set;}
public int ShowArtiID { get; set;}
public int ID { get; set; }
public string PublicationID { get; set;}
public int Review { get; set; }
public string Authur { get; set; }
public string CreateDate{ get;set;}
}
//For drop-down list
public class VM_PublicatorInfo {
public string PublicationID { get;set; }
public string DataDesc { get;set; }
}
//For total counts of data in the supposed table
public class VM_TablePage {
public int TotalCount{ get;set;}
}
My view/front-end:
@{
ViewBag.Title = "Publishing Data";
AjaxOptions ajaxOptions = new AjaxOptions {
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "Displayer"
};
}
<h2>Publisher Data</h2>
<div id="pagenum">
<p id="page"></p>
</div>
<!--Drop Down List-->
<div id="DropDownList">
@Html.DropDownList("PubID", ViewBag.TheList as SelectList, "Please choose a publisher", new { @class = "Droplist" })
<input id="P_Btn" class="btn-default" type="submit" />
<br />
</div>
<!--Partial-->
<div id="Displayer" class="center-block" >
<table id=TheTable style="visibility:hidden">
<thead>
<tr>
<th>No</th>
<th>ShowArtiID</th>
<th>ID</th>
<th>PublicationID</th>
<th>Review</th>
<th>Authur</th>
<th>CreateDate</th>
</tr>
</thead>
</table>
</div>
@section scripts{
//I hid the Datatable.js reference in my _Layout
<script>
let PathRoot='@Url.Content("~/")';
$('#P_Btn').click(function () {
if ($('#PubID').val()=="") {
alert("Please choose a publisher");
return false;
}
else
//Re-drawing table every time user send publisher's ID
$('#Displayer').empty();
$('#Displayer').append("<table id=" "TheTable" ">"
"<thead>"
"<tr>"
"<th>No</th>"
"<th>ShowArtiID</th>"
"<th>ID</th>"
"<th>PublicationID</th>"
"<th>Review</th>"
"<th>Authur</th>"
"<th>CreateDate</th>"
"</tr>"
"</thead >"
"</table >");
let table = $('#TheTable').DataTable({
"processing": true,
"serverSide": true,
"ajax": {
url: PathRoot 'Home/index?PubID=' $('#PubID').val(),
type: "POST",
error: function (jqXHR, exception) {
alert(jqXHR);
}
},
"columns": [
{ "data": "No", "bSortable": true },
{ "data": "ShowArtiID", "bSortable": true},
{ "data": "ID", "bSortable": true },
{ "data": "PublicationID", "bSortable": true, "bSearchable": true},
{ "data": "Review", "bSortable": true, "bSearchable": true},
{ "data": "Authur", "bSortable": true, "bSearchable": true },
{ "data": "CreateDate", "bSortable": true, "bSearchable": true }
],
"bLengthChange":false
//Doesn't seem to work?
//"retrive":true,
//"destory":true
})
});
</script>
So my current problems are:
I don't know how to send the page number that user selected to my back-end so it can dig the data out.
I don't know why the "destroy" and "retrive" of Datatable.js doesn't seem to work as intended, so I have to re-create the table whenever a new ID is send out to avoid crush. How may I fix this?
CodePudding user response:
Regarding your question about page number, I had the same problem and created model which handles datatable request schema:
public class DataTablePostModel
{
public int page { get { return GetPage(); } }
public int draw { get; set; }
public int start { get; set; }
public int length { get; set; }
public List<Column> columns { get; set; }
public Search search { get; set; }
public List<Order> order { get; set; }
private int GetPage()
{
if (this.start == 0)
{
return 0;
}
else
{
return start / length;
}
}
}
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 Search
{
public string value { get; set; }
public string regex { get; set; }
}
public class Order
{
public int column { get; set; }
public string dir { get; set; }
}
Then in controller you can use it like:
public ActionResult LoadProducts(DataTablePostModel model)
{
}
Answering you question in comment you can do something like this, because you intend to pass additional parameter to controller:
let table = $('#TheTable').DataTable({
"processing": true,
"serverSide": true,
"ajax": {
url:'Home/index',
data: function (d) {
d.pubId = $('#PubID').val();
}
type: "POST",
error: function (jqXHR, exception) {
alert(jqXHR);
}
},
"columns": [
{ "data": "No", "bSortable": true },
{ "data": "ShowArtiID", "bSortable": true},
{ "data": "ID", "bSortable": true },
{ "data": "PublicationID", "bSortable": true, "bSearchable": true},
{ "data": "Review", "bSortable": true, "bSearchable": true},
{ "data": "Authur", "bSortable": true, "bSearchable": true },
{ "data": "CreateDate", "bSortable": true, "bSearchable": true }
],
Then in you controller in this example index method:
public ActionResult Index (DataTablePostModel model, string pubId)
{
}