Redirigir desde el atributo de filtro de acción

¿Cuál es la mejor manera de hacer una redirección en un ActionFilterAttribute ? Tengo un ActionFilterAttribute llamado IsAuthenticatedAttributeFilter que verifica el valor de una variable de sesión. Si la variable es falsa, quiero que la aplicación redirija a la página de inicio de sesión. Preferiría redirigir usando el nombre de ruta SystemLogin sin embargo, cualquier método de redireccionamiento en este punto estaría bien.

Establecer filterContext.Result

Con el nombre de la ruta:

 filterContext.Result = new RedirectToRouteResult("SystemLogin", routeValues); 

También puedes hacer algo como:

 filterContext.Result = new ViewResult { ViewName = SharedViews.SessionLost, ViewData = filterContext.Controller.ViewData }; 

Si quieres usar RedirectToAction :

Puede hacer un método público RedirectToAction en su controlador ( preferiblemente en su controlador base ) que simplemente llame al RedirectToAction protegido desde System.Web.Mvc.Controller . Agregar este método permite una llamada pública a su RedirectToAction desde el filtro.

 public new RedirectToRouteResult RedirectToAction(string action, string controller) { return base.RedirectToAction(action, controller); } 

Entonces su filtro se vería algo así como:

 public override void OnActionExecuting(ActionExecutingContext filterContext) { var controller = (SomeControllerBase) filterContext.Controller; filterContext.Result = controller.RedirectToAction("index", "home"); } 

Alternativamente a una redirección, si está llamando a su propio código, puede usar esto:

 actionContext.Result = new RedirectToRouteResult( new RouteValueDictionary(new { controller = "Home", action = "Error" }) ); actionContext.Result.ExecuteResult(actionContext.Controller.ControllerContext); 

No es una redirección pura, sino que da un resultado similar sin sobrecarga innecesaria.

Estoy usando MVC4, utilicé el siguiente enfoque para redirigir una pantalla html personalizada al incumplimiento de la autorización.

Extienda AuthorizeAttribute CutomAuthorizer que CutomAuthorizer prevalece sobre OnAuthorization y HandleUnauthorizedRequest

Registre CustomAuthorizer en RegisterGlobalFilters .

 public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new CustomAuthorizer()); } 

al identificar el acceso no unAuthorized llame a HandleUnauthorizedRequest y redirija a la acción del controlador correspondiente como se muestra a continuación.


 public class CustomAuthorizer : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { bool isAuthorized = IsAuthorized(filterContext); // check authorization base.OnAuthorization(filterContext); if (!isAuthorized && !filterContext.ActionDescriptor.ActionName.Equals("Unauthorized", StringComparison.InvariantCultureIgnoreCase) && !filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.Equals("LogOn", StringComparison.InvariantCultureIgnoreCase)) { HandleUnauthorizedRequest(filterContext); } } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { filterContext.Result = new RedirectToRouteResult( new RouteValueDictionary{{ "controller", "LogOn" }, { "action", "Unauthorized" } }); } } 

Parece que desea volver a implementar, o posiblemente ampliar, AuthorizeAttribute . De ser así, debe asegurarse de heredar eso, y no ActionFilterAttribute , para permitir que ASP.NET MVC haga más por usted.

Además, debe asegurarse de autorizar antes de realizar cualquier trabajo real en el método de acción; de lo contrario, la única diferencia entre iniciar sesión y no será qué página verá cuando finalice el trabajo.

 public class CustomAuthorizeAttribute : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { // Do whatever checking you need here // If you want the base check as well (against users/roles) call base.OnAuthorization(filterContext); } } 

Hay una buena pregunta con una respuesta con más detalles aquí en SO.

Pruebe el siguiente fragmento, debería ser bastante claro:

 public class AuthorizeActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(FilterExecutingContext filterContext) { HttpSessionStateBase session = filterContext.HttpContext.Session; Controller controller = filterContext.Controller as Controller; if (controller != null) { if (session["Login"] == null) { filterContext.Cancel = true; controller.HttpContext.Response.Redirect("./Login"); } } base.OnActionExecuting(filterContext); } } 

podrías heredar tu controlador y luego usarlo dentro de tu filtro de acción

dentro de su clase ActionFilterAttribute:

  if( filterContext.Controller is MyController ) if(filterContext.HttpContext.Session["login"] == null) (filterContext.Controller as MyController).RedirectToAction("Login"); 

dentro de tu controlador base:

 public class MyController : Controller { public void RedirectToAction(string actionName) { base.RedirectToAction(actionName); } } 

Contras. de esto es cambiar todos los controladores para heredar de la clase “MyController”

Aquí hay una solución que también tiene en cuenta si está utilizando solicitudes Ajax.

 using System; using System.Web.Mvc; using System.Web.Routing; namespace YourNamespace{ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class AuthorizeCustom : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { if (YourAuthorizationCheckGoesHere) { string area = "";// leave empty if not using area's string controller = "ControllerName"; string action = "ActionName"; var urlHelper = new UrlHelper(context.RequestContext); if (context.HttpContext.Request.IsAjaxRequest()){ // Check if Ajax if(area == string.Empty) context.HttpContext.Response.Write($""); else context.HttpContext.Response.Write($""); } else // Non Ajax Request context.Result = new RedirectToRouteResult(new RouteValueDictionary( new{ area, controller, action })); } base.OnActionExecuting(context); } } }