Issue :
I am having Kendo Grid in my Angular JS html page. Kendo Grid data is coming from my remote service Web API.
Kendo grid try to download content of 38 MB in browser for each 10 records while we are doing Paging (or page load on first time) and it takes approx. 6 minutes to load data.
What and which content it is downloading for 38 MB ?
What i already implemented by reading/learning similar support tickets on stack overflow :
Implemented Server Paging true (pageSize = 10, Total records = 56000 approx.)
Bundling of JS and CSS
I tried both below options:
scrollable: { virtual: true } OR scrollable: { endless: true }
I check my stored procedure on production, it executes in less than 3 seconds for approx. 55000 records. (on production and staging both servers).
I check my Web API controller, it returns response in less than 4 seconds to kendo grid, and then kendo grid takes too much time to populate data.
I have below JS and CSS for Kendo (already implemented bundling) :
- Kendo.all.min.js
- kendo.bootstrap.min.css
- kendo.common-bootstrap.min.css
- Other needed JS and CSS for project are also loads in bundling manner.
Below are my live project pages :
HTML Page :
<div id="heatMapGrid" kendo-grid k-options="vm.heatMapGridOptions"></div>
AngularJS Controller :
var dataSourceHeatMapGrid = new kendo.data.DataSource({
transport: {
read: function (options) {
heatMapService.getHeatMapGrid(options.data, heatMapGridParams)
.then(function (response) {
options.success(response.data);
$rootScope.optioncallback = options;
//$scope.htmapGridCSV = [];
//$scope.htmapGridCSV = response.data.exportData;
}).catch(function (e) {
console.log('Error: ', e);
throw e;
});
},
parameterMap: function (options) {
return JSON.stringify(options);
}
},
schema: {
data: function (response) {
return response.gridData;
},
total: function (response) {
return response.Total;
},
model: {
fields: {
TPID: { type: "number" },
TPName: { type: "string" },
EndCustomerPurchaseAmt: { type: "number" },
PrimaryExpirationMonth: { type: "string" },
AgreementID: { type: "number" },
TotalPurchased: { type: "number" },
TotalAssigned: { type: "number" },
OverUnder: { type: "number" },
VSEntPurchasedUnits: { type: "number" },
VSProMSDNUnits: { type: "number" },
VSTestProMSDNUnits: { type: "number" },
MSDNPlat: { type: "number" },
CloudPurchasedUnits: { type: "number" },
UnbilledOverage: { type: "number" },
AzurePotentialRevenue: { type: "number" }
}
}
},
pageSize: 10,
serverPaging: true
});
vm.heatMapGridOptions = {
columns: [
{ "title": "", template: "<a title='#=TPID#' #=isPinnedAccount==1 ? \"class='terrunpinaccount'\" : \"class='terrpinaccount'\"# ng-click='vm.pinUnpinAccount(\"#=TPID#\")'></a>" },
{ "title": "Account Name", "field": "TPName", template: "<a href='javascript:void(0);' ng-click='vm.tPIDDetails(\"#=TPID#\",\"#=TPName#\")' title='#=TPName#'><div class='DisplayTitleTPName'>#=TPName#<ul><li>AM: #=AM#, OM: #=OperatingModel#, Country: #=Country#</li><li>DevSales Lead: #=SalesLead#, SSP: #=Dev_SSP#, TSP: #=DevTSP#</li></ul></div></a>", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{
"title": "PERFORMANCE AND ANNIVERSARIES", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns:
[{
"title": "Renewals and True Ups", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns: [{ "title": "Total Annualized Expiring", "field": "EndCustomerPurchaseAmt", format: "{0:c0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Primary Anniversary Month", "field": "PrimaryExpirationMonth", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Agreement Number", "field": "AgreementID", format: "{0:n0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } }]
}]
},
{
"title": "EFFECTIVE LICENSE POSITIONS", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns:
[{
"title": "Visual Studio Subscriptions", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns: [{ "title": "Purchased", "field": "TotalPurchased", format: "{0:n0}" },
{ "title": "Assigned", "field": "TotalAssigned", format: "{0:n0}" },
{ "title": "Over Under", "field": "OverUnder", format: "{0:n0}" }]
},
{
"title": "Account Footprint (Active SA Licenses)", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns: [{ "title": "Enterprise w/ MSDN", "field": "VSEntPurchasedUnits", format: "{0:n0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Pro w/ MSDN", "field": "VSProMSDNUnits", format: "{0:n0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Test Pro w/ MSDN", "field": "VSTestProMSDNUnits", format: "{0:n0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "MSDN Platforms", "field": "MSDNPlat", format: "{0:n0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Cloud", "field": "CloudPurchasedUnits", format: "{0:n0}" }]
},
{
"title": "Azure", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns: [{ "title": "Unbilled Overage", "field": "UnbilledOverage", format: "{0:c0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Potential Revenue", "field": "AzurePotentialRevenue", headerTemplate: '<span title="Potential Revue is based on the delta of activated seats and <br/> developers deploying to Azure multiplied by the annual <br/> value of an Azure attached developer ($15k)">Potential Revenue</span>', format: "{0:c0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } }]
}]
}
],
groupable: false,
sortable: true,
resizable: true,
//pageable: true,
pageable: {
refresh: true,
pageSizes: [10, 20, 50],
},
columnMenu: true,
scrollable: false
//filterable: true
};
$("#heatMapGrid").data("kendoGrid").setDataSource(dataSourceHeatMapGrid);
AngularJS Service :
services.getHeatMapGrid = function (command, heatMapGridParams) {
var data = {
page: command.page,
pageSize: command.pageSize,
skip: command.skip,
take: command.take,
alias: heatMapGridParams.alias,
hasDevTest: heatMapGridParams.hasDevTest,
hasDevTestLabs: heatMapGridParams.hasDevTestLabs,
hasXamarin: heatMapGridParams.hasXamarin,
devOpsMSShopFlag: heatMapGridParams.devOpsMSShopFlag,
devOpsOSSThirdPartyShopsFlag: heatMapGridParams.devOpsOSSThirdPartyShopsFlag,
intelligentAppsFlag: heatMapGridParams.intelligentAppsFlag,
paaSServicesFlag: heatMapGridParams.paaSServicesFlag,
enterpriseStepUpFlag: heatMapGridParams.enterpriseStepUpFlag,
devsLearningAzureFlag: heatMapGridParams.devsLearningAzureFlag,
devOpsAcceleratorEligibleFlag: heatMapGridParams.devOpsAcceleratorEligibleFlag,
overAssignedFlag: heatMapGridParams.overAssignedFlag,
lowAssignmentsFlag: heatMapGridParams.lowAssignmentsFlag,
hasCloudSubscriptionFlag: heatMapGridParams.hasCloudSubscriptionFlag,
hasUnbilledOverageFlag: heatMapGridParams.hasUnbilledOverageFlag,
hasDevTestOppty: heatMapGridParams.hasDevTestOppty,
areaID: heatMapGridParams.areaID,
countryID: heatMapGridParams.countryID,
segmentID: heatMapGridParams.segmentID,
subsegmentID: heatMapGridParams.subsegmentID,
salesUnitID: heatMapGridParams.salesUnitID,
agreementRenewalOrTrueupID: heatMapGridParams.agreementRenewalOrTrueupID,
aM: heatMapGridParams.aM,
industry: heatMapGridParams.industry,
hasAppServOppty: heatMapGridParams.hasAppServOppty,
hasDotNetDeveloperFlag: heatMapGridParams.hasDotNetDeveloperFlag,
paaSReadyFlag: heatMapGridParams.paaSReadyFlag,
startMonth: heatMapGridParams.startMonth,
endMonth: heatMapGridParams.endMonth
};
return $http({ method: 'GET', url: config.apiUrl + 'Account/HeatMapGrid/', params: data });
};
Web API :
[HttpGet]
public heatMapGridAndExport HeatMapGrid([FromUri]HeatMapGridModel model)
{
ListView listView = new ListView();
List<getHeatMapDataGlobalFilter_Result> listGridDataForTotalCount = new List<getHeatMapDataGlobalFilter_Result>();
listGridDataForTotalCount = listView.GetListViewGridData(model.alias, model.hasDevTest, model.hasDevTestLabs, model.hasXamarin, model.devOpsMSShopFlag, model.devOpsOSSThirdPartyShopsFlag, model.intelligentAppsFlag, model.paaSServicesFlag, model.enterpriseStepUpFlag, model.devsLearningAzureFlag, model.devOpsAcceleratorEligibleFlag, model.overAssignedFlag, model.lowAssignmentsFlag, model.hasCloudSubscriptionFlag, model.hasUnbilledOverageFlag, model.hasDevTestOppty, model.areaID, model.countryID, model.segmentID, model.subsegmentID, model.salesUnitID, model.agreementRenewalOrTrueupID, model.aM, model.industry, model.hasAppServOppty, model.hasDotNetDeveloperFlag, model.paaSReadyFlag, model.startMonth, model.endMonth);
List<getHeatMapDataGlobalFilter_Result> listGridData = new List<getHeatMapDataGlobalFilter_Result>();
listGridData = listGridDataForTotalCount.Skip(model.skip).Take(model.take).OrderByDescending(c => c.EndCustomerPurchaseAmt).ToList();
//List<heatMapExport> listExportData = new List<heatMapExport>();
//listExportData = listGridDataForTotalCount.Select(c => new heatMapExport()
//{
// TPName = c.TPName,
// TPID = c.TPID,
// OperatingModel = c.OperatingModel,
// Area = c.Area,
// Country = c.Country,
// CreditedRegion = c.CreditedRegion,
// CreditedDistrict = c.CreditedDistrict,
// Segment = c.Segment,
// ATUManager = c.ATUManager,
// Dev_SSP = c.Dev_SSP,
// AM = c.AM,
// Industry = c.Industry,
// ATSName = c.ATSName,
// AssignedPect = string.Format("{0:p0}", c.AssignedPect),
// ActivatedPect = string.Format("{0:p0}", c.ActivatedPect),
// AzureActivated = Convert.ToString(c.AzureActivated),
// EndCustomerPurchaseAmt = string.Format("{0:c0}", c.EndCustomerPurchaseAmt),
// PrimaryExpirationMonth = Convert.ToString(c.PrimaryExpirationMonth),
// AgreementID = Convert.ToString(c.AgreementID),
// TotalPurchased = string.Format("{0:n0}", c.TotalPurchased),
// TotalAssigned = string.Format("{0:n0}", c.TotalAssigned),
// OverUnder = string.Format("{0:n0}", c.OverUnder),
// VSEntPurchasedUnits = string.Format("{0:n0}", c.VSEntPurchasedUnits),
// VSProMSDNUnits = string.Format("{0:n0}", c.VSProMSDNUnits),
// VSTestProMSDNUnits = string.Format("{0:n0}", c.VSTestProMSDNUnits),
// MSDNPlat = string.Format("{0:n0}", c.MSDNPlat),
// CloudPurchasedUnits = string.Format("{0:n0}", c.CloudPurchasedUnits),
// UnbilledOverage = string.Format("{0:c0}", c.UnbilledOverage),
// AzurePotentialRevenue = string.Format("{0:c0}", c.AzurePotentialRevenue)
//}).ToList();
var heatMapData = new heatMapGridAndExport
{
gridData = listGridData,
//exportData = listExportData,
Total = listGridDataForTotalCount.Count()
};
return heatMapData;
}
My Environment :
Version Telerik Control - Kendo UI v2017.2.621
Operating System Development machine - Windows 10 Enterprise (8 GB RAM, Intel Core i7 Processor, 64 bit) (Client OS)
Browser - Google Chrome, Version 65.0.3325.181
.NET Framework - Version 4.6.1
Visual Studio - Enterprise 2015, Version 14.0.25431.01 (Update 3)
Coding Language - C#
Here is my browser screen shot for production server :
Here is the another screenshot when i am clicking on 2nd page, it again download 38 mb content and it takes approx. 6 minutes. (server paging = true and pageSize = 10)
Code Debugging screenshots:
What i am doing wrong? Can any one please help me.
Thank you in advance.



heatMapData.gridDatamust therefore contain the entire data set), or inspecting the JSON as it appears on the wire. You should be able to drill into that in the Chrome dev tools, or alternatively use an external tool like Fiddler, Wireshark etc. - Joe GloverheatMapData.gridDatain WebAPI response by debugging the code and also checked in fiddler, but at both the times it contains only 10 records not whole data set (as i used skip and take) And for ordering, i checked by swap ordering clause before skip/take but no effect and also tried by removing ordering, but no luck at both the times. Any other help appreciated. Thank you - Kashyap Vyas