So, I had the Grid working with Ajax, and that was really awesome as the paging and sorting was very quick. However, we had a problem that larger data sets (30k and more) would have the Grid time out. I believe switching over to a server side binding and grabbing 20 at a time would allow users to get the data. (Please correct me if I'm wrong).
Here's what I had before:
@(Html.Kendo().Grid<vNPISearch>() .Name("npi-grid") .DataSource(dataSource => dataSource .Ajax() .Read(read => read.Action("NPI_Read", "Pecos")) .ServerOperation(false) .PageSize(20)) .Columns(columns => { columns.Template(x => { }).ClientTemplate("#=GetPecosStatus(PecosNPI) #").Width(50); columns.Bound(x => x.ProviderFirstName).Title("First Name"); columns.Bound(x => x.ProviderLastName).Title("Last Name"); columns.Bound(x => x.ProviderBusinessLocationAddressCity).Title("City"); columns.Bound(x => x.ProviderBusinessLocationAddressState).Title("State"); columns.Bound(x => x.NPI).Title("NPI"); }) .Scrollable() .Sortable() .Pageable(pageable => pageable .Refresh(true) .PageSizes(true) .ButtonCount(5)) )And the NPI_Read looked like:
public ActionResult NPI_Read([DataSourceRequest] DataSourceRequest request){ if (!String.IsNullOrEmpty(SearchTerm)) { return Json(oandpService.GetPecosSearchResults(SearchTerm).ToDataSourceResult(request), JsonRequestBehavior.AllowGet); } else { return null; }}However, the performance was ABSOLUTELY TERRIBLE! For it to grab 55 records it took almost 10 seconds, whereas if I just populated a simple table it would be almost instantly.
So, I wanted to try server side binding.
The view now looks like:
@(Html.Kendo().Grid<vNPISearch>() .Name("npi-grid") .Columns(columns => { columns.Template(x => { }).ClientTemplate("#=GetPecosStatus(PecosNPI) #").Width(50); columns.Bound(x => x.ProviderFirstName).Title("First Name"); columns.Bound(x => x.ProviderLastName).Title("Last Name"); columns.Bound(x => x.ProviderBusinessLocationAddressCity).Title("City"); columns.Bound(x => x.ProviderBusinessLocationAddressState).Title("State"); columns.Bound(x => x.NPI).Title("NPI"); }) .Scrollable(src => src.Height("auto")) .Sortable() .Pageable() .DataSource(dataSource => dataSource .Server() .PageSize(20) .Total((int)ViewData["total"]) .Read(read => read.Action("NPI_Read", "Pecos"))))And the NPI_Read looks like:
public ActionResult NPI_Read([DataSourceRequest] DataSourceRequest request){ if (!String.IsNullOrEmpty(SearchTerm)) { if (request.PageSize == 0) { request.PageSize = 20; } IQueryable<vNPISearch> searchResults = oandpService.GetPecosSearchResults(SearchTerm); if (request.Sorts.Any()) { foreach (SortDescriptor sortDescriptor in request.Sorts) { if (sortDescriptor.SortDirection == ListSortDirection.Ascending) { switch (sortDescriptor.Member) { case "ProviderFirstName": searchResults = searchResults.OrderBy(x => x.ProviderFirstName); break; case "ProviderLastName": searchResults = searchResults.OrderBy(x => x.ProviderLastName); break; case "ProviderBusinessLocationAddressCity": searchResults = searchResults.OrderBy(x => x.ProviderBusinessLocationAddressCity); break; case "ProviderBusinessLocationAddressState": searchResults = searchResults.OrderBy(x => x.ProviderBusinessLocationAddressState); break; case "NPI": searchResults = searchResults.OrderBy(x => x.NPI); break; } } else { switch (sortDescriptor.Member) { case "ProviderFirstName": searchResults = searchResults.OrderByDescending(x => x.ProviderFirstName); break; case "ProviderLastName": searchResults = searchResults.OrderByDescending(x => x.ProviderLastName); break; case "ProviderBusinessLocationAddressCity": searchResults = searchResults.OrderByDescending(x => x.ProviderBusinessLocationAddressCity); break; case "ProviderBusinessLocationAddressState": searchResults = searchResults.OrderByDescending(x => x.ProviderBusinessLocationAddressState); break; case "NPI": searchResults = searchResults.OrderByDescending(x => x.NPI); break; } } } } else { //EF cannot page unsorted data. searchResults = searchResults.OrderBy(x => x.ProviderLastName); } //Apply paging. if (request.Page > 0) { searchResults = searchResults.Skip((request.Page - 1) * request.PageSize); } searchResults = searchResults.Take(request.PageSize); ViewData["total"] = searchResults.Count(); var result = new DataSourceResult() { Data = searchResults, Total = Convert.ToInt32(ViewData["total"]) }; return Json(result, JsonRequestBehavior.AllowGet); } else { return Json(Enumerable.Empty<vNPISearch>().AsQueryable()); }}However, when I run the page it immediately returns: Object reference not set to an instance of an object. With Line 21 being highlighted. That line is .DataSource(dataSource => dataSource
So, two questions:
- Is there a way to improve performance with AJAX and large datasets?
- If not, what am I not doing to get server side binding not working?
