Recently I had the need to make some ajax calls within a MVC 3.0 with Razor and jQuery application.  After a bit of trial and error and refactoring it was discovered that a number of different needs were required.  These included:The serverside code would be responsible for creating any redirect urls and we wanted to stick with the inherited controller RedirectToAction() method where possible in our controller actions.We are using jQuery unobtrusive validation and some situations meant that new forms were rendered onto the view via ajax.  That meant we needed to ensure those new form fields contained and validated when required.We wanted the flexibility to return html (PartialViews), json or tell the client side it was a redirect and the URL to redirect to (initiated via 1 above).Before page redirects at times we wanted to show div popups such as a Success confirmation.  Hence although we were using RedirectToAction() in the backend we wanted the javascript to actually perform the redirect.With these in place we did a bit of serverside code that ensured we hijacked the RedirectToAction() result and returned a json object instead.  I'm fairly happy that code works.  What I'm not sure about is the javascript code that I use to perform the result.  Some notes:The $.validator.unobtrusive.parseDynamicContent method will ensure the new html elements are rebound for validation.  I did not write that code so have not added it for review.For options 1, 2 and 3 above we didn't want the person writing the ajax to always have to worry about these so esentially wanted them to just be handled so to speak.I'm definitely pretty raw in the Javascript department so any comments or improvements on the code below would be greatly appreciated.$.ajaxWithRedirect = function (options) {    // If dataType wasn't specified in the options, default to 'html'    var dataType = (options.dataType !== undefined) ? options.dataType : 'html';    // jQuery AJAX object    $.ajax({        // Normal properties        type: options.type,        url: options.url,        data: options.data,        dataType: dataType,        cache: false,        // Global beforeSend wrapper with user defined function        beforeSend: function () {            // Execute user defined method            if (typeof options.beforeSend === 'function') {                options.beforeSend();            }        },        // Global success wrapper which will redirect if url specified is a json object        // with the RedirectUrl tag        success: function (data) {            var jData;            var redirected = false;            try {                if (data) {                    jData = $.parseJSON(data);                    if (jData && (typeof jData.RedirectUrl !== 'undefined' && jData != null && jData.RedirectUrl.length > 0)) {                        var performRedirect = true;                        if (typeof options.beforeRedirect !== 'undefined') {                            // beforeRedirect returns true if the redirect is still to occur otherwise false                            performRedirect = options.beforeRedirect(jData);                        }                        if (performRedirect) {                            redirected = true;                            // Using replace based off SO - http://stackoverflow.com/questions/503093/how-can-i-make-a-redirect-page-in-jquery-javascript                            window.location.replace(jData.RedirectUrl);                        }                    }                }            } catch (e) {                // not json            }            // Execute user defined method            if (!redirected) {                if ((options.success && typeof options.success === 'function')) {                    options.success(data);                }                // always done after the success to ensure any dyanamic elements have been loaded                if (typeof options.dynamicValidation != 'undefined') {                    $.validator.unobtrusive.parseDynamicContent(options.dynamicValidation);                }            }        },        error: function (xhr, status, err) {            if (typeof options.error === 'function') {                options.error(xhr, status, err);            }            if (xhr.status == 400) {                alert(err);            }        }    });};Example of usage is (Methods such as addUploadTableSpinner just included for examples):$.ajaxWithRedirect({    beforeSend: addUploadTableSpinner(),    type: POST,    url: '/MyUrl/Delete' + '?sessionId=' + sessionId,    dataType: html,    beforeRedirect: function (data) {        closePopup();        // show the user success message        showDeleteSuccessfulPopup(data.RedirectUrl);        showSuccessfulPopup = false;        // don't do the redirect        return false;    },    success: function (data) {        if (data.length == 0) {            deleteRow.remove();        } else if (showSuccessfulPopup) {            deleteRow.html(data);            closePopup();            showDeleteSuccessfulPopup();        }        removeUploadTableSpinner();    }});
Wrapper for jquery ajax to ensure redirects occur on clientside
javascript;jquery;asp.net mvc 3
It seems to me that you're duplicating some of what $.ajax() will do for you (such as calling beforeSend) and you're also leaving the door open for using the deferred promise methods (then, done, fail, etc.) that jQuery's XHR object provides.Here's a version that focusses solely on the redirection (i.e. it doesn't worry about the data type, the validation stuff, or doing its own error handling). It's just a transparent layer on top of the normal $.ajax() function.The code's below, and here's a demo$.ajaxWithRedirect = function (options) {  use strict;  var deferred = $.Deferred(),      successHandler,      xhr;  // force no-cache  options.cache = false;  // get a copy of the success handler...  successHandler = options.success;  // ... and replace it with this one  options.success = function (data) {    var contentType = xhr.getResponseHeader(Content-Type),        performRedirect = true,        redirectUrl = null,        args = [].slice.call(arguments, 0),        json;    // If response isn't there or isn't json,    // skip all the redirect logic    if( data && (/json/i).test(contentType) ) {      // If json was requested, and json received, jQuery will      // have parsed it already. Otherwise, we'll have to do it      if( options.dataType === 'json' ) {        redirectUrl = data.RedirectUrl;      } else {        try {          json = $.parseJSON(data);          redirectUrl = json.RedirectUrl;        } catch(e) {          // no-op        }      }      // check the redirect url      if( redirectUrl && typeof redirectUrl === 'string') {        // Is there a beforeRedirect handler?        if( typeof options.beforeRedirect === 'function' ) {          // pass all the arguments to the beforeRedirect handler          performRedirect = options.beforeRedirect.apply(null, args);        }        // unless strictly false, go ahead with the redirect        if( performRedirect !== false ) {          location.replace(redirectUrl);          // and stop here. No success and/or deferred handlers          // will be called since we're redirecting anyway          return;        }      }    }    // no redirect; forward everything to the success handler(s)    if( typeof successHandler === 'function' ) {      successHandler.apply(null, args);      deferred.resolve.apply(null, args);    }  };  // Make the request  xhr = $.ajax(options);  // Forward the deferred promise method(s)  xhr.fail(deferred.reject);  xhr.progress(deferred.notify);  // Replace the ones already on the xhr obj  deferred.promise(xhr);  return xhr;};Point is that you should be able use $.ajaxWithRedirect exactly like you'd use vanilla $.ajax, including all the shiny deferred promise stuff. The only thing it does different from the normal version is set options.cache = false, and that it has a beforeRedirect callback.