Kendo datasource does not trigger error handler to redirect response
I have some Kendo MVC grids related to Json controller remote actions that work very well. The MVC application uses the custom AuthorizeAttribute to authorize access to controller actions, and when the user is not authenticated, it responds with a redirect to the 302 login page. Everything is fine, except that when the session expires, data read calls with data sources fail fail as they receive a redirect response instead of the expected data. I tried to handle this situation in the data source error event handler, but the handler is not 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 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 am missing regarding this error handler?
source to share
As it turns out, the browser automatically follows the redirect to xhr, and the kendo datasource has no way of knowing about it. And since the redirect returns a status code of 200, the error handler doesn't run at all. In my opinion, since the response is in no way in json format and cannot be bound to a data source, the error handler must be triggered by the kendo data source.
Anyway...
My solution was to change the custom AuthorizeAttribute to return a 401 (unauthorized) status code, but only for ajax requests. This way, the data source error handler will be called and be able to respond 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" }));
This is what the datasource error handler 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 bit location.reload()
actually refreshes the page and puts the browser in the normal authentication workflow.
source to share