控制器和动作的MVC属性

有没有办法在Controller级别添加属性,但不能在特定操作上添加。 例如,如果我在我的控制器中有10个动作,那些动作中只有一个不需要我创建的特定属性。

 [MyAttribute]
 public class MyController:Controller
 {
     public ActionResult Action1(){}
     public ActionResult Action2(){}

     [Remove_MyAttribute]
     public ActionResult Action3(){}
 }

我可能会将此Action移动到另一个控制器(但不喜欢)或者我可以将MyAttribute应用于除Action3之外的所有操作,但只是想想是否有更简单的方法?

我知道我的答案有点晚了(差不多四年),但是我遇到了这个问题并希望分享一个我设计的解决方案,它允许我做几乎原来问题想要做的事情,以防它有帮助未来的任何人。

该解决方案涉及一个名为AttributeUsage的小gem,它允许我们在控制器(甚至任何基本控制器!)上指定属性,然后根据需要覆盖(忽略/删除)各个动作或子控制器。 它们将“级联”到只有最细粒度的属性实际触发的位置:即,它们从最不具体的(基本控制器),到更具体的(派生控制器),到最具体的(动作方法)。

这是如何做:

 [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method, Inherited=true, AllowMultiple=false)] public class MyCustomFilterAttribute : ActionFilterAttribute { private MyCustomFilterMode _Mode = MyCustomFilterMode.Respect; // this is the default, so don't always have to specify public MyCustomFilterAttribute() { } public MyCustomFilterAttribute(MyCustomFilterMode mode) { _Mode = mode; } public override void OnActionExecuting(ActionExecutingContext filterContext) { if (_Mode == MyCustomFilterMode.Ignore) { return; } // Otherwise, respect the attribute and work your magic here! // // // } } public enum MyCustomFilterMode { Ignore = 0, Respect = 1 } 

(我听说你喜欢属性,所以我在属性上添加了一些属性!这就是让魔术在最顶层工作的原因:允许它们inheritance/级联,但只允许其中一个执行。)

以下是它现在的使用方法:

 [MyCustomFilter] public class MyBaseController : Controller { // I am the application's base controller with the filter, // so any derived controllers will ALSO get the filter (unless they override/Ignore) } public class HomeController : MyBaseController { // Since I derive from MyBaseController, // all of my action methods will also get the filter, // unless they specify otherwise! public ActionResult FilteredAction1... public ActionResult FilteredAction2... [MyCustomFilter(Ignore)] public ActionResult MyIgnoredAction... // I am ignoring the filter! } [MyCustomFilter(Ignore)] public class SomeSpecialCaseController : MyBaseController { // Even though I also derive from MyBaseController, I can choose // to "opt out" and indicate for everything to be ignored public ActionResult IgnoredAction1... public ActionResult IgnoredAction2... // Whoops! I guess I do need the filter on just one little method here: [MyCustomFilter] public ActionResult FilteredAction1... } 

我希望这可以编译,我从一些类似的代码中抽出它并对它进行了一些搜索和替换,因此它可能不完美。

您必须覆盖/扩展默认属性并添加自定义构造函数以允许排除。 或者,您可以创建自定义属性以进行排除(在您的示例中为[Remove_MyAttribute])。

约翰内斯给出了正确的解决方案,这就是我编码的方式……希望它能帮助其他人。

 [MyFilter( “MyAction”)]
公共类HomeController:控制器
 {
    公共ActionResult Action1 ......
    公共ActionResult Action2 ......
    公共ActionResult MyAction ......
 }

公共类CompressFilter:ActionFilterAttribute
 {
     private IList _ExcludeActions = null;

     public CompressFilter()
     {
         _ExcludeActions = new List();
     }

     public CompressFilter(string excludeActions)
     {
         _ExcludeActions = new List(excludeActions.Split(','));
     }

     public override void OnActionExecuting(ActionExecutingContext filterContext)
     {
         HttpRequestBase request = filterContext.HttpContext.Request;

         string currentActionName =(string)filterContext.RouteData.Values [“action”];

         if(_ExcludeActions.Contains(currentActionName))
            返回;

         ...
     }

您可以通过将特定操作传递给main属性来排除它:

  [MyAttribute(Exclude="Action3")] 

编辑

我的例子来自头部(你可以看到以下是VB.NET,也许就是它出错的地方),这就是我实现的方式:

  _ Public Class MyController Inherits System.Web.Mvc.Controller End Class 

您尝试执行的操作的常用模式是使用布尔参数和属性来指示是否应用了属性。

例如:

 [ComVisible] which is equivalent with [ComVisible(true)] or [ComVisible(false)] 

在你的情况下你会有:

 [MyAttribute] // defaults to true and [MyAttribute(false)] for applying the attribute on excluded members