tags:

views:

541

answers:

4

Is there a way to add an Attribute on the Controller level but not on a specific action. For example say if i had 10 Actions in my Controller and just 1 of those Actions does not require a specific attribute I created.

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

    [Remove_MyAttribute]
    public ActionResult Action3

I could potentially move this Action into another controller (but dont like that) or I could apply the MyAttribute to all actions except from Action3 but just thought if there is an easier way?

A: 

You could exclude a specific action by passing it to the main attribute:

 [MyAttribute(Exclude="Action3")]

EDIT

My example was from the head (as you can see the following is VB.NET, maybe that's where it went wrong), this is how I implemented:

<Models.MyAttribute(Exclude:="Action3")> _
Public Class MyController
Inherits System.Web.Mvc.Controller

End Class
Ropstah
i get a compiler error trying to add the Exclude options. Intellisense only allows for Parameters Order. Could you give more of an example or am i missing something?
David Liddle
see edited post
Ropstah
+2  A: 

You have to override/extend the default attribute and add a custom constructor to allow exclusion. Or you can create your custom attribute for exclusion (in your example is the [Remove_MyAttribute]).

Johannes Setiabudi
thanks for the point in the right direction. ive upvoted your answer then provided the solution in my answer below.
David Liddle
+1  A: 

Johannes gave the correct solution and here is how I coded it... hope it helps other people.

[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;

        ...
    }
David Liddle
Thanks David! Exactly what I had in mind!
Johannes Setiabudi
+1  A: 

The usual pattern for what you are trying to do is to have and attribute with a boolean parameter that indicates if the attribute is applied or not.

Ex:

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

or 

[ComVisible(false)]

inf your case you would have:

[MyAttribute] // defaults to true

and

[MyAttribute(false)] for applying the attribute on excluded members
Pop Catalin
So you define it at the Controller level then effectively override it on the Action itself... i like that idea and is simpler than comparing it to action names. thanks for your solution.
David Liddle
I am using RenderAction from a Helper method which the MyAttribute(false) is defined on however when I debug eventhough it calls the correct constructor the private variable inside my attribute keeps getting reset. Any ideas?
David Liddle