tags:

views:

31

answers:

1

I have a BaseController which has an attribute on it rather than individual actions therefore all controllers run through it. I have one action on a controller that I do not want the attribute code to run on. How can I implement this?

[MyAttribute]
public class BaseController : Controller
{

}

public class WebPageController : BaseController
    {
       //How to override attribute executing here?
       public ActionResult Index()
        {
            //do stuff
        }

    }

public class PagePermissionAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
       //Do stuff
    }
}
+4  A: 

I completely misunderstood the question so I've removed my previous answer which was geared toward action inheritance.

In order to make a filter be omitted on an action in a derived controller, I think I would handle it differently. One idea would be to have your filter -- if you're using a built-in filter, you'd need to derive a custom filter from it -- use reflection to check for the presence of another attribute before it runs. In the case where the attribute is available, it simply doesn't execute.

public class SkipAuthorizeAttribute : Attribute
{
    public string RouteParameters { get; set; }
}

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
   public override void OnAuthorization( AuthorizationContext filterContext )
   {
       var action = filterContext.RouteData["action"];
       var methods = filterContext.Controller
                                  .GetType()
                                  .GetMethods()
                                  .Where( m => m.Name == action );
       var skips = methods.GetCustomAttributes(typeof(SkipAuthorizeAttribute),false)
                          .Cast<SkipAuthorizeAttribute>();

       foreach (var skip in skips)
       {
           ..check if the route parameters match those in the route data...
           if match then return
       }

       base.OnAuthorization();
   }
}

Usage:

[CustomAuthorize]
public class BaseController : Controller
{
   ...
}

public class DerivedController : BaseController
{
    // this one does get the base OnAuthorization applied
    public ActionResult MyAction()
    {
       ...
    }

    // this one skips the base OnAuthorization because the parameters match
    [SkipAuthorize(RouteParameters="id,page")]
    public ActionResult MyAction( int id, int page )
    {
        ...
    }
}
tvanfosson
I completely misunderstood your question. I've updated with a solution that addresses the real question. Much more complicated, though.
tvanfosson