35

Using Kendo UI in MVC4 I have a Grid that makes Ajax calls for data back into the Controller:

    public ActionResult SearchUser_Read([DataSourceRequest]DataSourceRequest request)
    {
        var data = CreateAnExcaptionHere();
        return Json(data.ToDataSourceResult(request));
    }

How do I use this call to inform the page that there was an error?

numaroth
  • 1,295
  • 4
  • 25
  • 36
Ian Vink
  • 66,960
  • 104
  • 341
  • 555

6 Answers6

52

If you need to display an error message from the server then you can do it by returning a DataSourceResult object with only its Errors property set:

return this.Json(new DataSourceResult
            {
                Errors = "my custom error"
            });

And pick it up on the client by using this (referenced by the .Events(events => events.Error("onError")) line):

function onError(e, status) {
    if (e.status == "customerror") {
        alert(e.errors);
    }
    else {
        alert("Generic server error.");
    }
}
Drew Delano
  • 1,421
  • 16
  • 21
  • 10
    I suggest you to use the ModelState `catch (Exception exc) { ModelState.AddModelError(string.Empty, exc.Message); return Json(new UserModel[0].ToDataSourceResult(request, ModelState)); }` In this case you will be able to use the same error handler for Update action validation and Delete\Read actions. (because during validation Erorrs are array[][] and not a string) – SerjG Feb 05 '15 at 10:39
  • 3
    if you use the ModelState as @Sergey suggested you have to use `e.errors[""].errors` in the `onError(e, status) ` method to access the error values. The string in the e.errors object is whatever key value you supplied to `ModelState.AddModelError` . Then you can loop through and display all the errors like so: `var errors = e.errors[""].errors; var errorMessage; for (var i = 0; i < errors.length; i++) { errorMessage = errors[i]; }` – iambdot Feb 12 '15 at 21:23
  • 1
    @Drew Delano. I am not able to find any property called " Errors " in " DataSourceResult ". Please advice. – Sachin Trivedi Dec 05 '15 at 08:33
  • My JavaScript method `function onError(e) { if (e.errors) { var message = "Errors:\n"; $.each(e.errors, function (key, value) { if ('errors' in value) { $.each(value.errors, function() { message += this + "\n"; }); } }); alert(message); } }` – Jeremy Ray Brown Oct 26 '16 at 18:56
  • @SachinTrivedi The "Errors" into "DataSourceResult" from MVC controller: `ModelState.AddModelError("Error", "Error occurred!");` `return Json(onDemandApps.ToDataSourceResult(request, ModelState));` That is easiest way to do it. – Jeremy Ray Brown Oct 26 '16 at 19:09
  • Unfortunately, there is no errors element on the handler function parameter. Kendo is a poor choice of frameworks, if you can't identify errors. – Suncat2000 Dec 08 '16 at 20:11
  • I'm guessing Telerik dropped it a while back. I no longer have access to a Kendo license so I can't update it with an answer that would work. I keep thinking someone will post a new answer here. – Drew Delano Dec 12 '16 at 03:42
  • I found out the hard way that the HTTP response status code - counter-intuitively - _must be_ *200* (OK) in order for the Kendo error handling to work right; populating `DataSourceResult` with an `Errors` member will be processed correctly _only_ if the status code indicates success(!). `ToDataSourceResult()` translates the `Errors` member into the error handler argument's `errors` member and triggers the OnError event. Some of this information is actually buried in the Kendo documentation if you are stubborn enough to keep digging for it. – Suncat2000 Jan 04 '17 at 14:58
  • In my case, the error function is being called on "update" event as well and showing the previous error which wasn't being returned from the server. – IntelligentCancer Jan 31 '22 at 06:35
28

Found it, Kendo supports it by just adding a Event to the DataSource the JS function to call. That's it.

  .DataSource(dataSource => dataSource
      .Ajax()
      .Events(events => events.Error("onError"))
      .Read(read => read.Action("SearchUser_Read", "Search").Data("parentModel"))
  )

<script> 
    function onError(e, status) {
          alert("A server error has occurred!");
}
</script>
Ian Vink
  • 66,960
  • 104
  • 341
  • 555
  • Is there something missing here? the first bit doesn't look like valid JS and the capitalization is all wrong for JS too. – Lawrence Dol Sep 01 '13 at 23:54
  • 4
    No, the top part is standard Kendo using the Razor format. This all makes sense and works. – Rethic Jan 13 '14 at 20:39
  • 1
    You still need a mechanism to pass the error data from the controller to the grid, so unfortunately there's more to it. – Suncat2000 Dec 08 '16 at 20:14
13

To extend Drew's answer just a little bit: we usually want to roll back the change in the Kendo Grid also when an error occurs. Otherwise, if an error is thrown as an item is deleted from the grid, for instance, it will still appear to be deleted even though the error was thrown and a message was shown.

This function also cancels the changes in any grids that are using the data source that threw an error:

function onError(e, status) {

    // Cancel changes on any grids on the page that are using this data source
    $('.k-grid').each(function (item) {
        var grid = $(this).data("kendoGrid");
        if (e.sender === grid.dataSource) {
            grid.cancelChanges();
        }
    });

    if (e.status == "customerror") {
        alert(e.errors);
    }
    else {
        alert("Generic server error.");
    }

}
Matt
  • 3,676
  • 3
  • 34
  • 38
  • In the same vein, to get the specific kendo grid which caused the datasource read, e.g. which was sorted, you can use `$(e.sender.options.table.context).data("kendoGrid")`. – Rhumborl Nov 27 '14 at 11:30
  • @Rhumborl my e.sender.options.table is null. Any idea why that might be? – Shawn de Wet Nov 21 '15 at 04:53
2

Try to raise the exception and check whether it is prompting an alert message or not.

For Kendo grid, there is error event which might be helpful for you.

http://docs.kendoui.com/documentation/getting-started/using-kendo-with/aspnet-mvc/migration/widgets/grid

We used telerik mvc grids which automatically displays alert messages if there is any error while binding.

http://www.telerik.com/community/forums/aspnet-mvc/grid/exception-handling.aspx

http://www.telerik.com/community/forums/aspnet-mvc/grid/how-to-do-error-handling-in-gridaction-methods.aspx

Sunny
  • 4,765
  • 5
  • 37
  • 72
  • 1
    Unfortunatly, the Kendo Grid does not handle exceptions in the Controller when accessing data via Ajax it seems. I am wondering if there is a message that we can send back though that it might pick up on – Ian Vink Nov 30 '12 at 22:24
  • If you are manually binding the grid using JQuery ajax requests, try sending the error message from "onexception" method of the controller. – Sunny Nov 30 '12 at 22:31
  • The last two links are premium-access only. – Bardicer Dec 28 '15 at 17:23
0

For Read data, you should not add exemption to ModelState and return it Like you would do it for Create Update and Delete Requested, Instead add the error to datasource object and handle it with the same jquery onerror event.

 public virtual JsonResult Read_Tasks([DataSourceRequest] DataSourceRequest request) 
    {
        try
        {
            return Json(ListAll().ToDataSourceResult(request));
        }
        catch (Exception ex)
        {
            string exmptionText = ex.Message;

            ModelState.AddModelError(string.Empty, exmptionText); //This will not work 
            Logger.Error(exmptionText + ex.StackTrace);

            return this.Json(new DataSourceResult
            {
                Errors = new
                {
                    a = new { errors = new[] { exmptionText } }
                }
            });
        }
    }

function error_handler(e)
    {
        if (e.errors)
        {
        var message = "Errors:\n";
        $.each(e.errors, function (key, value) {
            if ('errors' in value) {
                $.each(value.errors, function () {
                    message += this + "\n";
                });
            }

 alert(message );
        });

     
    }
david hosni
  • 11
  • 1
  • 5
-4

How about

throw new HttpResponseException(HttpStatusCode.BadRequest);
Undo
  • 25,519
  • 37
  • 106
  • 129
user714157
  • 399
  • 2
  • 4
  • 18