I am trying to take off the pagination from a couple of Telerik MVC Grids that have a large amount of data loaded into them (upwards of 5000, probably more once they hit production). With our smaller grids, I would just take off the Pageable property(see code below) and the scrolling functionality just works.
With the larger grids I get a JSON error saying that the length of the string exceeds the value set on the maxJsonLength property. I updated the webconfig to be set to the max value as per this links suggestion but it still gave me the same error.
The version of Telerik that I am using is plain Telerik(not Kendo) and is the MVC version (main UI DLL is Telerik.Web.MVC, version 2012.2.801.340).
All documentation that I have found either points me to the new version of Kendo or a RadGrid, which is not included/supported in my version.
Is there a way to acheive this, either by loading it all at once like this does here, or creating a dynamically loading grid using the Telerik version I have, or am I out of luck? I am also open to suggestions for another way to achieve this, but the results have to be in a Grid of some sort.
Below is the basic code for what I have for all grids. The larger grids that I am having issues with have more columns than this one which help account for the JSON error.
#(Html.Telerik().Grid<ApportionmentCode>()
.DataBinding(dataBinding => dataBinding.Ajax().Select("AjaxGetAppCodes", "AppCode"))
.Name("Grid")
.Columns(columns =>
{
columns.Bound(o => o.Id)
.Title("ID")
.Width(50)
.HtmlAttributes(new { #class = "text-center" })
.Hidden();
columns.Bound(o => o.Code)
.Title("AppCode")
.Width(90)
.HtmlAttributes(new { #class = "text-center" });
columns.Bound(o => o.Description)
.Title("Description")
.HtmlAttributes(new { style = "min-width: 200px;" })
.ClientTemplate("<span class=\"clip tooltip\"><#= Description #></span>");
columns.Command(commands =>
{
commands.Custom("edit")
.Text("Edit")
.ButtonType(GridButtonType.Image)
.Action("Edit", "AppCode")
.ImageHtmlAttributes(new { #class = "t-edit", title = "Edit" })
.DataRouteValues(route => route.Add(o => o.Id));
})
.Width(78)
.HtmlAttributes(new { #class = "nowrap" })
.IncludeInContextMenu(false);
})
.ToolBar(commands => commands.Custom()
.Text("Add")
.Action("Create", "AppCode", Request.GetRouteValues())
.ButtonType(GridButtonType.ImageAndText)
.ImageHtmlAttributes(new { #class = "t-add" })
.HtmlAttributes(new { #class = "addButton" }))
.Filterable()
.ClientEvents(events =>
{
events.OnDataBound("onDataBound");
events.OnComplete("AddGridFilter");
events.OnLoad("OnGridLoad");
})
.ColumnContextMenu()
.Sortable()
.Pageable(paging => paging.PageSize(20).Style(GridPagerStyles.NextPreviousAndNumeric).Position(GridPagerPosition.Bottom)) //When removed, this is the line that causes the JSON error
.Resizable(resizing => resizing.Columns(true))
.Scrollable(a => a.Height("auto")))
Thanks in advance
In the controller, I assume you have something like:
DataSourceResult result = model.ToDataSourceResult(request);
return Json(result, JsonRequestBehavior.AllowGet);
If you use the Newtonsoft package and change it to this, this should allow a larger amount of data through.
DataSourceResult result = model.ToDataSourceResult(request);
var json = Newtonsoft.Json.JsonConvert.SerializeObject(result);
return Content(json, "text/json");
EDIT:
If the problem is too much data and you don't want paging, how about trying virtualization by adding:
.Scrollable(scrollable => scrollable.Virtual(true))
You'll still need a page size, an example is here: http://demos.telerik.com/aspnet-mvc/grid/virtualization-remote-data
Related
I have taken over helping with development of a Visual Studio project written in C#, with me sadly not knowing much C# or the way these kind of projects work. Luckily I do have some experience in programming and can make sense of most of it.
However I now have a table with user data that I want to expand to include a column for the email address. I tried going to practically any file, but I can't find where the actual data is gotten from the database. I've commented out a "pro" column that isn't needed anymore, but the new "email" column shows the checkbox that was in the now removed "pro" column.
I've added the line to add the email column to the table and I've added a get, set for it in the .cs file. Can anyone point me in the direction to figure out where all this data is actually pulled from the database?
#(Html.Telerik().Grid<OnsPlatform.ViewModels.Admin_User>(Model.users)
.Name("Grid_Users")
.Columns(columns =>
{
columns.Bound(o => o.userName).Title(Common.AdminUsers_Name);
columns.Bound(o => o.Email).HtmlAttributes(new { #class = "email" }).Title(Common.AdminUsers_email);
columns.Bound(o => o.userID).Hidden();
columns.Bound(o => o.lastVisit).Format("{0:dd-MMM-yy}").Title(Common.AdminUser_LastVisit);
columns.Bound(o => o.nrPageViews).HtmlAttributes(new { #class = "number" }).Title(Common.AdminUsers_NrPageViews);
columns.Bound(o => o.nrComments).HtmlAttributes(new { #class = "number" }).Title(Common.AdminUsers_NrComments);
//columns.Bound(o => o.pro).Title(Common.AdminUsers_Pro);
columns.Template(#<text>
#Common.Edit
</text>).Title(Common.Invitations_Action);
})
.DataKeys(dataKeys => dataKeys.Add(o => o.userID))
.Selectable()
.ClientEvents(events => events.OnRowSelected("onRowSelected"))
.Sortable(sorting => sorting.Enabled(true))
.Pageable(paging => paging.Enabled(true))
)
And I have added the following rule in Admin_User.cs (in the correct place):
public bool Email { get; set; }
Got some help on Reddit, I had to right click the code and select "Go to controller", that sent me to a controller that led me to the eventual right controller where I could add an extra adminUser.Email variable.
Might be better to delete this question as I am very new to all this, but eh, you guys decide.
When I am using a MutliSelect Kendo control, it is not populating the pre selected items. e.g. when it loads it is not loading the ones define in my model
Model.WheelsetExchanges[i].ReasonCodeIds
The kendo control looks like this
#(Html.Kendo().MultiSelectFor(x => Model.WheelsetExchanges[i].ReasonCodeIds)
.Placeholder("Select Reason Code...")
.DataTextField("Value")
.AutoClose(false)
.DataValueField("Id")
.HtmlAttributes(new { #class = "multiselect--clause" })
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetWerReasonCodes", "ReferenceData");
})
.ServerFiltering(true);
})
)
Any idea why the previous selected reason codes are not being displayed when I load the page?
It seems okay what you're doing on the view- but can you check whether you're getting data on the server side?
When I set the datasource to WebAPI binding, the HTTP GET is being invoked on the controller and it returns the correct data. The problem is that my Kendo Grid is not binding the data correctly, instead I get an empty grid as a result.
#(Html.Kendo().Grid(Model)
.Name("Accounts")
.Columns(columns =>
{
columns.Bound(c => c.Description).Title("Account Name");
columns.ForeignKey(c => c.Type, (System.Collections.IEnumerable)ViewData["accountTypes"], "Id", "Name").Title("Account Type");
columns.ForeignKey(c => c.Currency, (System.Collections.IEnumerable)ViewData["currencyTypes"], "Id", "Name").Title("Account Currency");
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(210);
})
.Sortable(sortable =>
{
sortable.SortMode(GridSortMode.SingleColumn);
sortable.AllowUnsort(false);
})
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5)
)
.ToolBar(toolbar => { toolbar.Create(); })
.Editable(editable => editable.Mode(GridEditMode.InLine))
.DataSource(dataSource => dataSource
.WebApi()
.Model(model =>
{
model.Id(p => p.Id);
model.Field(p => p.Currency).DefaultValue(0).Editable(true);
model.Field(p => p.Description).Editable(true);
model.Field(p => p.Type).Editable(true);
})
.ServerOperation(true)
.Read(read => read.Action("Get", "Accounts"))
.Create(create => create.Action("Post", "Accounts"))
.Update(update => update.Action("Put", "Accounts", new { id = "{0}" }))
.Destroy(destroy => destroy.Action("Delete", "Accounts", new { id = "{0}" }))
.PageSize(10)
)
)
Controller
// GET: api/values
[HttpGet]
public DataSourceResult Get([DataSourceRequest]DataSourceRequest request)
{
return _context.Accounts.ToDataSourceResult(request);
}
I always get an HTTP 200 OK as a result of the paging or sorting command, but the grid is empty afterwards. The URL generated by Kendo is:
http://localhost:58829/Accounts/Get?sort=&page=1&pageSize=10&group=&filter=
Which actually returns JSON when I open it with a browser.
The problem seems to be that you are mixing two different ways to load the data. On the one hand you are passing the Model by param to the grid (this approach is used when ServerOperation = false) and on the other hand you are setting ServerOperation = true and specifying a read action.
The reason why the grid is empty in this case is probably because either the Model is empty.
Take a look at this demo example for a reference on how to implement the remote source databinding: http://demos.telerik.com/aspnet-core/grid/remote-data-binding
Example View:
Example controller:
Hope this helps KendoGrid is an awesome library but like many other libraries it could definitely use better exception handling and more user friendly exceptions :) In my opinion the grid should have shown an exception in this case.
The problem was this: when declaring the Kendo Grid and passing the Model as a parameter like so:
#(Html.Kendo().Grid(Model)
You need to remove the .Read() action, and make sure to use .ServerOperation(false). This works either with WebApi binding or Ajax binding:
.DataSource(dataSource => dataSource
.WebApi() // also works with .Ajax()
.Model(model =>
{
model.Id(p => p.Id);
}
)
.ServerOperation(false)
.Create(create => create.Action("Post", "Invoices"))
.Update(update => update.Action("Put", "Invoices", new { id = "{0}" }))
.Destroy(destroy => destroy.Action("Delete", "Invoices", new { id = "{0}" }))
.PageSize(10)
)
Also, the DataSourceResult Get() method can be removed.
I am using Kendo Gridview to display some records. These records are in Json when retrieved from the database and stored in a list of the same class. I have no problem when the list is of count 1000, but any number above 1000 triggers an exception : "Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property."
I have tried changing the maxJsonLength value in web.config and in appsettings as recommended in some of the solutions I found on stack overflow. But none of them work. This is my view:
#(Html.Kendo().Grid(Model)
.Name("grid")
.Scrollable()
.Filterable()
.Columns(columns =>
{
//Columns added here
})
.Selectable(selectable => selectable.Mode(GridSelectionMode.Single))
.Pageable(pageable => pageable
.Refresh(false)
.PageSizes(true)
.ButtonCount(3))
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.Model(model =>
{
model.Id(p => p.Id);
model.Field(p => p.Id).Editable(false);
})
.Read(read => read.Action("Action", "Controller"))
.PageSize(50)
)
.Events(e => e.DataBound("selectDefault"))
I came to realize that the Json Lists that I was passing to the view had too many complex data types(i.e class objects and enums) and that was the reason none of the solutions worked. So I referred to a solution described in this link and created an intermediate view model. In this model I added all the necessary attributes that I wanted and passed it to view. It works really fine now
I am having difficulties controlling the size of Donut component in Kendo-UI (Here).
Here is my code:
<div class="analytic-block">
<h4>Sources</h4>
<span class="text-muted">Recent activity</span>
#(Html.Kendo()
.Chart<ActivityModel>()
.Name("donutChart")
.Legend(legend => legend.Position(ChartLegendPosition.Bottom))
.DataSource(ds => ds
.Read(read => read.Action("Sources", "Statistics"))
.Group(group => group.Add(item => item.SliceLayer))
.Sort(sort => sort.Add(item => Guid.NewGuid().ToString())))
.Series(series =>
{
series.Donut(model => model.Share, model => model.Label, model => model.Color, model => true, mode => true)
.Border(b =>
{
b.Color("white");
b.Width(2);
})
.StartAngle(0)
.Labels(labels => labels.Visible(true)
.Position(ChartPieLabelsPosition.OutsideEnd)
.Template(" #=dataItem.Label #")//.Template("<span style=\"color:#=dataItem.Color#;\"> #=dataItem.Label # </span>")
.Background("transparent")
.Border(1, "grey", ChartDashType.Solid)
.Padding(2))
.Padding(120);
})
.Tooltip(tooltip => tooltip
.Template(" #=dataItem.Label # ")
.Visible(true)))
</div>
and here is the result it produces:
I am able to adjust the size of the chart by changing .Padding(120) but this leaves two large spaces just above and below the chart. I could not find any reference on how to manipulate the size of the area to draw this chart on.
If anyone could suggest a solution, that would be greatly appreciated.
I found my mistake. The div-container must be related to the chart ID:
<div id="donutChart" class="analytic-block">
#(Html.Kendo()
.Chart<ActivityModel>()
.Name("donutChart")
</div>
You should simply set width/height to the div chart element that you turn into a chart.
Here is an example.