Friday, May 22, 2015

Custom ActionFilter in ASP .Net MVC

I had a scenario like if a person doesn't have proper access to a resource he will receive a message on a page.
Initially I thought I should implement custom Authorization Filter [customize the existing Authorization Filter] - but it looked like Authorization filter is implemented [at least in my application] more like if the filter is not met you are redirected to login page - kind of session checking and stuffs like mandatory things for each of the Actions.
But in my case I was putting this check on a single Action - off course having option to reuse the filter later.
Following is the Controller with Filter:

[Authorize]
[PermittedSiteActionAttribute]
public ActionResult Siteinfo(int id = 0, string nodeType = "")
{
RASSiteDetailsModel model = null;
return View(model);
}

The  PermittedSiteActionAttribute lokked like :
public class PermittedSiteActionAttribute : FilterAttribute, IActionFilter
    {
        bool _IsAuthorised = false;
        void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
        {
            try
            {
                if (!_IsAuthorised)
                {
                    filterContext.Controller.ViewData.Model = null;
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Error in PermittedSiteActionAttribute>OnActionExecuted", ex);
            }
        }
        void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
        {
            try
            {
                var actionParams = filterContext.ActionParameters;
                object siteId;
                actionParams.TryGetValue("id", out siteId);
                if (siteId != null && decimal.Parse(siteId.ToString()) > 0)
                {
                    Util util = new Util();
                    _IsAuthorised = util.IsPermittedSite(decimal.Parse(siteId.ToString()));
                }
                if (!_IsAuthorised)
                {
                    filterContext.Controller.ViewBag.AuthorizationMessage = "You are not Authorised to access this resource; Please select a different site.";
                }
            }
            catch(Exception ex)
            {
                Logger.Error("Error in PermittedSiteActionAttribute>OnActionExecuting", ex);
            }
        }
    }
Here OnActionExecuting event I am checking the permission and if fails I am setting the Model to be Null at OnActionExecuted event - so that the user doesn't views the resource returned by the Action. May be not the perfect way of doing this - but a way around, I guess :)

To get started with these Asp .Net Action filters following tutorial is a good one: