RedirectToAction en @Ajax.BeginForm

Durante varias revisiones de código, me he dado cuenta de que en ocasiones se está evitando el uso de formularios AJAX en ASP.NET MVC (cuando todos los formularios de la aplicación lo son) por el simple hecho de que no es posible realizar una redirección al ser, evidentemente, una recarga parcial de la página. En este post voy a hablar de una posible solución a este caso:

El controlador

En el lado del controlador, normalmente cuando queremos redirigir al usuario a otra acción lo hacemos de la siguiente manera:

using System.Web.Mvc;

namespace AjaxRedirection.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult GoToTheDarkSide()
        {
            return RedirectToAction("DarkSide");
        }

        public ActionResult DarkSide()
        {
            return View();
        }
    }
}

Obviamente, en el caso de una petición AJAX, esta redirección es necesaria gestionarla de otra forma, puesto que lo más que podemos obtener es que toda la página se incluya dentro del fragmento que hayamos elegido para la carga parcial :P.

Para poder manejar el escenario que esperamos, una posible solución sería la siguiente:

        [HttpPost]
        public ActionResult GoToTheDarkSideAjax()
        {
            Thread.Sleep(3000);
            return Json(new { NewUrl = @Url.Action("DarkSide") });
        }

Al ser un ejemplo muy muy simple 🙂 he puesto un Thread.Sleep(3000); para que el servidor espere 3 segundos antes de indicar que necesita una redirección como resultado. Básicamente, lo que hacemos en este caso es devolver un objeto JSON con una propiedad llamada NewUrl que indicará al cliente a dónde debe dirigirse una vez terminada la petición.

Redirección en el cliente

Una vez que hemos hecho la petición AJAX, la forma para controlar si debemos redirigirnos o no podría ser la siguiente:

$(document).ajaxComplete(function (event, xhr, settings) {

    var jsonResult = JSON.parse(xhr.responseText);

    if (jsonResult != undefined && jsonResult.NewUrl)
        window.location = jsonResult.NewUrl;

});

En este ejemplo he asumido que este comportamiento debe manejarse a nivel global en la aplicación. Para ello he utilizado .ajaxComplete para que todas las peticiones ajax a través de JQuery sean controladas una vez hayan sido completadas. Cuando esto ocurre, comprobamos que dicha petición ha retornado un objeto JSON y que además contenga la propiedad NewUrl. En caso afirmativo lo único que tenemos que hacer es utilizar window.location para dirigirnos al lugar indicado por esta propiedad.

¡Saludos!