Estoy usando Ajax.BeginForm para crear un formulario que hará una devolución de datos ajax a una determinada acción del controlador y luego, si la acción es exitosa, el usuario debe ser redirigido a otra página (si la acción falla, se muestra un mensaje de estado usando el UpdateTargetId de AjaxOptions).
using (Ajax.BeginForm("Delete", null,
new { userId = Model.UserId },
new AjaxOptions { UpdateTargetId = "UserForm", LoadingElementId = "DeletingDiv" },
new { name = "DeleteForm", id = "DeleteForm" }))
{
[HTML DELETE BUTTON]
}
Si la eliminación es exitosa, estoy devolviendo un resultado de redireccionamiento:
[Authorize]
public ActionResult Delete(Int32 UserId)
{
UserRepository.DeleteUser(UserId);
return Redirect(Url.Action("Index", "Home"));
}
Pero la vista del índice del controlador de inicio se está cargando en UpdateTargetId y, por lo tanto, termino con una página dentro de una página. Dos cosas en las que estoy pensando:
- O estoy diseñando esto mal y debería manejar este tipo de acción de manera diferente (sin usar ajax).
- En lugar de devolver un resultado de redireccionamiento, devuelva una vista que contenga javascript que realiza el redireccionamiento en el lado del cliente.
¿Alguien tiene comentarios sobre el n. ° 1? O si el n. ° 2 es una buena solución, ¿cómo se vería la "vista de redirección de JavaScript"?
fuente
return JavaScript( "window.location = '" + Url.Action("Edit","Dispatch") + "'" );
Puede devolver un JSON con la URL y cambiar la ubicación de la ventana usando JavaScript en el lado del cliente. Prefiero esta forma que llamar a una función de JavaScript desde el servidor, que creo que está rompiendo la separación de preocupaciones.
Lado del servidor:
return Json(new {result = "Redirect", url = Url.Action("ActionName", "ControllerName")});
Lado del cliente:
if (response.result == 'Redirect') window.location = response.url;
Por supuesto, puede agregar más lógica porque podría haber un error en el lado del servidor y, en ese caso, la propiedad del resultado podría indicar esta situación y evitar la redirección.
fuente
El comportamiento que está intentando producir no se hace realmente mejor con AJAX. AJAX se utilizaría mejor si solo desea actualizar una parte de la página, no redirigir completamente a otra página. Eso frustra todo el propósito de AJAX realmente.
Sugeriría simplemente no usar AJAX con el comportamiento que está describiendo.
Alternativamente, puede intentar usar jquery Ajax, que enviaría la solicitud y luego especificaría una devolución de llamada cuando se complete la solicitud. En la devolución de llamada, puede determinar si falló o tuvo éxito, y redirigir a otra página en caso de éxito. He descubierto que jquery Ajax es mucho más fácil de usar, especialmente porque ya estoy usando la biblioteca para otras cosas de todos modos.
Puede encontrar documentación sobre jquery ajax aquí , pero la sintaxis es la siguiente:
jQuery.ajax( options ) jQuery.get( url, data, callback, type) jQuery.getJSON( url, data, callback ) jQuery.getScript( url, callback ) jQuery.post( url, data, callback, type)
fuente
Aunque no es elegante, me funciona en determinadas situaciones.
Controlador
if (RedirectToPage) return PartialView("JavascriptRedirect", new JavascriptRedirectModel("http://www.google.com")); else ... return regular ajax partialview
Modelo
public JavascriptRedirectModel(string location) { Location = location; } public string Location { get; set; }
/Views/Shared/JavascriptRedirect.cshtml
@model Models.Shared.JavascriptRedirectModel <script type="text/javascript"> window.location = '@Model.Location'; </script>
fuente
Usar
JavaScript
definitivamente hará el trabajo.También puedes usar
Content
si este es más tu estilo.Ejemplo:
Controlador MVC
[HttpPost] public ActionResult AjaxMethod() { return Content(@"http://www.google.co.uk"); }
Javascript
$.ajax({ type: 'POST', url: '/AjaxMethod', success: function (redirect) { window.location = redirect; } });
fuente
Simplemente puede escribir en Ajax Success como se muestra a continuación:
$.ajax({ type: "POST", url: '@Url.Action("GetUserList", "User")', data: { id: $("#UID").val() }, success: function (data) { window.location.href = '@Url.Action("Dashboard", "User")'; }, error: function () { $("#loader").fadeOut("slow"); } });
fuente
Qué tal esto :
public ActionResult GetGrid() { string url = "login.html"; return new HttpStatusCodeResult(System.Net.HttpStatusCode.Redirect,url) }
Y entonces
$(document).ajaxError(function (event, jqxhr, settings, thrownError) { if (jqxhr.status == 302) { location.href = jqxhr.statusText; } });
O
error: function (a, b, c) { if (a.status == 302) { location.href = a.statusText; } }
fuente
Necesitaba hacer esto porque tengo un formulario de inicio de sesión ajax. Cuando los usuarios inician sesión correctamente, redirijo a una nueva página y finalizo la solicitud anterior porque la otra página maneja la redirección de regreso a la parte de confianza (porque es un sistema SSO de STS).
Sin embargo, también quería que funcionara con javascript desactivado, siendo el salto de inicio de sesión central y todo, así que se me ocurrió esto,
public static string EnsureUrlEndsWithSlash(string url) { if (string.IsNullOrEmpty(url)) throw new ArgumentNullException("url"); if (!url.EndsWith("/")) return string.Concat(url, "/"); return url; } public static string GetQueryStringFromArray(KeyValuePair<string, string>[] values) { Dictionary<string, string> dValues = new Dictionary<string,string>(); foreach(var pair in values) dValues.Add(pair.Key, pair.Value); var array = (from key in dValues.Keys select string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(dValues[key]))).ToArray(); return "?" + string.Join("&", array); } public static void RedirectTo(this HttpRequestBase request, string url, params KeyValuePair<string, string>[] queryParameters) { string redirectUrl = string.Concat(EnsureUrlEndsWithSlash(url), GetQueryStringFromArray(queryParameters)); if (request.IsAjaxRequest()) HttpContext.Current.Response.Write(string.Format("<script type=\"text/javascript\">window.location='{0}';</script>", redirectUrl)); else HttpContext.Current.Response.Redirect(redirectUrl, true); }
fuente
Simplemente puede hacer algún tipo de filtro de respuesta ajax para las respuestas entrantes con $ .ajaxSetup . Si la respuesta contiene la redirección MVC, puede evaluar esta expresión en el lado de JS. Código de ejemplo para JS a continuación:
$.ajaxSetup({ dataFilter: function (data, type) { if (data && typeof data == "string") { if (data.indexOf('window.location') > -1) { eval(data); } } return data; } });
Si los datos son: "window.location = '/ Acount / Login'", el filtro anterior lo detectará y evaluará para realizar la redirección.
fuente
No estoy satisfecho con la mejor respuesta de Joseph, en lugar de solucionar el problema correcto, dijo que este es un caso de uso incorrecto. De hecho, hay muchos lugares, por ejemplo, si está convirtiendo una base de código antigua a un código ajaxificado y allí lo NECESITA, entonces lo NECESITA. En programación no hay excusa porque no solo tú estás codificando, todos son buenos y malos desarrolladores y tienes que trabajar codo con codo. Entonces, si no codifico la redirección en ajax, mi compañero desarrollador puede obligarme a tener una solución para ello. Al igual que me gusta usar todos los sitios con patrones de AMD o mvc4, y mi empresa puede mantenerme alejado de ellos durante un año.
Así que hablemos de la solución ahora.
He hecho un infierno de manejo de solicitudes y respuestas ajax y la forma más sencilla que descubrí fue enviar códigos de estado al cliente y tener una función javascript estándar para comprender esos códigos. Si simplemente envío, por ejemplo, el código 13, podría significar una redirección.
Entonces, una respuesta json como {statusCode: 13, message: '/ home / log-in'} por supuesto que hay toneladas de variaciones propuestas como {status: 'success', code: 13, url: '/ home / log-in ', mensaje:' Ha iniciado sesión ahora '}
etc, por lo que depende de su propia elección de mensajes estándar
Por lo general, heredo de la clase base Controller y pongo mi elección de respuestas estándar como esta
public JsonResult JsonDataResult(object data, string optionalMessage = "") { return Json(new { data = data, status = "success", message = optionalMessage }, JsonRequestBehavior.AllowGet); } public JsonResult JsonSuccessResult(string message) { return Json(new { data = "", status = "success", message = message }, JsonRequestBehavior.AllowGet); } public JsonResult JsonErrorResult(string message) { return Json(new { data = "", status = "error", message = message }, JsonRequestBehavior.AllowGet); } public JsonResult JsonRawResult(object data) { return Json(data, JsonRequestBehavior.AllowGet); }
Acerca del uso de $ .ajax en lugar de Ajax.BeginForm Me encantaría usar Jquery ajax y lo hago, pero nuevamente no soy yo en todo el mundo para tomar decisiones.Tengo una aplicación llena de Ajax.BeginForm y, por supuesto, no hice eso. Pero tengo que vivir con eso.
Por lo tanto, también hay una devolución de llamada exitosa en el formulario de inicio, no necesita usar jquery ajax para usar devoluciones de llamada .
Gracias
fuente
Si es redirigido desde la clase JavaScript
misma vista - controlador diferente
<strike>window.location.href = `'Home'`;</strike>
no es la misma vista
<strike>window.location.href = `'Index/Home'`;</strike>
fuente
Agrega una clase de ayuda:
public static class Redirector { public static void RedirectTo(this Controller ct, string action) { UrlHelper urlHelper = new UrlHelper(ct.ControllerContext.RequestContext); ct.Response.Headers.Add("AjaxRedirectURL", urlHelper.Action(action)); } public static void RedirectTo(this Controller ct, string action, string controller) { UrlHelper urlHelper = new UrlHelper(ct.ControllerContext.RequestContext); ct.Response.Headers.Add("AjaxRedirectURL", urlHelper.Action(action, controller)); } public static void RedirectTo(this Controller ct, string action, string controller, object routeValues) { UrlHelper urlHelper = new UrlHelper(ct.ControllerContext.RequestContext); ct.Response.Headers.Add("AjaxRedirectURL", urlHelper.Action(action, controller, routeValues)); } }
Luego llame a su acción:
this.RedirectTo ("Índice", "Cemento");
Agregue código javascript a cualquier archivo global incluido en javascript o archivo de diseño para interceptar todas las solicitudes ajax:
<script type="text/javascript"> $(function() { $(document).ajaxComplete(function (event, xhr, settings) { var urlHeader = xhr.getResponseHeader('AjaxRedirectURL'); if (urlHeader != null && urlHeader !== undefined) { window.location = xhr.getResponseHeader('AjaxRedirectURL'); } }); }); </script>
fuente
Como dice ben foster, puede devolver los javascripts y lo redirigirá a la página deseada.
Para cargar la página en la página actual:
return JavaScript("window.location = 'http://www.google.co.uk'");'
Para cargar la página en la nueva pestaña:
return JavaScript("window.open('http://www.google.co.uk')");
fuente
Puede obtener una redirección no basada en js desde una llamada ajax colocando una de esas metaetiquetas de actualización. Esto aquí parece estar funcionando:
return Content("<meta http-equiv=\"refresh\" content=\"0;URL='" + @Url.Action("Index", "Home") + "'\" />");
Nota: descubrí que Firefox desactiva automáticamente las meta actualizaciones, lo que hace que esto no sea muy útil.
fuente