有没有办法在Controller级别添加属性,但不能在特定操作上添加。例如,假设我的控制器中有10个操作,其中只有一个操作不需要我创建的特定属性。
[MyAttribute] public class MyController : Controller { public ActionResult Action1() {} public ActionResult Action2() {} [Remove_MyAttribute] public ActionResult Action3() {} }
我可能会将此Action移动到另一个控制器(但不喜欢)或者我可以将MyAttribute应用于除Action3之外的所有操作,但只是想想是否有更简单的方法?
答案 0 :(得分:5)
我知道我的答案有点晚了(差不多四年),但是我遇到了这个问题并希望分享一个我设计的解决方案,这个解决方案让我能够完成原始问题想做的事情,如果它将来帮助其他任何人。
该解决方案涉及一个名为AttributeUsage
的小宝石,它允许我们在控制器(甚至任何基本控制器!)上指定属性,然后在各个动作或子控制器上覆盖(忽略/删除)需要。它们将“级联”到只有最细粒度的属性实际触发的位置:即,它们从最不具体(基本控制器)到更具体(派生控制器),到最具体(动作方法)。
以下是:
[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
}
(我听说你喜欢属性,所以我在属性上添加了一些属性!这就是让魔术在最顶层工作的原因:允许它们继承/级联,但只允许其中一个执行。)< / p>
以下是现在的使用方法:
[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...
}
我希望这可以编译,我从一些类似的代码中抽出它并对它进行了一些搜索和替换,因此它可能不完美。
答案 1 :(得分:3)
您必须覆盖/扩展默认属性并添加自定义构造函数以允许排除。或者,您可以创建自定义属性以进行排除(在您的示例中为[Remove_MyAttribute])。
答案 2 :(得分:3)
Johannes给出了正确的解决方案,这就是我编码的方式......希望它能帮助其他人。
[MyFilter("MyAction")] public class HomeController : Controller { public ActionResult Action1... public ActionResult Action2... public ActionResult MyAction... } public class 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)) return; ... }
答案 3 :(得分:2)
您可以通过将特定操作传递给主要属性来排除该操作:
[MyAttribute(Exclude="Action3")]
修改强>
我的例子来自头部(你可以看到以下是VB.NET,也许就是它出错的地方),这就是我实现的方式:
<Models.MyAttribute(Exclude:="Action3")> _
Public Class MyController
Inherits System.Web.Mvc.Controller
End Class
答案 4 :(得分:2)
您尝试做的通常模式是使用布尔参数和属性来指示属性是否应用。
例如:
[ComVisible] which is equivalent with [ComVisible(true)]
or
[ComVisible(false)]
在你的情况下你会有:
[MyAttribute] // defaults to true
and
[MyAttribute(false)] for applying the attribute on excluded members