控制器和动作的MVC属性

时间:2009-05-13 10:14:17

标签: c# asp.net-mvc

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

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

    [Remove_MyAttribute]
    public ActionResult Action3() {}
}

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

5 个答案:

答案 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