如何为所有控制器编写动作过滤器

时间:2014-09-25 07:44:30

标签: asp.net-mvc controller attributes action-filter

以下是示例操作过滤器。我们知道当我们编写一个动作过滤器时,我们需要用这样的属性来装饰控制器,以便将它用于任何控制器。

我想知道是否有任何方法可以编写一个动作过滤器,它可以用于所有控制器,我不需要使用动作过滤器属性来装饰所有控制器。有什么想法吗?

[LogActionFilter]
public class HomeController : Controller
{}

public class LogActionFilter : ActionFilterAttribute

     {
          public override void OnActionExecuting(ActionExecutingContext filterContext)
          {
               Log("OnActionExecuting", filterContext.RouteData);       
          }

          public override void OnActionExecuted(ActionExecutedContext filterContext)
          {
               Log("OnActionExecuted", filterContext.RouteData);       
          }

          private void Log(string methodName, RouteData routeData)
          {
               var controllerName = routeData.Values["controller"];
               var actionName = routeData.Values["action"];
               var message = String.Format("{0} controller:{1} action:{2}", methodName, controllerName, actionName);
               Debug.WriteLine(message, "Action Filter Log");
          }

     }

3 个答案:

答案 0 :(得分:11)

public class LogActionFilterAttribute : IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            Log("OnActionExecuted", filterContext.RouteData);    
        }

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            Log("OnActionExecuting", filterContext.RouteData);  
        }

        private void Log(string methodName, RouteData routeData)
        {
            var controllerName = routeData.Values["controller"];
            var actionName = routeData.Values["action"];
            var message = String.Format("{0} controller:{1} action:{2}", methodName, controllerName, actionName);
            Debug.WriteLine(message, "Action Filter Log");
        }
    }

public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalFilters.Filters.Add(new LogActionFilterAttribute());
        }
    }

答案 1 :(得分:3)

对于您的方案,您只需创建自定义BaseController 并将您的[LogActionFilter]属性放在自定义Basecontroller 上,并从自定义Basecontroller继承所有控制器,如下所示:

[LogActionFilter]
public class MyBaseController : Controller
{

}

public class MyOtherController : MyBaseController //<----instead of using Controller as base use MyBaseController as base class
{
    public ActionResult Index()
    {
        // ...
    }
}

此方法的优点是您必须将自定义[LogActionFilter]属性仅放在一个位置,即仅在自定义BaseController上。

答案 2 :(得分:1)

如果您已经从基本控制器继承子类,则不需要过滤器属性或注册任何内容。您可以覆盖所需的方法,例如,

public class BaseController : Controller {
   protected override void OnActionExecuting(ActionExecutingContext filterContext) {
      ViewBag.SomeValue = "glorp frob blizz nunk";
      // Access the controller, parameters, querystring, etc. from the filterContext
      base.OnActionExecuting(filterContext);
   }
}

然后,从其子类化的每个控制器都将运行该方法:

public sealed class GlorpController : BaseController {
   public ActionResult Index() => View();
}

视图很高兴看到ViewBag.SomeValue值。