Click here to Skip to main content
15,860,861 members
Articles / Web Development / ASP.NET

A Simple Action Filter Overview for Authorization and Exception Handling in ASP.NET MVC

Rate me:
Please Sign up or sign in to vote.
4.70/5 (25 votes)
10 Dec 2013CPOL4 min read 119.6K   41   4
A simple action filter overview for authorization and exception handling in ASP.NET MVC.

Contents

  1. Introduction
  2. Types of filtering in ASP.NET MVC
  3. Simple understanding of Action Filter
  4. Using the code [Type of Action Filter, Authorization with Filter, Exception Handling]
  5. Conclusion

Introduction

Earlier, we used traditional try..catch block or globally catch exception in ASP.NET. Also ASP.NET has several traditional ways to handle authorization like session storage of user information and others. But in ASP.NET MVC has a much more smarter way to handle authorization and exception handling capability using filtering while requesting to Action through controller. I am going to describe a practical implementation for ASP.NET MVC application to implement authorization and exception. Eventually, I also discussed with the fundamental of filtering of ASP.NET MVC.

Types of Filters in ASP.NET MVC

ASP.NET has a great feature: request filter to action. All filters work when an action invoker starts to the end of the execution process, that means before sending processed data to the client. There are four types of action filters:

  • Authorization filter: to authorize a request, we can add the filter object in Global.asax. The interface that needs to be implemented for this filter is IAuthorizationFilter.
  • Action filter: IActionFilter will be implemented if we want to use this filter.
  • Result filter: This is a very important filtering for data, incoming and outgoing, because it has two events that are fired before and after the action is invoked. We will have to implement IResultFilter.
  • ExceptionFilter: Implementing the IExceptionFilter attribute, we can catch any exception and process further.

Using the Code

For example, you are developing an ASP.NET MVC application but no security and exception handling mechanism had been implemented yet. So you will have to implement those and the best approach is to filter action against a single controller or globally for all controllers or registering a filter attribute so that all actions have been passed by the filtering process. As we know, ASP.NET MVC's entry point is an action through controller so if we can take any of the above approaches, then the overall application's behavior will be secured, or a global exception handler.

For the controller, all controllers already have four types of the above filter, because it implements IActionFilter, IResultFilter, IAuthorizationFilter, and IExceptionFilter. So, we can override OnAuthorization/ OnExecuting for authorization and OnException for exception handling. But we have to write individually for all controllers of the application.

On the other hand, we can create a BaseController by inheriting the Controller class and override those above events for authorization and exception. Then every controller must inherit BaseController rather than standard MVC controller so that every action comes through the filtering process.

C#
public class BaseController : Controller
{
    protected void SetAuthInfo(Guid Id, string Email, string FullName, string Role)
    {
        AuthUtil.SetAuthInfo(Id, Email, FullName, Role);
    }
    protected override void OnException(ExceptionContext filterContext)
    {
        //write your custom code here
    }
    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        //write your custom code here
    }
}
public class Home:BaseController
{
    public ActionResult Index()
    {
        return View();
    }  
}    

Another approach is to write a class and register it to global.asax. Add a class for authorization and register globally:

C#
public class LogOnAuthoRization: AuthorizeAttribute
{     
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        var isAuthorised = base.IsAuthorized(actionContext);

        if (isAuthorised)
        {
            var cookie = HttpContext.Current.Request.Cookies
            [FormsAuthentication.FormsCookieName];
            var ticket = FormsAuthentication.Decrypt(cookie.Value);
            var identity = new GenericIdentity(ticket.Name);
            string userData = ticket.UserData;
            if (userData.Contains("_"))
            {
                string[] data = userData.Split('_');
                if (data != null && data.Length > 3)
                {
                    string Email = data[0];
                    string Id = data[1];
                    string FullName = data[2];
                    string Role = data[3];
                    var principal = new CustomUserPrincipal
                    (identity, new Guid(Id), Email, Role, FullName);
                    HttpContext.Current.User = principal;
                    Thread.CurrentPrincipal = principal;
                }
            }
        }
    }
} 

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new CPExceptionHandler());
        filters.Add(new LogonAuthorizeAttribute());            
    }

    internal static void RegisterHttpFilters(System.Web.Http.Filters.HttpFilterCollection filters)
    {
        filters.Add(new APIAuthorizeAttribute());       
    }
} 

Registering global.asax in the Application_Start method.

C#
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

For exception handling, you have to follow the above approach. But for exception, you need to write a class by inheriting HandleErrorAttribute (if you want to register globally not BaseController or individual controller approach). Later, you have to register by calling the FilterConfig.RegisterGlobalFilters in Application_Start method. The class for Exception handling will look like:

C#
public class CPExceptionHandler : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        //redirect to error page and do your necessary task here
    }
} 

You have seen in a earlier code block I register "CPExceptionHandler" this class for global filter.

Sometimes we need to execute a specific task depends on action's behavior. For example, if a owner of a web site wants to know immediately when a user visits a specific view. Then the owner expects to get a mail from the application automatically. For this type of scenario, we can use Action Filter. After execution an action, the application will generate a mail and sent to the owner automatically.

C#
public class MyActivityFilter : ActionFilterAttribute{
  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
  }
   public override void OnActionExecuted(ActionExecutedContext filterContext)
   {
    Task.Factory.StartNew(() => Email(filterContext));
   }
  public override void OnResultExecuting(ResultExecutingContext filterContext)
   {
   }
  public override void OnResultExecuted(ResultExecutedContext filterContext)
  {
  }
}

In the above code, the MyActivityFilter class inherits ActionFilterAttribute. The ActionFilterAttribute class implements the IActionFilter interface.

Conclusion

By using the above, a different approach need not be followed at a time. I suggest writing your own filtering class and registering it globally. One thing I did not mention here is "How to do exception and authorization handling for WebAPI and AJAX". The next part of this article will be on this topic. But if your requirement is like the above scenario, then you can follow it anyway. There is nothing like a smart way to handle authorization and exception handling.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
QuestionAction Filter Pin
Member 1102927822-Aug-14 0:14
Member 1102927822-Aug-14 0:14 
QuestionMy Vote of 5 Pin
Rubol10-Dec-13 16:51
professionalRubol10-Dec-13 16:51 
QuestionArticle grammar and written text Pin
csugden12-Sep-13 9:57
professionalcsugden12-Sep-13 9:57 
GeneralMy vote of 2 Pin
dllundin10-Sep-13 9:48
dllundin10-Sep-13 9:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.