3

During testing (at least) we're logging some low-level information for each controller/action. All controllers are derived from our custom BaseController which overrides OnActionExecuting to do the logging.

We have a property in the BaseController that determines whether or not this logging will occur, so that a controller can override OnActionExecuting itself, reset the flag, and then call "base.OnActionExecuting". The flag is normally true, but we'd want to turn it off for some Json requests, for example.

What we'd prefer to do is create a custom controller/action filter to handle that, something like this:

[LogPageAccess(false)]
[HttpGet]
Public ActionResult Foobar()

I'm sure there's a way to do it, but I haven't been able to figure out how to create the custom attribute and have it reset the flag in the BaseController.

Thanks...

Kras
  • 623
  • 2
  • 9
  • 13

2 Answers2

2

in my project I use the following to verify access controllers:

    [Capability(UserCapability.FileManagement)]
    public ActionResult FileList(FileListRequestModel request, bool ajax = false)
    {
        //code
    }

Here is my Capability Class

/// <summary>
/// Decorator to MVC class and method to evaluate if a certain capability is enabled
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CapabilityAttribute : AuthorizeAttribute
{
    #region Class Attributes

    private object _capability = null;

    #endregion

    #region Public Methods

    /// <summary>
    /// Create a new capability attribute
    /// </summary>
    /// <param name="capability">Context Value passed to the validator</param>
    public CapabilityAttribute(object capability)
    {
        this._capability = capability;
    }

    /// <summary>
    /// Check if attribute is enabled
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (!Capability.Enabled(this._capability))
        {
            throw new UnauthorizedAccessException();
        }
        else
        {
            base.OnAuthorization(filterContext);
        }
    }

    #endregion
}

You just need to adapt this code for your case, I hope it become useful

João Louros
  • 2,752
  • 4
  • 23
  • 30
  • Had need for something similar, and this got me where I needed to go. Instead of throwing an `UnauthorizedAccessException` however, I used `filterContext.Result = new HttpUnauthorizedResult();` which I feel fit better into the MVC page. You can review [the MSDN documentation for `UnauthorizedAccessException`](http://msdn.microsoft.com/en-us/library/system.unauthorizedaccessexception.aspx) to understand why I didn't feel it a fit in this case. – Mike Guthrie Apr 25 '14 at 16:45
0

I tried to build out a simple example of your situation for a while, but then realized that I couldn't pass instance data to an Attribute-- so say if I set a Log flag to false, I couldn't use that to directly manipulate the base controller's property.

Check out this SO post.

Here was the code I was playing around with (does not compile -- can't pass this):

public class BaseController : Controller
{
    public bool LogPageRequests { get; set; }
}

public class LogPageAccess : ActionFilterAttribute
{
    public LogPageAccess(BaseController baseController, bool log = true)
    {
        baseController.LogPageRequests = log;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //Do Whatever
        base.OnActionExecuting(filterContext);
    }
}

public class SomeController : BaseController
{
    [LogPageAccess(this, false)]
    public ActionResult Index()
    {
        return View();
    }
}

Maybe you can do something with reflection, but it might be the case that you'll have to do it the way you've been doing it since it just doesn't seem possible to get instance data to the attribute.

Community
  • 1
  • 1
davecoulter
  • 1,806
  • 13
  • 15
  • You can get the controller from the context. – SLaks Sep 22 '11 at 15:05
  • @SLaks Could you give me a quick and dirty example? – davecoulter Sep 22 '11 at 23:48
  • I tried `filterContext.Controller` but that doesn't provide access to it's property (`LogPageRequests` in my original example). What I ended up doing is creating an `AuthorizeAttribute` and then setting a flag in `TempData` that I check in `OnActionExecuting` in BaseController. Decidedly hokey, but it does seem to work. – Kras Sep 23 '11 at 15:51