Datatable server side processing c# mvc - c#

Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult LoadData()
{
var draw = Request.Form.GetValues("draw").FirstOrDefault();
var start = Request.Form.GetValues("start").FirstOrDefault();
var length = Request.Form.GetValues("length").FirstOrDefault();
var sortColumn = Request.Form.GetValues("columns[" + Request.Form.GetValues("order[0][column]").FirstOrDefault() + "][name]").FirstOrDefault();
var sortColumnDir = Request.Form.GetValues("order[0][dir]").FirstOrDefault();
int pageSize = length != null ? Convert.ToInt32(length) : 0;
int skip = start != null ? Convert.ToInt32(start) : 0;
int totalRecord = 0;
using (ACETeaEntities db = new ACETeaEntities())
{
var v = (from item in db.Drinks_Category select item);
if (!(string.IsNullOrEmpty(sortColumn) && string.IsNullOrEmpty(sortColumnDir)))
{
v = v.OrderBy(sortColumn + " " + sortColumnDir);
}
totalRecord = v.Count();
var data = v.Skip(skip).Take(pageSize).ToList();
return Json(new { draw = draw, recordsFilterd = totalRecord, recordsTotal = totalRecord, data = data }, JsonRequestBehavior.AllowGet);
}
}
}
View:
<script src="~/Scripts/jquery-1.7.2.js" ></script>
<script src="~/Scripts/DataTables/jquery.dataTables.js" ></script>
<link rel="stylesheet" type="text/css" href="~/Content/DataTables/css/jquery.dataTables.css">
<script>
$(document).ready(function () {
$('#example').dataTable({
"processing": true,
"serverSide": true,
"filter": true,
"ordermulti": false,
"ajax": {
"url": "/Home/LoadData",
"type": "POST",
"dataType": "json"
},
"columns": [
{ "data": "Name_category", "autoWidth": true },
{ "data": "Id_category", "autoWidth": true },
{ "data": "Parent", "autoWidth": true }
]
});
});
</script>
<div style="margin:30px;">
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr style="text-align:left;">
<th>Id</th>
<th>Name</th>
<th>Parent</th>
</tr>
</thead>
<tfoot>
<tr style="text-align:left;">
</tr>
</tfoot>
</table>
</div>
My code bugs at: v = v.OrderBy(sortColumn + " " + sortColumnDir);
Can someone help me fix it?

When using the OrderBy method you need to pass the column you want to sort by as a property and use a different method for defining the direction
For example:
v = v.OrderBy(i => i.myColumn);
v = v.OrderByDescending(i => i.myColumn);
Since you are getting your parameters as a string, you have two options:
1) You can build your function first before passing it as well as define your direction
For example:
if (sortColumn == "myColumn")
{
myOrderByFunc = i => i.myColumn;
}
elseif (sortColumn == "myOtherColumn")
{
myOrderByFunc = i => i.myOtherColumn;
}
if (direction == "asc")
{
v = v.OrderBy(myOrderByFunc);
}
elseif (direction == "desc")
{
v = v.OrderByDescending(myOrderByFunc);
}
2) You can use the System.Linq.Dynamic library available here to use strings directly in the linq query (as you are doing now)

Note that you can also try the more updated library System.Linq.Dynamic.Core which does support OrderBy and also ThenBy.

Related

How do I use ternary operator in generic repository function?

I am doing an MVC4 project using Gijgo grid. I want a single generic repository function to work for all grids in the project. So, I have converted the server side code in Gijgo website to get data, filter and sort data into a generic function. Since in Gijgo grid's server-side code, all functionality of parameters passed from jquery to server-side code is automatically taken care of. For my customization, I need to use a ternary operator to check if the filter parameter is empty (then return all data) & if not empty, then return filtered data.
I have a service layer which service classes and a function Get for each service - which calls the generic repository function"Get" for that service module. For a module, the service class has a function "Get" which calls the repository "Get" function to get data for the grid.
Here are the explanations:
I have ProductService in my ServiceLayer which has a function "Get" to call the generic repository "Get" function.
public IEnumerable<ProductDTO> Get(string product, string subCategory, string description,int? page = null, int? pageSize = null, string sortBy = null, bool isDescending = false)
{
var products = _unitOfWork.ProductRepository
.Get(
x => (product != null ? x.EnglishProductName.Contains(product.Trim()) : false) ||
(subCategory != null ? x.DimProductSubcategory.EnglishProductSubcategoryName.Contains(subCategory.Trim()) : false) ||
(description != null ? x.EnglishDescription.Contains(description.Trim()) : false),
sortBy,
isDescending,
page,
pageSize,
includeProperties: player => player.DimProductSubcategory
).AsQueryable();
if (products.Any())
{
return products.ToList().Select(Mapper.Map<DimProduct, ProductDTO>);
}
return Enumerable.Empty<ProductDTO>();
}
Generic Repository "Get" function below
public virtual List<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, string sortBy = null, bool isDescending = false,
int? page = null,
int? pageSize = null, params Expression<Func<TEntity, object>>[] includeProperties)
{
IQueryable<TEntity> query = DbSet;
foreach (Expression<Func<TEntity, object>> include in includeProperties)
query = query.Include(include);
if (filter != null)
query = query.Where(filter);
if (!string.IsNullOrEmpty(sortBy))
{
query = SortByColumnExt.OrderBy(query, sortBy, isDescending);
}
HttpContext.Current.Session["Total"] = query.Count();
if (page.HasValue && pageSize.HasValue)
{
int start = (page.Value - 1) * pageSize.Value;
var records = query.Skip(start).Take(pageSize.Value).ToList();
return (records.ToList());
}
else
{
return (query.ToList());
}
}
My problem is this code section of service function:
var products = _unitOfWork.ProductRepository
.Get(
x => (product != null ? x.EnglishProductName.Contains(product.Trim()) : false) ||
(subCategory != null ? x.DimProductSubcategory.EnglishProductSubcategoryName.Contains(subCategory.Trim()) : false) ||
(description != null ? x.EnglishDescription.Contains(description.Trim()) : false),
sortBy,
isDescending,
page,
pageSize,
includeProperties: player => player.DimProductSubcategory
).AsQueryable();
I want the ternary operator to return whole data if filter parameters EnglishProductName, EnglishProductSubcategoryName and EnglishDescription are passed as empty
""
from jquery, that is when the grid first loads or when user don't enter filter option. This is automatically taken care of in Gijgo grid (in the link I provided above).
Here's the code from Gijgo's Manage Ajax Sourced Data Grid.
Front End
<!DOCTYPE html>
<html>
<head>
<title>Manage Ajax Sourced Data With Grid</title>
<meta charset="utf-8" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" type="text/css" />
<link href="https://unpkg.com/gijgo#1.9.13/css/gijgo.css" rel="stylesheet" type="text/css" />
<style>
.form-row { display: flex; margin-bottom: 29px; }
.form-row:last-child { margin-bottom: 0px; }
.margin-top-10 { margin-top: 10px; }
.float-left { float: left; }
.float-right { float: right; }
.display-inline { display: inline; }
.display-inline-block { display: inline-block; }
.width-200 { width: 200px; }
.clear-both { clear: both; }
.gj-display-none { display: none; }
</style>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://unpkg.com/gijgo#1.9.13/js/gijgo.js" type="text/javascript"></script>
</head>
<body>
<div class="margin-top-10">
<div class="float-left">
<form class="display-inline">
<input id="txtName" type="text" placeholder="Name..." class="gj-textbox-md display-inline-block width-200" />
<input id="txtNationality" type="text" placeholder="Nationality..." class="gj-textbox-md display-inline-block width-200" />
<button id="btnSearch" type="button" class="gj-button-md">Search</button>
<button id="btnClear" type="button" class="gj-button-md">Clear</button>
</form>
</div>
<div class="float-right">
<button id="btnAdd" type="button" class="gj-button-md">Add New Record</button>
</div>
</div>
<div class="clear-both"></div>
<div class="margin-top-10">
<table id="grid"></table>
</div>
<div id="dialog" class="gj-display-none">
<div data-role="body">
<input type="hidden" id="ID" />
<div class="form-row">
<input type="text" class="gj-textbox-md" id="Name" placeholder="Name...">
</div>
<div class="form-row">
<select id="Nationality" width="100%" placeholder="Nationality..."></select>
</div>
<div class="form-row">
<input type="text" id="DateOfBirth" placeholder="Date Of Birth..." width="100%" />
</div>
<div class="form-row">
<label for="IsActive"><input type="checkbox" id="IsActive" /> Is Active?</label>
</div>
</div>
<div data-role="footer">
<button type="button" id="btnSave" class="gj-button-md">Save</button>
<button type="button" id="btnCancel" class="gj-button-md">Cancel</button>
</div>
</div>
<script type="text/javascript">
var grid, dialog, nationalityDropdown, dateOfBirth, isActiveCheckbox;
function Edit(e) {
$('#ID').val(e.data.id);
$('#Name').val(e.data.record.Name);
nationalityDropdown.value(e.data.record.CountryID);
dateOfBirth.value(e.data.record.DateOfBirth);
isActiveCheckbox.state(e.data.record.IsActive ? 'checked' : 'unchecked');
dialog.open('Edit Player');
}
function Save() {
var record = {
ID: $('#ID').val(),
Name: $('#Name').val(),
CountryID: nationalityDropdown.value(),
DateOfBirth: gj.core.parseDate(dateOfBirth.value(), 'mm/dd/yyyy').toISOString(),
IsActive: $('#IsActive').prop('checked')
};
$.ajax({ url: '/Players/Save', data: { record: record }, method: 'POST' })
.done(function () {
dialog.close();
grid.reload();
})
.fail(function () {
alert('Failed to save.');
dialog.close();
});
}
function Delete(e) {
if (confirm('Are you sure?')) {
$.ajax({ url: '/Players/Delete', data: { id: e.data.id }, method: 'POST' })
.done(function () {
grid.reload();
})
.fail(function () {
alert('Failed to delete.');
});
}
}
$(document).ready(function () {
grid = $('#grid').grid({
primaryKey: 'ID',
dataSource: '/Players/Get',
columns: [
{ field: 'ID', width: 56 },
{ field: 'Name', sortable: true },
{ field: 'CountryName', title: 'Nationality', sortable: true },
{ field: 'DateOfBirth', sortable: true, type: 'date' },
{ field: 'IsActive', title: 'Active?', type: 'checkbox', width: 90, align: 'center' },
{ width: 64, tmpl: '<span class="material-icons gj-cursor-pointer">edit</span>', align: 'center', events: { 'click': Edit } },
{ width: 64, tmpl: '<span class="material-icons gj-cursor-pointer">delete</span>', align: 'center', events: { 'click': Delete } }
],
pager: { limit: 5 }
});
dialog = $('#dialog').dialog({
autoOpen: false,
resizable: false,
modal: true,
width: 360
});
nationalityDropdown = $('#Nationality').dropdown({ dataSource: '/Locations/GetCountries', valueField: 'id' });
dateOfBirth = $('#DateOfBirth').datepicker();
isActiveCheckbox = $('#IsActive').checkbox();
$('#btnAdd').on('click', function () {
$('#ID').val('');
$('#Name').val('');
nationalityDropdown.value('');
dateOfBirth.value('');
isActiveCheckbox.state('unchecked');
dialog.open('Add Player');
});
$('#btnSave').on('click', Save);
$('#btnCancel').on('click', function () {
dialog.close();
});
$('#btnSearch').on('click', function () {
grid.reload({ page: 1, name: $('#txtName').val(), nationality: $('#txtNationality').val() });
});
$('#btnClear').on('click', function () {
$('#txtName').val('');
$('#txtNationality').val('');
grid.reload({ name: '', nationality: '' });
});
});
</script>
</body>
</html>
Backed-Code
using Gijgo.Asp.NET.Examples.Models.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace Gijgo.Asp.NET.Examples.Controllers
{
public class PlayersController : Controller
{
public JsonResult Get(int? page, int? limit, string sortBy, string direction, string name, string nationality, string placeOfBirth)
{
List<Models.DTO.Player> records;
int total;
using (ApplicationDbContext context = new ApplicationDbContext())
{
var query = context.Players.Select(p => new Models.DTO.Player
{
ID = p.ID,
Name = p.Name,
PlaceOfBirth = p.PlaceOfBirth,
DateOfBirth = p.DateOfBirth,
CountryID = p.CountryID,
CountryName = p.Country != null ? p.Country.Name : "",
IsActive = p.IsActive,
OrderNumber = p.OrderNumber
});
if (!string.IsNullOrWhiteSpace(name))
{
query = query.Where(q => q.Name.Contains(name));
}
if (!string.IsNullOrWhiteSpace(nationality))
{
query = query.Where(q => q.CountryName != null && q.CountryName.Contains(nationality));
}
if (!string.IsNullOrWhiteSpace(placeOfBirth))
{
query = query.Where(q => q.PlaceOfBirth != null && q.PlaceOfBirth.Contains(placeOfBirth));
}
if (!string.IsNullOrEmpty(sortBy) && !string.IsNullOrEmpty(direction))
{
if (direction.Trim().ToLower() == "asc")
{
switch (sortBy.Trim().ToLower())
{
case "name":
query = query.OrderBy(q => q.Name);
break;
case "countryname":
query = query.OrderBy(q => q.CountryName);
break;
case "placeOfBirth":
query = query.OrderBy(q => q.PlaceOfBirth);
break;
case "dateofbirth":
query = query.OrderBy(q => q.DateOfBirth);
break;
}
}
else
{
switch (sortBy.Trim().ToLower())
{
case "name":
query = query.OrderByDescending(q => q.Name);
break;
case "countryname":
query = query.OrderByDescending(q => q.CountryName);
break;
case "placeOfBirth":
query = query.OrderByDescending(q => q.PlaceOfBirth);
break;
case "dateofbirth":
query = query.OrderByDescending(q => q.DateOfBirth);
break;
}
}
}
else
{
query = query.OrderBy(q => q.OrderNumber);
}
total = query.Count();
if (page.HasValue && limit.HasValue)
{
int start = (page.Value - 1) * limit.Value;
records = query.Skip(start).Take(limit.Value).ToList();
}
else
{
records = query.ToList();
}
}
return this.Json(new { records, total }, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public JsonResult Save(Models.DTO.Player record)
{
Player entity;
using (ApplicationDbContext context = new ApplicationDbContext())
{
if (record.ID > 0)
{
entity = context.Players.First(p => p.ID == record.ID);
entity.Name = record.Name;
entity.PlaceOfBirth = record.PlaceOfBirth;
entity.DateOfBirth = record.DateOfBirth;
entity.CountryID = record.CountryID;
entity.Country = context.Locations.FirstOrDefault(l => l.ID == record.CountryID);
entity.IsActive = record.IsActive;
}
else
{
context.Players.Add(new Player
{
Name = record.Name,
PlaceOfBirth = record.PlaceOfBirth,
DateOfBirth = record.DateOfBirth,
CountryID = record.CountryID,
Country = context.Locations.FirstOrDefault(l => l.ID == record.CountryID),
IsActive = record.IsActive
});
}
context.SaveChanges();
}
return Json(new { result = true });
}
[HttpPost]
public JsonResult Delete(int id)
{
using (ApplicationDbContext context = new ApplicationDbContext())
{
Player entity = context.Players.First(p => p.ID == id);
context.Players.Remove(entity);
context.SaveChanges();
}
return Json(new { result = true });
}
public JsonResult GetTeams(int playerId, int? page, int? limit)
{
List<Models.DTO.PlayerTeam> records;
int total;
using (ApplicationDbContext context = new ApplicationDbContext())
{
var query = context.PlayerTeams.Where(pt => pt.PlayerID == playerId).Select(pt => new Models.DTO.PlayerTeam
{
ID = pt.ID,
PlayerID = pt.PlayerID,
FromYear = pt.FromYear,
ToYear = pt.ToYear,
Team = pt.Team,
Apps = pt.Apps,
Goals = pt.Goals
});
total = query.Count();
if (page.HasValue && limit.HasValue)
{
int start = (page.Value - 1) * limit.Value;
records = query.OrderBy(pt => pt.FromYear).Skip(start).Take(limit.Value).ToList();
}
else
{
records = query.ToList();
}
}
return this.Json(new { records, total }, JsonRequestBehavior.AllowGet);
}
}
}

Server side paging & sorting and filtering Performance

I have only one table in database with 2 million records , i want the user to be able to browse the data and also have the ability to sort data and filter it.
also user should be able to navigate between pages
Here is my MVC controller
public class AssetController : Controller
{
private ApplicationDbContext _dbContext;
public ApplicationDbContext DbContext
{
get
{
return _dbContext ?? HttpContext.GetOwinContext().Get<ApplicationDbContext>();
}
private set
{
_dbContext = value;
}
}
public AssetController()
{
}
public AssetController(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
// GET: Asset
public ActionResult Index()
{
return View();
}
public ActionResult Get([ModelBinder(typeof(DataTablesBinder))] IDataTablesRequest requestModel)
{
IEnumerable<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);
}
}
and below is index.cshtml
<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">Properties</h1>
</div>
<div class="panel-body">
<table id="datatable" class="table table-striped table-bordered" style="width:100%;">
<thead>
<tr>
<th>BarCode</th>
<th>Manufacturer</th>
<th>Building</th>
<th>Quantity</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>
#section Scripts
{
<script type="text/javascript">
$(document).ready(function () {
var datatableInstance = $('#datatable').DataTable({
serverSide: true,
processing: true,
"ajax": {
"url": "#Url.Action("Get","Asset")"
},
lengthMenu: [[10, 25, 50, 100], [10, 25, 50, 100]],
columns: [
{ 'data': 'BarCode' },
{ 'data': 'Manufacturer' },
{
'data': 'Building',
'searchable': true,
},
{
'data': 'Quantity',
'searchable': true,
'render': function (Quantity) {
return "$ " + Quantity;
}
},
],
});
});
</script>
}
I used JQuery data-tables , code is working fine if i have small number of rows - less than 100000 , but if i have large number of rows , it becomes very bad
It takes too long in the following line
var filteredCount = query.Count();
How can i enhance the performance
In my opinion, instead doing "var totalCount = query.Count();" try to make an sql statement with a count over the table, probably you will get a better perfomance.
var totalCount = _context.SqlQuery("Select count(0) from yourTable").FirstOrDefault();
I havenĀ“t tested the perfomance with Count(), but with Distinc() the difference is remarkable.
Hope it helps

DataTables warning - Requested unknown parameter '0' for row 0, column 0

I am working with DataTable.js and trying to implement into MVC. I've written code as per below:
View:
<div id="container">
<div id="demo">
<h2>Index</h2>
<table id="myDataTable" class="display">
<thead>
<tr>
<th>ID</th>
<th>Event Name</th>
<th>Event Type</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
#section scripts{
<script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
$('#myDataTable').dataTable({
"bServerSide": true,
"sAjaxSource": "#Url.Action("AjaxHandler","DataTable")",
"bProcessing": true,
"aoColumns": [
{ "sName": "EventID" },
{ "sName": "EventName" },
{ "sName": "EventTypeTitle" }
]
});
});
</script>
}
And Controller:
public ActionResult Index()
{
return View();
}
public ActionResult AjaxHandler(jQueryDataTableParamModel param)
{
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = getAllEvent().Count(),
iTotalDisplayRecords = getAllEvent().Count(),
aaData = getAllEvent()
}, JsonRequestBehavior.AllowGet);
}
private List<EventModel> getAllEvent()
{
List<EventModel> model = new List<EventModel>();
EventModel model1 = new EventModel { EventID = 1, EventName = "Event 1", EventType = 1, EventTypeTitle = "General" };
model1.EventScheduleList = new List<EventScheduleModel> { new EventScheduleModel {EventScheduleID = 1 }, new EventScheduleModel { EventScheduleID = 2 } };
model.Add(model1);
return model;
}
I am getting DataTables warning: table id=myDataTable - Requested
unknown parameter '0' for row 0, column 0. For more information about
this error, please see http://datatables.net/tn/4
As I research about the error I could find that this particular error is occur when data is not in correct manner. but, when I check response, I am getting correct data.
Is it because I have returned more numbers of columns which are used
in View? or Do I send integer value in JSON?
I've attached fiddle link as well:
https://dotnetfiddle.net/MEoqg8
You need to make very small change in you JacaScript code which goes like this, which means instead of using sName you need to use data inside aoColumns array.
<script>
$(document).ready(function () {
$('#myDataTable').dataTable({
"bServerSide": true,
"sAjaxSource": '#Url.Action("AjaxHandler","Home")',
"bProcessing": true,
"aoColumns": [
{
"data": "EventID",
"bSearchable": false,
"fnRender": function (oObj) {
return '<a href=\"Details/' +
oObj.aData[0] + '\">View</a>';
}
},
{ "data": "EventName" },
{ "data": "EventTypeTitle" }
]
});
});
</script>
You can check a fork from your fiddle here : https://dotnetfiddle.net/7sXghO

MVC Paging not working in AJAX Form

I am trying to implement ASP.NET MVC Paging using MVC4.Paging nuget package.
Problem:
It is working in online demo and also in the download source code. However I am not able to find why it is not working in my particular project by AJAX. In my project it is working by full post back method but not Ajax.
I have even tried to copy over the Index action method and Index and _AjaxEmployeeList Views (.cshtml) files (except .js).
Note: In my solution its not bootstrap as shown in samples. Also my controller name is AdminController whereas in Samples its HomeController
In my solution I need it to work in AJAX method as in samples.
Kindly help regarding:
1. How to find the root cause for why it is not working?
2. How to make this working?
.
My Solution Code (which I tried to reproduce in my solution from the sample):
Index.cshtml
#using MvcPaging
#model IPagedList<MvcPagingDemo.Models.Employee>
#{
ViewBag.Title = "MVC 4 Paging With Ajax Bootstrap";
}
<div class="row-fluid">
<div class="span6">
<h2>
Ajax Paging With Bootstrap In MVC 4
</h2>
</div>
<div class="span6">
<div class="alert alert-info">
The pager also supports area's. #Html.ActionLink("Ajax paging in an area", "Index", "Admin", new { Area = "AreaOne" }, new { #class = "btn btn-success" })</div>
</div>
</div>
<div class="clearfix">
</div>
#using (Ajax.BeginForm("Index", "Admin",
new AjaxOptions { UpdateTargetId = "grid-list", HttpMethod = "get", LoadingElementId = "loading", OnBegin = "beginPaging", OnSuccess = "successPaging", OnFailure = "failurePaging" },
new { id = "frm-search" }))
{
<div class="input-append">
<input class="span2" id="appendedInputButton" type="text" name="employee_name" placeholder="Name" />
<button class="btn" type="submit">
<i class="icon-search"></i> Search</button>
</div>
<div id="grid-list">
#{ Html.RenderPartial("_AjaxEmployeeList", Model); }
</div>
}
<script type="text/javascript">
function beginPaging(args) {
// Animate
$('#grid-list').fadeOut('normal');
}
function successPaging() {
// Animate
$('#grid-list').fadeIn('normal');
$('a').tooltip();
}
function failurePaging() {
alert("Could not retrieve list.");
}
</script>
_AjaxEmployeeList.cshtml
#using MvcPaging
#model IPagedList<MvcPagingDemo.Models.Employee>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>
ID
</th>
<th>
Name
</th>
<th>
Email
</th>
<th>
Phone
</th>
<th>
City
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#item.ID
</td>
<td>
#item.Name
</td>
<td>
#item.Email
</td>
<td>
#item.Phone
</td>
<td>
#item.City
</td>
</tr>
}
</tbody>
</table>
<div class="pager1">
#Html.Raw(Ajax.Pager(
new Options
{
PageSize = Model.PageSize,
TotalItemCount = Model.TotalItemCount,
CurrentPage = Model.PageNumber,
ItemTexts = new ItemTexts() { Next = "Next", Previous = "Previous", Page = "P" },
ItemIcon = new ItemIcon() { First = "icon-backward", Previous = "icon-chevron-left", Next = "icon-chevron-right", Last = "icon-forward" },
TooltipTitles = new TooltipTitles() { Next = "Next page", Previous = "Previous page", Page = "Page {0}." },
Size = Size.normal,
Alignment = Alignment.centered,
IsShowControls = true,
IsShowFirstLast = true,
CssClass = ""
},
new AjaxOptions
{
UpdateTargetId = "grid-list",
OnBegin = "beginPaging",
OnSuccess = "successPaging",
OnFailure = "failurePaging"
}, new { controller = "Admin", action = "Index", employee_name = ViewData["employee_name"] }))
<div class="well">
Showing <span class="badge badge-success">#Model.ItemStart</span> to <span class="badge badge-success">#Model.ItemEnd</span>
of <span class="badge badge-info">#Model.TotalItemCount</span> entries</div>
</div>
AdminController.cs
public class AdminController : Controller
{
private const int defaultPageSize = 3;
private IList<Employee> allEmployee = new List<Employee>();
private string[] name = new string[4] { "Will", "Johnny", "Zia", "Bhaumik" };
private string[] phone = new string[4] { "1-274-748-2630", "1-762-805-1019", "1-920-437-3485", "1-562-653-8258" };
private string[] email = new string[4] { "donec#congueelitsed.org", "neque.non#Praesent.co.uk", "et.magna#Pellentesque.ca", "enim.commodo#orci.net" };
private string[] city = new string[4] { "Wigtown", "Malderen", "Las Vegas", "Talence" };
public AdminController()
{
InitializeEmployee();
}
private void InitializeEmployee()
{
// Create a list of 200 employee.
int index = 0;
for (int i = 0; i < 200; i++)
{
var employee = new Employee();
//int categoryIndex = i % new Random().Next(1, 5);
//if (categoryIndex > 3)
// categoryIndex = 3;
index = index > 3 ? 0 : index;
employee.ID = i + 1;
employee.Name = name[index];
employee.Phone = phone[index];
employee.Email = email[index];
employee.City = city[index];
allEmployee.Add(employee);
index++;
}
}
public ActionResult Index(string employee_name, int? page)
{
ViewData["employee_name"] = employee_name;
int currentPageIndex = page.HasValue ? page.Value : 1;
IList<Employee> employees = this.allEmployee;
if (string.IsNullOrWhiteSpace(employee_name))
{
employees = employees.ToPagedList(currentPageIndex, defaultPageSize);
}
else
{
employees = employees.Where(p => p.Name.ToLower() == employee_name.ToLower()).ToPagedList(currentPageIndex, defaultPageSize);
}
//var list =
if (Request.IsAjaxRequest())
return PartialView("_AjaxEmployeeList", employees);
else
return View(employees);
}
public ActionResult Paging(string employee_name, int? page)
{
ViewData["employee_name"] = employee_name;
int currentPageIndex = page.HasValue ? page.Value : 1;
IList<Employee> employees = this.allEmployee;
if (string.IsNullOrWhiteSpace(employee_name))
{
employees = employees.ToPagedList(currentPageIndex, defaultPageSize);
}
else
{
employees = employees.Where(p => p.Name.ToLower() == employee_name.ToLower()).ToPagedList(currentPageIndex, defaultPageSize);
}
return View(employees);
}
}
JS references in the _Layout.cshtml
You have not described how exactly it is not working. but i will guess the most common issues which might be causing your issue
make sure you actually have a reference to the correct java script files. its not enough to have them in a folder, your page must link to them.
see the following link to see how you reference scripts on you page. http://www.w3schools.com/tags/att_script_src.asp
make sure you put in the correct path.
make sure you reference the *ajax.js files for ajax to work along with any other required files.
Finally I found the solution.
Since I was using jquery-1.11.1.js, in script file jquery.unobtrusive-ajax.js I had to replace calls to .live() with .on().
But simple find and replace was not right way which I found later. I found from other sources that I have to change completely those lines of code as the .on() works.
I replaced the code as below:
Non-working code with .live() function:
$("a[data-ajax=true]").live("click", function (evt) {
debugger;
evt.preventDefault();
asyncRequest(this, {
url: this.href,
type: "GET",
data: []
});
});
$("form[data-ajax=true] input[type=image]").live("click", function (evt) {
debugger;
var name = evt.target.name,
$target = $(evt.target),
form = $target.parents("form")[0],
offset = $target.offset();
$(form).data(data_click, [
{ name: name + ".x", value: Math.round(evt.pageX - offset.left) },
{ name: name + ".y", value: Math.round(evt.pageY - offset.top) }
]);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$("form[data-ajax=true] :submit").live("click", function (evt) {
debugger;
var name = evt.target.name,
form = $(evt.target).parents("form")[0];
$(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$("form[data-ajax=true]").live("submit", function (evt) {
debugger;
var clickInfo = $(this).data(data_click) || [];
evt.preventDefault();
if (!validate(this)) {
return;
}
asyncRequest(this, {
url: this.action,
type: this.method || "GET",
data: clickInfo.concat($(this).serializeArray())
});
});
Working code with .on() function:
$(document).on("click", "a[data-ajax=true]", function (evt) {
evt.preventDefault();
asyncRequest(this, {
url: this.href,
type: "GET",
data: []
});
});
$(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {
var name = evt.target.name,
$target = $(evt.target),
form = $target.parents("form")[0],
offset = $target.offset();
$(form).data(data_click, [
{ name: name + ".x", value: Math.round(evt.pageX - offset.left) },
{ name: name + ".y", value: Math.round(evt.pageY - offset.top) }
]);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$(document).on("click", "form[data-ajax=true] :submit", function (evt) {
var name = evt.target.name,
form = $(evt.target).parents("form")[0];
$(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$(document).on("submit", "form[data-ajax=true]", function (evt) {
var clickInfo = $(this).data(data_click) || [];
evt.preventDefault();
if (!validate(this)) {
return;
}
asyncRequest(this, {
url: this.action,
type: this.method || "GET",
data: clickInfo.concat($(this).serializeArray())
});
});
Thanks.

jQuery DataTable JSON Parsing Error

Okay, so, my issue today is I am trying to return a jquery datatable from a AJAX result, and every time I request the AJAX I am getting the following error:
"DataTables warning: JSON data from server could not be parsed. This is caused by a JSON formatting error"
Here is what my view looks like:
<script type="text/javascript">
$(document).ready(function () {
var oTable = $('#StudentTable').dataTable({
"bServerSide": true,
"sAjaxSource": "Admin/FindStudent",
"bProcessing": true,
"aoColumns": [
{ "sName": "StudentID",
"bSearchable": false,
"bSortable": false,
"fnRender": function (oObj) {
return 'View';
}
},
{ "sName": "FirstName" },
{ "sName": "LastName" },
{ "sName": "EmailAddress" }
]
});
});
</script>
<table id="StudentTable" class="display">
<thead>
<tr>
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Email Address</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
And here is the controller:
public ActionResult FindStudent(DataTableParamModel dtParams)
{
//if (Session["IsAdmin"] != "True")
//{
// return View("Login");
//}
var repo = new StudentRepository();
var allStudents = repo.GetAllStudents();
IEnumerable<StudentInfo> filteredStudents;
//Check whether the students should be filtered by keyword
if (!string.IsNullOrEmpty(dtParams.sSearch))
{
//Used if particulare columns are filtered
var fnameFilter = Convert.ToString(Request["sSearch_1"]);
var lnameFilter = Convert.ToString(Request["sSearch_2"]);
var emailFilter = Convert.ToString(Request["sSearch_3"]);
//Optionally check whether the columns are searchable at all
var isFNameSearchable = Convert.ToBoolean(Request["bSearchable_1"]);
var isLNameSearchable = Convert.ToBoolean(Request["bSearchable_2"]);
var isEmailSearchable = Convert.ToBoolean(Request["bSearchable_3"]);
filteredStudents = repo.GetAllStudents()
.Where(c => isFNameSearchable && c.FirstName.ToLower().Contains(dtParams.sSearch.ToLower())
||
isLNameSearchable && c.LastName.ToLower().Contains(dtParams.sSearch.ToLower())
||
isEmailSearchable && c.EmailAddress.ToLower().Contains(dtParams.sSearch.ToLower()));
}
else
{
filteredStudents = allStudents;
}
var isFNameSortable = Convert.ToBoolean(Request["bSortable_1"]);
var isLNameSortable = Convert.ToBoolean(Request["bSortable_2"]);
var sortColumnIndex = Convert.ToInt32(Request["iSortCol_0"]);
Func<StudentInfo, string> orderingFunction = (c => sortColumnIndex == 1 && isFNameSortable ? c.FirstName :
sortColumnIndex == 2 && isLNameSortable ? c.LastName :
"");
var sortDirection = Request["sSortDir_0"]; // asc or desc
if (sortDirection == "asc")
filteredStudents = filteredStudents.OrderBy(orderingFunction);
else
filteredStudents = filteredStudents.OrderByDescending(orderingFunction);
var displayedStudents = filteredStudents.Skip(dtParams.iDisplayStart).Take(dtParams.iDisplayLength);
var result = from c in displayedStudents select new[] { Convert.ToString(c.StudentID), c.FirstName, c.LastName, c.EmailAddress };
JsonResult results = Json(new
{
sEcho = dtParams.sEcho,
iTotalRecords = allStudents.Count(),
iTotalDisplayRecords = filteredStudents.Count(),
aaData = result
},
JsonRequestBehavior.AllowGet);
return View(results);
}
When using JSONLint, it spits out
Parse error on line 1:
<headid="Head1"><sty
^
Expecting '{', '['
Any ideas?
try to return Json object:
return Json(new {
sEcho = dtParams.sEcho,
iTotalRecords = allStudents.Count(),
iTotalDisplayRecords = filteredStudents.Count(),
aaData = result
}, JsonRequestBehavior.AllowGet);
resource

Categories

Resources