2009-05-19 5 views
6

У меня есть BaseController, в который я ввел некоторые данные из коллекции ViewData, переопределив OnActionExecuting.Вызов фильтра OnAction FilterAttribute перед выполнением OnAction BaseController

Теперь у меня есть действие в ChildController, которому не нужны эти данные просмотра.

Для этого я создал DontPopulateViewData ActionFilterAttribute, который устанавливает bool на BaseController, который предотвращает заполнение отображаемых данных .

Проблема: метод ActionFilters OnActionExecuting вызывается после одного в BaseController и не раньше.

Будет ли ActionFilters всегда вызываться до переопределения OnActionExecuting в базовых контроллерах и есть ли способ обойти это?

ответ

15

В дополнение к тому, что Marwan Aouida отправил и предложил (используя ActionFilter в базовом классе), я не думаю, что вы сможете создать ActionFilter, который выполняется до перегрузки OnActionExecuting() на базе класс. Следующий код:

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

производит этот выход:

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

Спасибо. И да, включение логики в ActionFilter в baseclass решит проблему и даже приведет к более чистым дизайнам. –

0

Класс ActionFilterAttribute имеет свойство «Заказ», которое вы можете использовать для установки порядка выполнения Action Filters.
В вашем случае вы должны установить порядок фильтр атрибута в BaseController до 2 и фильтра атрибута в DerivedController 1:

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

    public ActionResult MyAction() { 

    } 

} 

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

    public ActionResult AnotherAction() { 

    } 

} 

Читать это для более подробной информации: http://msdn.microsoft.com/en-us/library/dd381609.aspx

Примечания: Я не проверял это.