net mvc filters attribute asp asp.net-mvc redirecttoaction

asp.net mvc - mvc - ¿Cómo hacer para que el filtro redirija a otra acción?



filters asp net mvc 5 (5)

RedirectToAction está protegido y solo podemos usarlo dentro de las acciones. Pero si quiero redirigir en un filtro?

public class IsGuestAttribute: ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { if (!Ctx.User.IsGuest) filterContext.Result = (filterContext.Controller as Controller) .RedirectToAction("Index", "Home"); } }


Aquí hay un ejemplo de código:

public override void OnActionExecuting(ActionExecutingContext filterContext) { if (!Ctx.User.IsGuest) { RouteValueDictionary redirectTargetDictionary = new RouteValueDictionary(); redirectTargetDictionary.Add("action", "Index"); redirectTargetDictionary.Add("controller", "Home"); filterContext.Result = new RedirectToRouteResult(redirectTargetDictionary); } }


Sé que llegué un poco tarde a la fiesta, pero utilicé la solución de veggerby y construí una clase de ayuda que puede ser útil para algunas personas, así que quería brindarla aquí:

public static class ActionFilterHelpers { public static void Redirect(this ActionExecutingContext filterContext, String controller, String action, object routeValues) { filterContext.Result = Redirect(controller, action, routeValues); } public static ActionResult Redirect(String controller, String action, object routeValues) { var routeValues = new RouteValueDictionary(); routeValues["controller"] = controller; routeValues["action"] = action; foreach (var keyValue in new ObjectDictionary(routeValues)) routeValues.Add(keyValue.Key, keyValue.Value); return new RedirectToRouteResult(routeValues); } }

Proporcioné un método estático que devuelve un ActionResult redirección y un método de extensión que amplía filterContext . Espero que alguien encuentre esto útil.

ObjectDictionary es una clase que usa la reflexión para crear un diccionario a partir de las propiedades del objeto desde el que está construido. No incluí ese código porque creo que hay una manera mejor de hacerlo en algún lugar del marco. Aún no lo he encontrado, pero no quiero que otros hereden mis posibles errores.


Seguridad / Autorización / Autenticación Los filtros deben usar AuthorizeAttribute y IAuthorizationFilter .

public class IsGuestAttribute: AuthorizeAttribute, IAuthorizationFilter { public void OnResultExecuted(ResultExecutedContext filterContext) { } public void OnActionExecuting(ActionExecutingContext filterContext) { if (!Ctx.User.IsGuest) { filterContext.Result = new RedirectToRouteResult( new RouteValueDictionary { { "controller", "Home" }, { "action", "Index" } }); } } }


RedirectToAction es solo un método auxiliar para construir un RedirectToRouteResult() , entonces lo que usted hace es simplemente crear un nuevo RedirectToRouteResult() pasando a lo largo de un RouteValueDictionary() con valores para su acción.

Muestra completa basada en el código de @Domenic en el comentario a continuación:

public class IsGuestAttribute: ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { if (!Ctx.User.IsGuest) { filterContext.Result = new RedirectToRouteResult( new RouteValueDictionary { { "controller", "Home" }, { "action", "Index" } }); } } }


Uso: filterContext.RedirectToAction("Login", "Account");

Aquí hay una clase de ayuda que escribí con algunos métodos de extensión escritos para proporcionar la funcionalidad RedirectToAction en más lugares. Esto es demasiado tarde para el OP, pero espero que ayude a alguien.

public static class RedirectHelper { // RedirectToAction Extension Methods public static void RedirectToAction(this HttpResponseBase response, String action, String controller, object routeValues = null, bool endResponse = false) { response.RedirectToRoute(CreateRoute(action, controller, routeValues)); if (endResponse) response.End(); } public static void RedirectToAction(this HttpResponse response, String action, String controller, object routeValues = null, bool endResponse = false) { response.RedirectToRoute(CreateRoute(action, controller, routeValues)); if (endResponse) response.End(); } public static void RedirectToAction(this ActionExecutingContext filterContext, String action, String controller, object routeValues = null, bool endResponse = false) { if (endResponse) filterContext.HttpContext.Response.RedirectToAction(action, controller, routeValues, true); else filterContext.Result = new RedirectToRouteResult(CreateRoute(action, controller, routeValues)); } public static void RedirectToAction(this ExceptionContext filterContext, String action, String controller, object routeValues = null, bool endResponse = false) { if (endResponse) filterContext.HttpContext.Response.RedirectToAction(action, controller, routeValues, true); else { filterContext.ExceptionHandled = true; filterContext.Result = new RedirectToRouteResult(CreateRoute(action, controller, routeValues)); } } // Route Value Derivation public static RouteValueDictionary CreateRoute(String action, String controller, object routeValues = null) { RouteValueDictionary result = routeValues != null ? HtmlHelper.AnonymousObjectToHtmlAttributes(routeValues) : new RouteValueDictionary(); result["controller"] = controller; result["action"] = action; return result; } }

Hay más ControllerContexts que no están incluidos, pero debería ser bastante fácil agregar el suyo según sus necesidades.