DataTable not rendering based on JSON data received from AJAX call - asp.net-mvc

I want to load a data from the table into jQuery DataTable. For this I've applied below code:
HTML
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" />
</head>
<body>
<div style="width:90%;margin:0 auto">
<table id="mydatatable">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email Id</th>
<th>City</th>
<th>Country</th>
</tr>
</table>
</div>
<script src="~/scripts/jquery-3.2.1.min.js"></script>
<script src="~/scripts/jquery.validate.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<script src="~/scripts/jquery-ui-1.12.1.min.js"></script>
<script>
$document.ready(function () {
var oTable = $("mydatatable").DataTable({
"ajax": {
url: "/Home/GetEmployees",
type: "get",
database: "json"
},
"columns": [
{ "data": "FirstName", "autowidth": true },
{ "data": "LastName", "autowidth": true },
{ "data": "EmailId", "autowidth": true },
{ "data": "City", "autowidth": true },
{ "data": "Country", "autowidth": true }
]
});
});
</script>
</body>
</html>
Controller
using MVC_CRUD.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MVC_CRUD.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult GetEmployees() {
using (MvcCRUDDBEntities dc = new MvcCRUDDBEntities()) {
var employees = dc.Employees.OrderBy(a => a.FirstName).ToList();
return Json(new { data = employees }, JsonRequestBehavior.AllowGet);
}
}
}
}
Data which I'm receiving in "//Home/GetEmployees" is :
{"data":[{"EmployeeId":4,"FirstName":"Ankit","LastName":"Agarwal","EmailId":"ankit#xyz.com","City":"Pune ","Country":"India "},{"EmployeeId":2,"FirstName":"Niraj","LastName":"Desai","EmailId":"niraj#xyz.com","City":"Bilimora ","Country":"India "},{"EmployeeId":1,"FirstName":"Pratik","LastName":"Soni","EmailId":"pratik#xyz.com","City":"Valsad ","Country":"India "},{"EmployeeId":3,"FirstName":"Shezad","LastName":"Khan","EmailId":"shezad#xyz.com","City":"Manglore ","Country":"India "}]}
But when I run the application, DataTable is not having any data:
What I want here is data should be loaded in the DataTable on the start of the application. I tried some existing solutions available on StackOverflow but none of them helped me.
Update:
While debugging I found that in HomeController.cs file "GetEmployees" method is not event getting called.

You need edit code below:
var oTable = $("mydatatable").DataTable
to
var oTable = $("#mydatatable").DataTable
because you have table with id="mydatatable". For getting this element by id in jQuery you need use # before of id.
Update
Client side
You need add below option to get data from server:
oTable = $('#mydatatable').dataTable({
"bServerSide": true,
...
});
Server side
return Json(new {
data = employees.Select(e => new {
FirstName = e.FirstName,
LastName = e.LastName,
StatusLU = e.StatusLU,
EmailId = e.EmailId,
City = e.City,
Country = e.Country
})
}, JsonRequestBehavior.AllowGet);

Try this once :
var draw = Request.Form.GetValues("draw").FirstOrDefault();
return Json(new
{ draw = draw,
recordsFiltered = recordsTotal,
recordsTotal = recordsTotal, //1000
data = employees
}, JsonRequestBehavior.AllowGet);
Update : I found you have used database in properties, that seems wrong.
var oTable = $("#mydatatable").DataTable({
"processing": true, //update
"serverSide": true, //update
"ajax": {
url: "/Home/GetEmployees",
type: "get",
datatype: "json" //review this
},
"columns": [
{ "data": "FirstName", "name": "FirstName", "autowidth": true },
{ "data": "LastName", "name": "LastName", "autowidth": true },
{ "data": "EmailId", "name": "EmailId", "autowidth": true },
{ "data": "City", "name": "City", "autowidth": true },
{ "data": "Country", "name": "Country", "autowidth": true }
]
});

Related

Error while trying to load server-side data into razor page using datatables

My table code in view is:
<table class="table table-bordered table-hover table-striped table-content" id="table3">
<thead>
<tr>
<th>messageId</th>
<th>messageText</th>
<th>messageDate</th>
<th>receiverUserId</th>
<th>isSeen</th>
<th>senderId</th>
<th>dateSeen</th>
<th>user</th>
</tr>
</thead>
jQuery code:
$('#table3').DataTable( {
"processing": true, // for show progress bar
"serverSide": true, // for process server side
"filter": true, // this is for disable filter (search box)
"orderMulti": false, // for disable multiple column at once
"ajax": {
"url": "/Admin/LoadPmData",
"type": "POST",
"datatype": "json",
"columns": [
{"data":"messageId"},
{"data":"messageText"},
{"data":"messageDate"},
{"data":"receiverUserId"},
{"data":"isSeen"},
{"data":"senderId"},
{"data":"dateSeen"},
{"data":"user"}
]
}
});
The controller:
[HttpPost]
public JsonResult LoadPmData()
{
var pm = _messageRepository.GetAllMessages();
return Json(new { data = JsonSerializer.Serialize(pm) });
}
I have the following error as alert:
DataTables warning: table id=table3 - Requested unknown parameter '1' for row 0. For more information about this error, please see http://datatables.net/tn/4
How can I fix it?
You only need to put a list into Json(),Here is a demo:
controller:
[HttpPost]
public JsonResult LoadPmData()
{
var pm = _messageRepository.GetAllMessages();//make sure the type of pm is List<Message>
return Json(pm);
}
jQuery(try to put columns outside ajax):
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.8/js/jquery.dataTables.min.js"></script>
<script>
$('#table3').DataTable( {
"processing": true, // for show progress bar
"serverSide": true, // for process server side
"filter": true, // this is for disable filter (search box)
"orderMulti": false, // for disable multiple column at once
"ajax": {
"url": "/Admin/LoadPmData",
"dataSrc": ""
},
"columns": [
{"data":"messageId"},
{"data":"messageText"},
{"data":"messageDate"},
{"data":"receiverUserId"},
{"data":"isSeen"},
{"data":"senderId"},
{"data":"dateSeen"},
{"data":"user"}
]
});
</script>
result:

Showing "Processing..." in datatable when data is empty in mvc view

Showing "Processing..." in datatable when data is empty in mvc view. I am confusing that why it is showing "Processing...". If there is empty data then it want to show "No data available in table"
Here is my code
[View Side]
<div class="row">
<div class="col-md-12">
<table id="dataGrid" class="display table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0">
<thead>
<tr>
<th>Id</th>
<th>Document Name</th>
<th>Other Document Name</th>
<th>Image</th>
<th>Action</th>
</tr>
</thead>
</table>
</div>
</div>
<script>
$(document).ready(function () {
var data = {
'customerId': #Model.Id,
}
addAntiForgeryToken(data);
// DataTable
$("#dataGrid").DataTable({
"scrollX": true, // scrolling horizontal
"bSort": false,
"bFilter": false,
"processing": true, // for show progress bar
"serverSide": true, // for process server side
"pageLength": 5,
"lengthMenu": [5, 10, 50, 100, 1000, 10000],
"ajax": {
"url": "/Admin/FreeLancer/list",
"type": "POST",
"datatype": "json",
"data": data,
"success": function (data) {
}
},
"columnDefs":
[{
"targets": [0],
"visible": false,
"searchable": false,
"orderable": false,
}
],
"columns": [
{ "data": "Id", "name": "Id", "autoWidth": true },
{ "data": "DocumentName", "name": "DocumentName", "autoWidth": true },
{ "data": "OtherDocumentName", "name": "otherdocumentname", "autoWidth": true },
{ "data": "UploadID", "name": "UploadID", "autoWidth": true },
{
"render": function (data, type, row) {
//return "<a target='_blank' href='/Download/GetDownload?downloadId=" + row.UploadID + "' class='btn btn-info'>Download </a>" +
//"<a href='#' class='btn btn-danger' onclick=DeleteData('" + row.Id + "');>Delete</a>"; }
return "<a href='#' class='btn btn-danger' onclick=DeleteData('" + row.Id + "');>Delete</a>";
}
},
],
});
});
</script>
[Controller Side]
[HttpPost]
public IActionResult List(int customerId)
{
// getting all data
var dataList = _customerRegister.DocumentList(customerId,
start: Convert.ToInt32(Request.Form["start"]),
pageSize: Request.Form["length"].ToString() != null ? Convert.ToInt32(Request.Form["length"].ToString()) : 0,
sortColumnName: Request.Form["columns[" + Request.Form["order[0][column]"] + "][name]"],
sortColumnDirection: Request.Form["order[0][dir]"]);
var data = dataList.Select(x => new
{
Id = x.Id,
DocumentName = x.DocumentName,
OtherDocumentName = x.OtherDocumentName,
UploadID = x.UploadID,
});
//returning json data
Response.StatusCode = 200;
return Json(new { draw = Request.Form["draw"], recordsfiltered = dataList.TotalCount, recordstotal = dataList.TotalCount, data = data });
}
This is the code, but I dont think so that their is any problem in the code
Have you checked the DataTables dom property?
$("#table_selector").DataTable({
dom: 'r<"datatable-header"fl><"datatable-scroll"t><"datatable-footer"ip>',
processing: true,
serverSide: true
});
Options
The built-in table control elements in DataTables are:
l - length changing input control
f - filtering input
t - The table!
i - Table information summary
p - pagination control
r - processing display element
https://datatables.net/reference/option/dom
I can see that there is no code for displaying the message. If you are using JQuery Data table which i have notice you can use:
oLanguage: {
sEmptyTable: "Message",
sZeroRecords: "Message",
},

SAPUI5 table binditems from expand performed in a bindelement

I am trying a proof of concept in SAPui5 to check the content of a searchfield, bind a result into another field, if i don't have any result i display an error message that has been written in a message field of my odata
so far i succeeded that this way
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
}
}
}
(If someone knows how to do that a better way, because using mParameters is not the best way, it is welcome)
Now, I want to extend my odata call with an expand navigation to display a table of results, by not using another odata call that the one i used already, so here is my code so far :
eanSearch: function(evt) {
var oView = this.getView();
var oTemplate = new ColumnListItem({
cells: [
new Text({
text: "{Volum}"
}),
new Text({
text: "{Voleh}"
})
]
});
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
parameters: {
expand: "ExcMarmNav"
},
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
}
}
}
});
oView.byId("table").bindItems({
path : '/ExcMarmNav',
template : oTemplate
});
}
The data of the expand is loaded into my response as you can see here
data: {
"ExcSet('5410366897766')": {
"__metadata": {
"id": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/ExcSet('5410366897766')",
"uri": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/ExcSet('5410366897766')",
"type": "ZEXCEPTION_SRV.Exc"
},
"Matnr": "000000000040000000",
"Ean": "5410366897766",
"Message": "",
"ExcMarmNav": {
"__list": [
"MarmSet(Matnr='40000000',Meinh='EA')"
]
}
},
"MarmSet(Matnr='40000000',Meinh='EA')": {
"__metadata": {
"id": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/MarmSet(Matnr='40000000',Meinh='EA')",
"uri": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/MarmSet(Matnr='40000000',Meinh='EA')",
"type": "ZEXCEPTION_SRV.Marm"
},
"Matnr": "40000000",
"Meinh": "EA",
"Umrez": "1",
"Umren": "1",
"Eannr": "",
"Ean11": "5410366897766",
"Numtp": "HE",
"Laeng": "20.000",
"Breit": "20.000",
"Hoehe": "10.000",
"Meabm": "CM",
"Volum": "4000.000",
"Voleh": "CCM",
"Brgew": "2.500",
"Gewei": "KG",
"Mesub": "",
"Atinn": "0000000000",
"Mesrt": "00",
"Xfhdw": "",
"Xbeww": "",
"Kzwso": "",
"Msehi": "",
"BflmeMarm": "",
"GtinVariant": "",
"NestFtr": "0",
"MaxStack": 0,
"Capause": "0.000",
"Ty2tq": ""
}
}
But i don't know how to use resultset to bind it into a table, my code above is not working, if someone has an idea of the params to use for my binditems, or if there is another way to do it?
Best regards
Denis
I managed to do the binding of my table using an intermediate JSON Model based on the response of the Odata Model
eanSearch: function(evt) {
var oView = this.getView();
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
parameters: {
expand: "ExcMarmNav"
},
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
} else {
var model = new JSONModel({
"items": response.mParameters.data.ExcMarmNav
});
oView.setModel(model, "itemModel");
}
}
}
});
And this is the XML view:
<Table id="table" items="{itemModel>/items}">
<columns>
<Column><Label/></Column>
<Column><Label/></Column>
</columns>
<ColumnListItem>
<cells>
<Text text="{itemModel>Volum}"/>
<Text text="{itemModel>Voleh}"/>
</cells>
</ColumnListItem>
</Table>
works fine but I would like to avoid using the intermediate JSON Model and bind directly the array of the response in the table
Ok I managed to find what I needed :)
so the controller:
eanSearch: function(evt) {
var oView = this.getView();
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
parameters: {
expand: "ExcMarmNav"
},
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
}
}
}
});
}
and the view:
<Table noDataText="No Data" items="{EXCEPTION>ExcMarmNav}">
<columns>
<Column><Label/></Column>
<Column><Label/></Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{EXCEPTION>Volum}"/>
<Text text="{EXCEPTION>Voleh}"/>
</cells>
</ColumnListItem>
</items>
</Table>

DataSourceResult in asp.net core

When i was worked in Asp.net Mvc , for paging data use KendoUi.this code use in Asp.net Mvc Web api
public DataSourceResult Get(HttpRequestMessage requestMessage)
{
var request = JsonConvert.DeserializeObject<DataSourceRequest>(
requestMessage.RequestUri.ParseQueryString().GetKey(0)
);
WebApplicationDbContext db = new WebApplicationDbContext();
var list = db.Product.ToList();
return list.AsQueryable()
.ToDataSourceResult(request.Take, request.Skip, request.Sort, request.Filter);
}
And now working with Asp.net Core when i was use this code , it doesn't work.
in the error list show to me this error
'Uri' does not contain a definition for 'ParseQueryString' and no
extension method 'ParseQueryString' accepting a first argument of type
'Uri' could be found (are you missing a using directive or an assembly
reference?)
How can i use this code in Asp.net Core?
First remove the HttpRequestMessage requestMessage parameter. Then remove the requestMessage.RequestUri.ParseQueryString().GetKey(0) part and replace it with:
var rawQueryString = this.HttpContext.Request.QueryString.ToString();
// PM> Install-Package Microsoft.AspNetCore.WebUtilities
var rawQueryStringKeyValue = QueryHelpers.ParseQuery(rawQueryString).FirstOrDefault();
var dataString = Uri.UnescapeDataString(rawQueryStringKeyValue.Key); // this is your received JSON data from Kendo UI
I'm not sure why you need to deserialize the request. I normally pass request to ToDataSourceResult extension method.
For example,
public JsonResult Get([DataSourceRequest] DataSourceRequest request)
{
var db = new WebApplicationDbContext();
return db.Product.ToDataSourceResult(request);
}
Thank you VahidN
This project has helped me a lot
KendoUI.Core.Samples
Im use this code in Controller
public DataSourceResult GetProducts()
{
var dataString = this.HttpContext.GetJsonDataFromQueryString();
var request = JsonConvert.DeserializeObject<DataSourceRequest>(dataString);
var list = ProductDataSource.LatestProducts;
return list.AsQueryable()
.ToDataSourceResult(request.Take, request.Skip, request.Sort, request.Filter);
}
And use this code in chstml
#{
ViewData["Title"] = "Home Page";
}
<!--Right to left grid-->
<div class="k-rtl">
<div id="report-grid"></div>
</div>
#section Scripts
{
<script type="text/javascript">
$(function () {
var productsDataSource = new kendo.data.DataSource({
transport: {
read: {
url: "#Url.Action("GetProducts", "Sample03")",
dataType: "json",
contentType: 'application/json; charset=utf-8',
type: 'GET'
},
parameterMap: function (options) {
return kendo.stringify(options);
}
},
schema: {
data: "data",
total: "total",
model: {
fields: {
"id": { type: "number" }, //Determine the field for dynamic search
"name": { type: "string" },
"isAvailable": { type: "boolean" },
"price": { type: "number" }
}
}
},
error: function (e) {
alert(e.errorThrown);
},
pageSize: 10,
sort: { field: "id", dir: "desc" },
serverPaging: true,
serverFiltering: true,
serverSorting: true
});
$("#report-grid").kendoGrid({
dataSource: productsDataSource,
autoBind: true,
scrollable: false,
pageable: true,
sortable: true,
filterable: true,
reorderable: true,
columnMenu: true,
columns: [
{ field: "id", title: "RowNumber", width: "130px" },
{ field: "name", title: "ProductName" },
{
field: "isAvailable", title: "Available",
template: '<input type="checkbox" #= isAvailable ? checked="checked" : "" # disabled="disabled" ></input>'
},
{ field: "price", title: "Price", format: "{0:c}" }
]
});
});
</script>
}

Knockoutjs one to many mapping not working

In this following code snippet I am creating parent child view model using knockoutjs mapping plugin.I am not getting any error in mapping But when I am running the application it's throwing the error name is not defined.
data = {
"Id": 1,
"Name": "Microsoft",
"Address": "USA",
"WebPage": "SS",
"Employees": [
{
"Id": 1,
"FirstName": "sadsasa",
"LastName": "ADF",
"Twitter": "dfd",
"WebPage": "sdfdf"
},
{
"Id": 2,
"FirstName": "sadsasa",
"LastName": "ADF",
"Twitter": "dfd",
"WebPage": "sdfs"
},
{
"Id": 3,
"FirstName": "sadsasa",
"LastName": "ADF",
"Twitter": "dfd",
"WebPage": "sfdfs"
}
]
};
var mapping = {
'Employees': {
create: function (options) {
alert(options);
return new PersonViewModel(options.data);
}
}
}
function PersonViewModel(data) {
ko.mapping.fromJS(data);
}
function CompanyViewModel(data) {
ko.mapping.fromJS(data, mapping, this);
}
var company;
$(document).ready(function () {
$.ajax({
url: '/api/Greet',
type: 'GET',
dataType: 'json',
success: function (result) {
data = JSON.stringify(result);
company = new CompanyViewModel(data);
console.log(company);
ko.applyBindings(company);
},
error: function (e) {
alert(e);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>
FirstName: <span data-bind="text:Name"></span>
</div>
Well you need to do some small modifications in your code .
View Model :
function PersonViewModel(data) {
ko.mapping.fromJS(data,mapping,this);
}
function CompanyViewModel(data) {
self.childlist=ko.observableArray();
ko.mapping.fromJS(data, mapping, this);
self.childlist.push(new PersonViewModel()); //child array
}
View :
<div>
<b>FirstName:</b> <span data-bind="text:Name"></span>
<div data-bind="foreach:Employees">
<span data-bind="text:Id"></span>
</div>
</div>
Working fiddle here
Do let me know incase of any issues .

Resources