Learn About Action Filters In ASP.NET MVC

This article will help you to understand filters in Asp.Net MVC and why we should use them.

This article will help you understand what filters are in ASP.NET MVC and why we should use them. Before moving to the actual definition of filters, don’t be confused by the name, it is not going to filter your data from some list of data.

Basically, filters in ASP.NET MVC are pre-processing and post-processing custom business logic which helps us to add or manipulate our data just before an action is being executed and just after an action has executed. Pre-Processing and Post-Processing logic is not written in any action, we just write it inside the filters. We can use filters for logging visitor details, knowing who is accessing our website, or for some logging information after an action has executed or authentication/authorization logic for the user which is not basically part of our action method.

This article will demonstrate what filters are, why we use them, and how to create custom filters in ASP.NET MVC. Filters can be defined as Controller level, Action level, or Global level. To define it at controller or action level, we have to use it as an attribute, just like below.

To define your filters at a controller level, just decorate the filter as an attribute with a Controller.

  1. [CustomFilter]  
  2. public class HomeController : Controller 

To define your filters at an action level, just decorate the filter as an attribute with Action method.

  1. [CustomFilter]  
  2. public ActionResult Index() 

To define your filters at a global level, just add the filter in a GlobalFilterCollection object in FilterConfig.cs file which is located in the App_Start folder of ASP.NET MVC application.

  1. namespace FilterExample {  
  2.     public class FilterConfig {  
  3.         public static void RegisterGlobalFilters(GlobalFilterCollection filters) {  
  4.             filters.Add(new HandleErrorAttribute());  
  5.             filters.Add(new CustomFilter());  
  6.         }  
  7.     }  

And this is already registered on Application_Start method inside Global.asax.cs file.

  1. public interface IAuthenticationFilter {  
  2.     void OnAuthentication(AuthenticationContext filterContext);  
  3.     void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext);  

There are different types of filters available in ASP.NET MVC based on their uses in the ASP.NET MVC page life cycle and these are as following.

Authentication Filter

As the name says, it is an authentication filter used for authentication of the valid user while processing the requested page. It is the first filter which executes before any other filter is being executed.  It implements IAuthenticationFilter interface which has defined two methods:  OnAuthentication, which will be called at the time of user verification; and OnAuthenticationChallenge, which will be called after Authentication or Authorization has failed and an action method gets called before your View is being rendered.

  1. public interface IAuthenticationFilter {  
  2.     void OnAuthentication(AuthenticationContext filterContext);  
  3.     void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext);  
  4. }  

Authorization Filter

This filter is called when authorization is required. Basically, the sequence of calling this filter is just after the Authentication filter and just before an action filter gets called. It is used to authorize the user with his/her role. For example “Authorize” attribute is used to implement Authorization filter. Authorization filter implements IauthorizationFilter interface which has only one method defined as “OnAuthorization” which will call at the time of authorization.

  1. public interface IAuthorizationFilter {  
  2.     void OnAuthorization(AuthorizationContext filterContext);  
  3. }  

Action Filter

This filter is really helpful when we have to perform some pre or post-processing logic with action method executed. Yes, action filter gets called before an action method gets executed and after an action method gets executed. Action filter implements IactionFilter interface which has two methods defined as OnActionExecuted and OnActionExecuting. OnActionExecuting method is called just before an action method getting called and OnActionExecuted method is called just after an action method getting called.

  1. public interface IActionFilter {  
  2.     void OnActionExecuted(ActionExecutedContext filterContext);  
  3.     void OnActionExecuting(ActionExecutingContext filterContext);  
  4. }  

Result Filter

It is similar to Action Filter and used to modify your View before rendering or performing some extra custom logic just after rendering the View. So, it means, it is mainly used for your result which you want to render on the View. It implements IresultFilter interface which has two methods similar to ActionFilter as OnResultExecuted, called just after your result is created and OnResultExecuting which is called just before your result is declared. For example, there is an inbuilt Result filter which gets used using “OutputCache” attribute that is used to cache your page response.

  1. public interface IResultFilter {  
  2.     void OnResultExecuted(ResultExecutedContext filterContext);  
  3.     void OnResultExecuting(ResultExecutingContext filterContext);  
  4. }  

Exception Filter

This filter is called when some exception has occurred. For example, if we would like to log exception messages when an exception occurrs then we can use exception filter. There is an inbuilt exception filter available and that is “HandleError” attribute. This implements IexceptionFilter interface which has only one method defined as OnException and it gets called when any exception is generated.

  1. public interface IExceptionFilter {  
  2.     void OnException(ExceptionContext filterContext);  

Custom Action Filters

There are several inbuilt filters available with their uses. But if we want to add some custom logic as per our requirement then we can create custom action filter. In this demonstration, we will see, how to create custom action filter to track our visitor data and update page view once a page gets a view.

Before moving to Visual Studio to create an application, just create one database and a few tables that we will use further in this demonstration. Following scripts, we can use this for creating database and tables.

  1. CREATE DATABASE Demo  
  2. GO  
  3. USE Demo  
  4. CREATE TABLE Visitors (Id INT PRIMARY KEY IDENTITY(1,1), IP_Address VARCHAR(50), Location VARCHAR(255), Created_date DATETIME)  
  5. CREATE TABLE PageDetails(Id INT PRIMARY KEY IDENTITY(1,1), PageName VARCHAR(50), Views INT)  

Visitors table will contain information about real-time visitors who visit our sites and the PageDetails table will show page view of the particular page.

So we have database and tables ready for demonstration. Now just create an Asp.Net MVC application as we usually create in Visual Studio.To create a new project just follows the following instructions.

  1. Open Visual Studio 2013/2015/2017
  2. Go to File >> New >> Project.
  3. From the "New Project" window, select “ASP.NET Web Application”.
  4. Browse the location to save the project and provide a suitable name and click "OK".
  5. From the next window, select MVC as a template and click "OK".

Create a new folder in solution, name it “filters” and add a new class and name it “CustomFilter.cs”. To make this class behave as an Action filter, we have to inherit “ActionFilterAttribute” class as the following code shows.

  1. using System;  
  2. using System.Data;  
  3. using System.Linq;  
  4. using System.Net;  
  5. using System.Web;  
  6. using System.Web.Mvc;  
  7. using System.Xml;  
  8. namespace FilterExample.filters {  
  9.     public class CustomFilter: ActionFilterAttribute {  
  10.         //     Called by the ASP.NET MVC framework before the action method executes.       
  11.         public override void OnActionExecuting(ActionExecutingContext filterContext) {}  
  12.         //     Called by the ASP.NET MVC framework after the action method executes.      
  13.         public override void OnActionExecuted(ActionExecutedContext filterContext) {}  
  14.         //     Called by the ASP.NET MVC framework before the action result executes.       
  15.         public override void OnResultExecuting(ResultExecutingContext filterContext) {}  
  16.         //     Called by the ASP.NET MVC framework after the action result executes.         
  17.         public override void OnResultExecuted(ResultExecutedContext filterContext) {}  
  18.     }  
  19. }  

As we will perform some database operation here to add data into the database. So, right click to solution, add a new item named “Ado.Net Entity Data Model” and through the wizard just make a connection with the defined tables as above.  In this example, we have created “DemoEntities” to access database tables.

Just update the following lines of code inside the OnActionExecuting method. Basically, here we are getting visitor details like their IP address and Location based on some parameters and once this data is available, we add it to Visitors tables. This logic will perform before any action method is being executed.

  1. public override void OnActionExecuting(ActionExecutingContext filterContext) {  
  2.     string varVisitorCountry = string.Empty;  
  3.     string varIpAddress = string.Empty;  
  4.     varIpAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];  
  5.     if (string.IsNullOrEmpty(varIpAddress)) {  
  6.         if (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null) {  
  7.             varIpAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];  
  8.         }  
  9.     }  
  10.     if (varIpAddress == "" || varIpAddress == null) {  
  11.         if (HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"] != null) {  
  12.             varIpAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];  
  13.         }  
  14.     }  
  15.     WebRequest varWebRequest = WebRequest.Create("http://freegeoip.net/xml/" + varIpAddress);  
  16.     WebProxy px = new WebProxy("http://freegeoip.net/xml/" + varIpAddress, true);  
  17.     varWebRequest.Proxy = px;  
  18.     varWebRequest.Timeout = 2000;  
  19.     try {  
  20.         WebResponse rep = varWebRequest.GetResponse();  
  21.         XmlTextReader xtr = new XmlTextReader(rep.GetResponseStream());  
  22.         DataSet ds = new DataSet();  
  23.         ds.ReadXml(xtr);  
  24.         varVisitorCountry = Convert.ToString(ds.Tables[0]);  
  25.     } catch {}  
  26.     using(var db = new DemoEntities()) {  
  27.         db.Visitors.Add(new Visitor() {  
  28.             IP_Address = varIpAddress,  
  29.                 Location = varVisitorCountry,  
  30.                 Created_date = DateTime.Now  
  31.         });  
  32.         db.SaveChanges();  
  33.     }  
  34. }  

Move to the OnActionExecuted method and update the code with following code. This code will be executed after the action method is being executed. Here, we have written logic to update the number of page views inside the database table called "Pagedetails”. 

  1. public override void OnActionExecuted(ActionExecutedContext filterContext) {  
  2.         using(var db = new DemoEntities()) {  
  3.             var pageDetail = db.PageDetails.Where(x => x.PageName == "Home").FirstOrDefault();  
  4.             if (pageDetail != null) {  
  5.                 if (pageDetail.Views != null) {  
  6.                     db.PageDetails.FirstOrDefault().Views += 1;  
  7.                 } else {  
  8.                     db.PageDetails.Add(new PageDetail() {  
  9.                         PageName = "Home",  
  10.                             Views = 1  
  11.                     });  
  12.                 }  
  13.             }  
  14.             db.SaveChanges();  
  15.         } 

Now, it is time to call this custom action filter with our action method in Home Controller. So, we are just decorating our Index action method of HomeController with [CustomFilter] attribute, as below.

  1. public class HomeController: Controller {  
  2.     [CustomFilter]  
  3.     public ActionResult Index() {  
  4.         return View();  
  5.     }  

Now, run the application and check the database. After running the application, we have refreshed the page once more. So, our page has reloaded. When we move to the database and select both tables to see the data, we will find the following output.

Here, we can see that "Visitors" table contains the records for each visitor and "PageDetails" table contains the page view based on the page name and this information has been added by the custom filter, as we created above. Visitors' information is added to the database as pre-processing logic and page view information is added as post-processing logic.

Conclusion

So, today, we learned what filters are in ASP.NET MVC and why should we use them. We have also seen how to create a custom filter and use it.

I hope this post will help you. Please put your feedback in the comments section which will help me to improve myself for the next post. If you have any doubts, please ask; and if you like this post, please share it with your friends.