2011-03-27 28 views
106

¿Cuál es la mejor manera de hacer una redirección en un ActionFilterAttribute. Tengo un ActionFilterAttribute llamado IsAuthenticatedAttributeFilter y que comprobó 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 redirección en este punto estaría bien.Redirect From Action Filter Attribute

+2

** [Marque esta respuesta. Espero que esto te ayude.] (Http://stackoverflow.com/a/18126733/2015869) ** –

Respuesta

152

Conjunto filterContext.Result

Con el nombre de la ruta:

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

También puede hacer algo como:

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

Si desea utilizar RedirectToAction:

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

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

A continuación, el filtro se vería algo como:

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

Esto funciona, pero ¿no debería haber un método RedirectToAction disponible? –

+0

@BenMills, sin embargo, está 'protegido' por lo que no tendría acceso al filtro. – James

+7

Mi pregunta ahora es ¿por qué Microsoft decidió hacer este filtro 'protegido' debe haber alguna explicación razonable? Me siento muy mal redefiniendo esta accesibilidad de 'RedirectToAction' sin entender por qué fue encapsulado en primer lugar. –

9

Suena como si desea volver a poner en práctica, o posiblemente extender, AuthorizeAttribute. Si es 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 hacer el 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 question con un answer con más detalles aquí en la SO.

4

Prueba el siguiente fragmento, que debe 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); 
    } 
} 
+0

Esto funcionó para mí, tuve que verificar los valores de cadena de consulta si cualquier usuario intenta cambiar los valores de cadena de consulta e intenta acceder a datos que no están autorizados para él/ella de lo que los estoy redirigiendo a página de mensajes no autorizados, usando ActionFilterAttribute. – Sameer

+0

Esto funciona perfectamente. ¡Gracias! –

1

que podría heredar su controlador y luego usarlo dentro de su 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 su controlador base:

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

Contras.de esto es cambiar todos los controladores de heredar de la clase "myController"

56

Como alternativa a una redirección, si está llamando a su propio código, se 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 puro, sino da un resultado similar sin gastos generales innecesarios.

+0

Tu ME ayudaste. ¡Gracias! –

+0

Esta es LA respuesta correcta. –

+12

Tenga en cuenta que no debe llamar 'actionContext.Result.ExecuteResult' desde su filtro de acción - MVC lo hará automáticamente después de que se ejecute el filtro de acción (siempre que' actionContext.Result' no sea nulo). – NightOwl888

10

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

Extender AuthorizeAttribute dicen CutomAuthorizer anulación del OnAuthorization y HandleUnauthorizedRequest

Registrar el CustomAuthorizer en el RegisterGlobalFilters.

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 

    filters.Add(new CustomAuthorizer()); 
} 

sobre la identificación de la llamada unAuthorized acceso HandleUnauthorizedRequest y redirigir a la acción del controlador en cuestión 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" } 

             }); 

    } 
}