Reputation: 95
I have an ASP MVC application that lets a user add multiple partial views to a div with jQuery ajax calls.
jQuery("#AddNew").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) {
jQuery("#DivId").append(html);
}
});
return false;
});
The problem is that since a user must be authorized for the action returning the partial view, when a user's session has timed out, it is rendering the login page instead of the partial view. I have multiple places that are using similar ajax calls, so I added the following as a global ajaxSuccess event:
jQuery(document).ajaxSuccess(function (event, request, settings) {
var isLogin = jQuery(request.responseText).find('.login-form').length;
if (isLogin > 0) {
var url = document.URL;
var rootPath = '@Request.Url.GetLeftPart(UriPartial.Authority)';
var path = url.replace(rootPath, '');
var pathEncoded = encodeURIComponent(path);
var loginURL = rootPath + "/Account/Login?returnUrl=" + pathEncoded;
location.href = loginURL;
}
});
This works, as it will redirect the user to the login page when an unauthorized ajax request is made. However, it is still adding the html to the div, which is visible for a short time before the redirect.
Is there a way to get the global event to trigger before the local one? The jQuery API shows that the local success event is triggered before the global ajaxSuccess event, so I tried changing the ajax call to use complete, rather than success. This does work, but it seems like if for some reasons I needed to add code in the future that only executes on success, that I'll run into the same problem. Is there a better way to handle this?
Upvotes: 1
Views: 688
Reputation: 745
I might advise creating your own API wrapping the ajax
method which ensures the functionality you desire (in particular, the order of operations). Here's a very over-simplified example:
var async = function(props) {
var finished = $.Deferred();
$.ajax(props)
.done(function(response) {
// detect auth timeout, handle consisently
if(response.isAuthTimeout) {
// render login ui
finished.reject('auth-timeout');
} else {
finished.resolve.apply(finished, arguments);
}
})
.fail(function() {
finished.reject.apply(finished, arguments);
})
return finished;
};
Then, in practice you'll make calls to async
(or whatever you decide to call your wrapper) rather than the native $.ajax
API.
Make sense?
Upvotes: 2