Hello,
I currently have an ASP.NET MVC application that is primarily composed of a hierarchical grid and custom edit templates. I want to display a simple error page to indicate a failed database operation to the user.
I tried a standard approach adding the following to the Web.Config file:
<customErrors mode="On"></customErrors>
I also added the following attribute at the beginning of my controller classes:
[HandleError(ExceptionType = typeof(DbUpdateException), View = "Error")]
The error page, Error.cshtml is located in the Views/Shared directory of the application.
I cannot get this to work. I can't even view the error page in the browser. I get a 404 error when I right click on the file and select view in browser.
Are there any general error handling guidelines for Telerik UI for ASP.NET MVC? I looked, but couldn't find anything fairly recent. If any such guidelines / documentation exists, where would I find it?
Thanks
5 Answers, 1 is accepted

For some reason, my grid doesn't have the Error event available. When I tried to reference it, I got the following message: GridEvent builder does not contain a definition for "Error" and no accessible extension method Error accepting a first argument type
of GridEventBuilder. I'm using Visual Studio 2019 with the latest version of Kendo UI for ASP.NET MVC.
My grid code isn't anything special.
@(Html.Kendo().Grid<DonationManagement2019.Models.Donor>()
.Name("donors")
.Columns(columns =>
{
columns.Bound(c => c.DonorName).Width(600);
columns.Bound(c => c.Address).Width(600);
columns.Bound(c => c.City).Width(175);
columns.Bound(c => c.State).Width(85);
columns.Bound(c => c.ZipCode).Width(120);
columns.Bound(c => c.Email).Width(390);
columns.Bound(c => c.PrimaryPhone).Width(150);
columns.Bound(c => c.PhoneExt).Width(75);
columns.Bound(c => c.DonorType).Width(175);
columns.Bound(c => c.DonorCategory).Width(160);
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(200);
})
//.HtmlAttributes(new { style = "width: 1500px;" })
.ToolBar(toolbar =>
{
toolbar.Create();
})
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("Donor"))
.Pageable()
.Sortable(sortable =>
{
sortable.SortMode(GridSortMode.SingleColumn);
})
.Filterable()
.Scrollable(scrollable => scrollable.Enabled(false))
.ClientDetailTemplateId("template")
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(p => p.DonorId))
.Read(read => read.Action("Donors_Read", "Home"))
.Create(create => create.Action("Donors_Create", "Home"))
.Update(update => update.Action("Donors_Update", "Home"))
.Destroy(destroy => destroy.Action("Donors_Destroy", "Home"))
)
.Events(events => events.DataBound("dataBound"))
)
<script id="template" type="text/kendo-tmpl">
@(Html.Kendo().TabStrip()
.Name("tabStrip_#=DonorId#")
.SelectedIndex(0)
.Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
.Items(items =>
{
items.Add().Text("Donations" +
"").Content(@<text>
@( Html.Kendo().Grid<DonationManagement2019.Models.Donation>()
.Name("grid_#=DonorId#") // template expression, to be evaluated in the master context
.Columns(columns =>
{
columns.Bound(d => d.DonationDate).Format("{0:MM/dd/yyyy}").Width(70);
columns.Bound(d => d.FiscalYear).Width(110);
columns.Bound(d => d.Campaign);
columns.Bound(d => d.DonationAmount).Format("{0:C}").Width(200);
columns.Bound(d => d.DonationMethod).Width(200);
columns.Bound(d => d.Notes);
columns.Bound(d => d.RecordedOn).Format("{0:MM/dd/yyyy}");
columns.Bound(d => d.UpdatedOn).Format("{0:MM/dd/yyyy}");
columns.Command(command => { command.Edit(); command.Destroy(); });
})
.ToolBar(toolbar =>
{
toolbar.Create();
})
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("Donation"))
.DataSource(dataSource => dataSource
.Ajax()
.Events(ev => ev.RequestEnd("onRequestEnd"))
.Model(model => model.Id(d => d.DonationId))
.PageSize(10)
.Read(read => read.Action("Donations_Read", "Donations", new { parentID = "#=DonorId#" }))
.Create(create => create.Action("Donations_Create", "Donations", new { parentID = "#=DonorId#" }))
.Update(update => update.Action("Donations_Update", "Donations", new { parentID = "#=DonorId#" }))
.Destroy(destroy => destroy.Action("Donations_Destroy", "Donations"))
)
.Pageable()
.Sortable()
.Filterable()
.ClientDetailTemplateId("customtemplate")
.ToClientTemplate())
</text>
);
items.Add().Text("Notes ").Content(
"<div class='donor-details'>" +
"<ul>" +
"<li><label>Notes:</label>#= Notes#</li>" +
"</ul>" +
"</div>"
);
})
.ToClientTemplate())
</script>
<script id="customtemplate" type="text/kendo-tmpl">
@(Html.Kendo().TabStrip()
.Name("tabStrip_#=DonationId#")
.SelectedIndex(0)
.Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
//.Items(items =>
//{
// items.Add().Text("Donation Notes").Content(
// "<div class='donor-details'>" +
// "<ul>" +
// "<li><label>Notes:</label>#= Notes#</li>" +
// "</ul>" +
// "</div>"
// );
//})
.ToClientTemplate())
</script>
<script>
function dataBound() {
this.expandRow(this.tbody.find("tr.k-master-row").first());
}
var detailExportPromises = [];
function employees_detailInit(e) {
var deferred = $.Deferred(); /
// get the index of the master row
var masterRowIndex = e.masterRow.index(".k-master-row");
// add the deferred to the list of promises
detailExportPromises.push(deferred);
}
(function () {
window.onRequestEnd = function (e) {
if (e.response.Data && e.response.Data.length) {
var data = e.response.Data;
if (this.group().length && e.type == "read") {
handleGroups(data);
} else {
loopRecords(data);
}
}
}
function handleGroups(groups) {
for (var i = 0; i < groups.length; i++) {
var gr = groups[i];
offsetDateFields(gr); //handle the Key variable as well
if (gr.HasSubgroups) {
handleGroups(gr.Items)
} else {
loopRecords(gr.Items);
}
}
}
function loopRecords(donations) {
for (var i = 0; i < donations.length; i++) {
var donation = donations[i];
offsetDateFields(donation);
}
}
function offsetDateFields(obj) {
for (var name in obj) {
var prop = obj[name];
if (typeof (prop) === "string" && prop.indexOf("/Date(") == 0) {
obj[name] = prop.replace(/\d+/, function (n) {
var offsetMiliseconds = new Date(parseInt(n)).getTimezoneOffset() * 60000;
return parseInt(n) + offsetMiliseconds
});
}
}
}
})();
//function employees_excelExport(e) {
// // prevent saving the file because we will update the workbook
// e.preventDefault();
// var workbook = e.workbook;
// // Export all detail grids
// $("[data-role=grid]", this.element).each(function () {
// $(this).data("kendoGrid").saveAsExcel();
// });
// // wait for all detail grids to finish exporting
// $.when.apply(null, detailExportPromises)
// .then(function () {
// // get the export results
// var detailExports = $.makeArray(arguments);
// // sort by masterRowIndex
// detailExports.sort(function (a, b) {
// return a.masterRowIndex - b.masterRowIndex;
// });
// // add an empty column
// workbook.sheets[0].columns.unshift({ width: 30 });
// // prepend an empty cell to each row
// for (var i = 0; i < workbook.sheets[0].rows.length; i++) {
// workbook.sheets[0].rows[i].cells.unshift({});
// }
// // merge the detail export sheet rows with the master sheet rows
// // loop backwards so the masterRowIndex doesn't need to be updated
// for (var i = detailExports.length - 1; i >= 0; i--) {
// var masterRowIndex = detailExports[i].masterRowIndex + 1;
// var sheet = detailExports[i].sheet;
// // prepend an empty cell to each row
// for (var ci = 0; ci < sheet.rows.length; ci++) {
// if (sheet.rows[ci].cells[0].value) {
// sheet.rows[ci].cells.unshift({});
// }
// }
// // insert the detail sheet rows after the master row
// [].splice.apply(workbook.sheets[0].rows, [masterRowIndex + 1, 0].concat(sheet.rows));
// }
// // save the workbook
// kendo.saveAs({
// dataURI: new kendo.ooxml.Workbook(workbook).toDataURL(),
// fileName: "Export.xlsx"
// });
// });
//}
</script>
<style>
.k-detail-cell .k-tabstrip .k-content {
padding: 0.2em;
}
.donor-details ul {
list-style: none;
font-style: italic;
margin: 15px;
padding: 0;
}
.donor-details ul li {
margin: 0;
line-height: 1.7em;
}
.donor-details label {
display: inline-block;
width: 150px;
padding-right: 10px;
text-align: right;
font-style: normal;
font-weight: bold;
}
</style>

This is the example I tried to use. The grid in the example has an Error event available, my grid does not.
// Omitted for brevity..
.DataSource(dataSource => dataSource.Ajax()
.Events(events => events.Error("onError"))
// Omitted for brevity.
<script>
function onError(e, status) {
alert("A server error has occurred!");
}
</script>
Example source: https://docs.telerik.com/aspnet-mvc/html-helpers/data-management/grid/faq
Hi Sheila,
The example in the documentation might not showing where the Error event is available. You should search for this event in the Events method of the DataSource, not the Grid. Here you are a code example that might shed more light on the case:
@(Html.Kendo().Grid<TelerikMvcApp3.Models.OrderViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.OrderID).Filterable(false);
columns.Bound(p => p.Freight);
columns.Bound(p => p.OrderDate).Format("{0:MM/dd/yyyy}");
columns.Bound(p => p.ShipName);
columns.Bound(p => p.ShipCity);
})
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.HtmlAttributes(new { style = "height:550px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Orders_Read", "Grid"))
.Events(events => events.Error("onError")) // DataSource events
)
.Events(events => events.DataBound("onDataBound")) // Grid events
)
I hope that helps.
Regards,
Ianko
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.

Thanks for the example Ianko.
I'll give it a try.
Hi Sheila,
Let me know if you need any further assistance on the case.
Regards,
Ianko
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.