有没有办法在控制器级别添加属性,而不是在特定操作上添加属性。例如,如果我的控制器中有 10 个操作,而其中只有 1 个操作不需要我创建的特定属性。
[我的属性] 公共类 MyController :控制器 { 公共 ActionResult Action1() {} 公共 ActionResult Action2() {} [删除_我的属性] 公共 ActionResult Action3() {} }
我可能会将此操作移至另一个控制器(但不喜欢那样),或者我可以将 MyAttribute 应用于除 Action3 之外的所有操作,但只是想是否有更简单的方法?
我知道我的答案有点晚了(几乎四年了),但我遇到了这个问题,并想分享我设计的一个解决方案,它允许我做几乎最初的问题想做的事情,以防万一将来可以帮助其他人。
该解决方案涉及一个名为
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
}
(我听说你喜欢属性,所以我在属性上添加了一些属性!这确实是让魔法在最顶层发挥作用的原因:允许它们继承/级联,但只允许其中一个执行。)
现在的使用方法如下:
[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]
)。
Johannes 给出了正确的解决方案,这是我的编码方式......希望它对其他人有帮助。
[我的过滤器(“我的操作”)] 公共类 HomeController :控制器 { 公共操作结果操作1... 公共 ActionResult Action2... 公共 ActionResult 我的操作... } 公共类压缩过滤器:ActionFilterAttribute { 私有 IList _ExcludeActions = null; 公共压缩过滤器() { _ExcludeActions = 新列表(); } 公共压缩过滤器(字符串排除动作) { _ExcludeActions = new List(excludeActions.Split(',')); } 公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext) { HttpRequestBase 请求 = filterContext.HttpContext.Request; 字符串 currentActionName = (string)filterContext.RouteData.Values["action"]; if (_ExcludeActions.Contains(currentActionName)) 返回; ... }
您可以通过将特定操作传递给主属性来排除它:
[MyAttribute(Exclude="Action3")]
编辑
我的例子是从头开始的(你可以看到下面是VB.NET,也许这就是它出错的地方),这就是我的实现方式:
<Models.MyAttribute(Exclude:="Action3")> _
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