Fun with MVC Action Filters

Today while working in an MVC web application I ran into a scenario where I needed to authorize access based on an internally developed authorization system.

At first I thought about overriding the OnAuthorization() method in the controller which I’ve done in the past, but then I realized that the permissions could be different based on the action which is invoked on the controller. Because of this, something on the controller level may have been too restrictive, so I kept digging and then had a thought. What about a method attribute? The beautiful thing about an attribute is that you can specify the scope of that attribute. In this case, I wanted to be able to specify that the attribute could be used on a controller class or action method. So I found the perfect tool in my developer “tool belt” for this use.

Class attributes are not really anything new in terms of coding, but in the MVC world, they are actually used quite a bit. In this particular case, I have the need to call an in-house authorization system based on the controller or even the action method that is called. While this could be done within each method, it did not seem like a very elegant solution. Therefore I looked for something that was a little more reusable, and landed on the ActionFilterAttribute.

I ended up creating a custom attribute below using the sudo code below…

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomPermAttribute : ActionFilterAttribute
{
  private string _permCategory, _viewName;

  public CustomPermAttribute  (string permCategory, string viewName=”NoAccess”)
  {
    _permCategory = permCategory;
    _viewName = viewName;
  }

  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
    var username = HttpContext.Current.User.Identity.Name;
    if (string.IsNullOrEmpty(username) || !PermissionsWrapper.CheckPermission(
        username,
        _permCategory))
      filterContext.Result = new ViewResult() { ViewName = _viewName };
    else
      base.OnActionExecuting(filterContext);
  }
}

Reading the code, you can see that this attribute can be used at both the class level and the method level. Therefore it will allow for the flexibility that I need to restrict the usage. Additionally, you will see that if access is not allowed, then we return a view result using our generic “NoAccess” view. And if so needed, we can supply a different view name as well by passing it though the attribute.

Below is an example of a controller now using our custom attribute…

public class HomeController : Controller
{
  //
  // GET: /Home/
  [CustomPerm("ViewItem")]
  public ActionResult Index()
  {
    var viewData = GetItemList();
    return View(viewData);
  }   

  [HttpPost]
  [CustomPerm("EditItem")]
  public ActionResult Index(ItemViewModel viewModel)
  {
    if (ModelState.IsValid(viewModel))
    {
      return RedirectToAction("Index");
    }
    return View(viewModel);
  }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s