2009-05-19 13 views
6

Mam BaseController w których mogę umieścić w niektórych danych w kolekcji ViewData nadrzędnymi OnActionExecuting.Wywołanie OnActionExecuting FilterAttribute przed BaseController za OnActionExecuting

Teraz mam akcję w ChildController, która nie potrzebuje tych danych widoku.

W tym celu utworzyłem DontPopulateViewData ActionFilterAttribute, który ustawia wartość parametru bool na BaseController, która zapobiega zapełnianiu danych widoku przez BaseController.

Problem: metoda ActionFilters OnActionExecuting jest wywoływana po tej w BaseController, a nie wcześniej.

Czy ActionFilters będzie zawsze wywoływane przed zastąpieniem OnActionExecuting w kontrolerach bazowych i czy istnieje sposób na obejście tego?

Odpowiedz

15

Oprócz tego, co napisał i zasugerował Marwan Aouida (używając ActionFilter w klasie bazowej), nie sądzę, że będziesz w stanie stworzyć ActionFilter, który będzie wykonywany przed przeciążeniem OnActionExecuting() w bazie klasa. Poniższy kod:

[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>"); 
    } 
} 

produkuje ten wyjściowe:

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

Dzięki. I tak, umieszczenie logiki w ActionFilter na baseclass rozwiąże problem, a nawet doprowadzi do czystszego projektu. –

0

Klasa ActionFilterAttribute ma właściwość o nazwie "Zamówienie", za pomocą której można ustawić kolejność wykonywania filtrów działania.
W twoim przypadku trzeba ustawić kolejność atrybutów filtr w BaseController do 2 i atrybut filtr w DerivedController 1:

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

    public ActionResult MyAction() { 

    } 

} 

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

    public ActionResult AnotherAction() { 

    } 

} 

Przeczytaj to wiecej informacje o: http://msdn.microsoft.com/en-us/library/dd381609.aspx

Uwaga: Nie testowałem tego.

Powiązane problemy