2

I have some Kendo MVC grids bound to remote Json controller actions which work very well. The MVC application uses a custom AuthorizeAttribute for authorizing access to the controller actions and when a user is not authenticated it replies with a 302 redirect to the login page. Everything is fine, except that when the session expires, the datasource read calls fail silently as they receive the redirect response instead of the expected data. I have tried handling this situation in the error event handler of the datasource, but the handler does not get called in this situation.

This is the error handler:

function childGrid_error(e, gridName) {
    if (e.xhr.status === 302)
        location.reload();
    else
        if (e.errors) {
            var message = "";
            $.each(e.errors, function (key, value) {
                if ('errors' in value) {
                    $.each(value.errors, function () {
                        message += this + "\n";
                    });
                }
            });
            kendoAlert(message);
            var grid = $(gridName).data("kendoGrid");
            grid.cancelChanges();
        }
}

And this is a Kendo Datasource, in Razor syntax:

.DataSource(ds => ds
               .Ajax()
               .Model(m => m.Id(c => c.Id))               
               .Sort(s=>s.Add(f=>f.Username))
               .PageSize(10)
               .Events(e => e.Error("function(e) { grid_error(e, \"UsersGrid\");}"))
               .Read("GetUsers", "Admin")
               .Create("PutUser", "Admin")
               .Destroy("DeleteUser", "Admin")
               .Update("UpdateUser", "Admin"))

Is there something I'm missing regarding this error handler?

Mihai Caracostea
  • 8,336
  • 4
  • 27
  • 46

1 Answers1

0

As it turns out, the browser automatically follows the redirect on the xhr and the kendo datasource can not know about this in any way. And since the redirect returns a 200 status code, the error handler does not get fired at all. In my opinion, since the response is in no way in json format and cannot possibly get bound to by the datasource, the error handler should get fired by the kendo datasource.

Anyway...

My solution was to modify the custom AuthorizeAttribute in order to return a 401 (Unauthorized) status code, but only for the ajax requests. This way, the datasource error handler would get called and would be able to react to the expired session issue.

Relevant code in the custom AuthorizeAttribute:

if (filterContext.HttpContext.Request.IsAjaxRequest())
                    filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.Unauthorized);
                else
                    filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Auth", action = "Login" }));

And this is how the datasource error handler now looks like:

function childGrid_error(e, gridName) {
    if (e.xhr.status === 401) //Unauthorized
        location.reload();
    else
        if (e.errors) {
            var message = "";
            $.each(e.errors, function (key, value) {
                if ('errors' in value) {
                    $.each(value.errors, function () {
                        message += this + "\n";
                    });
                }
            });
            kendoAlert(message);
            var grid = $(gridName).data("kendoGrid");
            grid.cancelChanges();
        }
}

The location.reload() bit actually does a page refresh and puts the browser in the normal authentication work flow.

Mihai Caracostea
  • 8,336
  • 4
  • 27
  • 46