2009-05-19 1102 views
6

Tengo un BaseController en el cual pongo algunos datos en la colección ViewData anulando OnActionExecuting.Llamando a OnActionExecuting de FilterAttribute antes de OnController's OnActionExecuting

Ahora tengo una Acción en un ChildController que no necesita esa información.

Para ese propósito creé un DontPopulateViewData ActionFilterAttribute que establece un bool en el BaseController que impide que BaseController llene los viewdata.

Problema: el método ActionFilters OnActionExecuting se llama después del que está en BaseController y no antes.

¿Los ActionFilters se llamarán siempre antes de que se anulen OnActionExecuting en los controladores base y existe alguna forma de evitar esto?

Respuesta

15

Además de lo que Marwan Aouida publicó y sugirió (utilizando un ActionFilter en la clase base), no creo que pueda crear un ActionFilter que se ejecute antes de la sobrecarga OnActionExecuting() en la base clase. El siguiente código:

[MyActionFilter(Name = "Base", Order = 2)] 
public class MyBaseController : Controller 
{ 
    protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     Response.Write("MyBaseController::OnActionExecuting()<br>"); 
     base.OnActionExecuting(filterContext); 
    } 

    protected override void Execute(System.Web.Routing.RequestContext requestContext) 
    { 
     requestContext.HttpContext.Response.Write("MyBaseController::Execute()<br>"); 
     base.Execute(requestContext); 
    } 

    protected override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     Response.Write("MyBaseController::OnActionExecuted()<br>"); 
     base.OnActionExecuted(filterContext); 
    } 
} 

public class MyActionFilter : ActionFilterAttribute 
{ 
    public string Name; 

    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     filterContext.HttpContext.Response.Write("MyActionFilter_" + Name + "::OnActionExecuted()<br>"); 
     base.OnActionExecuted(filterContext); 
    } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     filterContext.HttpContext.Response.Write("MyActionFilter_" + Name + "::OnActionExecuting()<br>"); 
     base.OnActionExecuting(filterContext); 
    } 
} 

public class MyTestController : MyBaseController 
{ 
    [MyActionFilter(Name = "Derived", Order = 1)] 
    public void Index() 
    { 
     Response.Write("MyTestController::Index()<br>"); 
    } 
} 

produce esta salida:

MyBaseController::Execute() 
MyBaseController::OnActionExecuting() 
MyActionFilter_Derived::OnActionExecuting() 
MyActionFilter_Base::OnActionExecuting() 
MyTestController::Index() 
MyActionFilter_Base::OnActionExecuted() 
MyActionFilter_Derived::OnActionExecuted() 
MyBaseController::OnActionExecuted() 
+0

Gracias. Y sí, poner la lógica en un ActionFilter en la clase base resolverá el problema e incluso dará como resultado un diseño más limpio. –

0

La clase ActionFilterAttribute tiene una propiedad llamada "Orden" que puede usar para establecer el orden en que se ejecutan los filtros de acción.
En su caso, usted tiene que fijar el orden del filtro de atributos en el BaseController a 2 y el atributo de filtro en el DerivedController a 1:

[MyFilter(Order=2)] 
public class BaseController:Controller 
{ 

    public ActionResult MyAction() { 

    } 

} 

[MySecondFilter(Order=1)] 
public class DerivedController:BaseController 
{ 

    public ActionResult AnotherAction() { 

    } 

} 

leer esto para más infos: http://msdn.microsoft.com/en-us/library/dd381609.aspx

Nota: No probé esto.

Cuestiones relacionadas