Dealing with Filters in MVC Framework 4.0

Introduction:- In software development field, we developers always try to use those things which makes our life easier. Frankly speaking we developers always try to write as less code as possible. And Microsoft understand it very well, so they developed Filters.

Ok, so question is how Filters will make our life easier?

Answer of above question is in three words – cross-cutting concerns.

Cross-cutting concernswhat it is? This term is in use to refer those functionality that is used on all over the application, doesn’t fit into any one place, where it would break the heart of MVC Framework that is separation of concerns. Example of cross-cutting concerns are logging, authorization, caching etc.

For example let say I have four action methods in my Home controller, and I wanted to let the user access to these methods only if they have authority to access it. So what I can do, I just write code in all these four methods like –

if (!Request.IsAuthenticated)
{
FormsAuthentication.RedirectFromLoginPage();
}

So all you can say, what it is? We need to write the same code four times. For this problem one solution can be writing one new function and placing this common code to that function. But still we need to call this function from each action method.

So Now here Filters comes into play. With the help of filter what we can do, we can just write one attribute at the top of the controller, that’s it, we done . Like –

 [Authorize]
 public class HomeController : Controller

Note – People who are not aware of Attributes in .NET, I would suggest to have a little bit idea of it. Without having knowledge of Attribute you will not be able to make most of it(Filter).

Types of Filters –
MVC Framework provides 4 basic type of Filters

  1. Authorization
  2. Action
  3. Result
  4. Exception

Let us check all these in more details-

Authorization Filter – As name suggest this is in use for handling authorization. This filter runs before any other filter or any action method.
Interface – IAuthorizationFilter
Default Implementation – AuthorizeAttribute

Action Filter – Runs before and after Action method.
Interface – IActionFilter
Default Implementation – ActionFilterAttribute

Result Filter – Runs before and after the action result executed.
Interface – IResultFilter
Default Implementation – ActionFilterAttribute

Exception Filter – Runs when exception occurs.
Interface – IExceptionFilter
Default Implementation – HandleErrorAttribute.

Please note that the default implementation is a class which implements corresponding interface which is mandatory to create Filter in MVC Framework. The next point is for ActionFilter and Result Filter the default implementation class is same(ActionFilterAttribute). It means that this class implements both the interface IActionFilter, IResultFilter.

MVC Framework provides the way to create our own custom filter by implementing the above mentioned Interfaces or by inheriting the default implementation classes. Most of the time when we are creating our own custom filter then we are inheriting the default implementation class like ActionFilterAttribute instead of implementing the interface directly. The main advantage of doing so is, when we inherit any class then we need to only override those methods which we need, but in case of interface we will be needing to implement each and every method of interface.

Applying Filters to Controllers and Action Method-
We can apply filters to Controlles as well as on Action methods. The main difference is, if we will apply the Filter on controller then all the action methods available in that controlller will have impact. From my above example –

[Authorize]
 public class HomeController : Controller

All the action method will be under authorization as we applied filter on controller class.

 

We can apply the Filter on any individual action method too, in this condition we will have impact of that filter only on that action method.

Using Authorization Filter –
Here is my custom Filter-

public class MyAuthAttribute : AuthorizeAttribute
 {
 private string PcName = string.Empty;

public MyAuthAttribute(string PcName)
 {
 this.PcName = PcName;
 }

protected override bool AuthorizeCore(HttpContextBase httpContext)
 {
 return PcName == "MUKUND-PC" ? true : false;
 }
 }

Use –

 [MyAuth("MUKUND-PC")]
 public String Index()
 {
 return "Hello from Mukund-PC";
 }

We can also use the in built authorization filter MVC framework. I would like to suggest you always the in built filter, because if it will fail then we can at least blame Microsoft for it. 🙂

We can use built in Authorization filter also like –

 [Authorize(Users = "himanshu, vipin, uttam", Roles="admin")]
 public string TestBuiltInAuthorizeFilter()
 {
 return "Hello from TestBuiltInAuthorizeFilter of CheckCustomAuthController";
 }

Using Exception Filter-

Here is my custom exception filter

public class MyExceptionFilterAttribute : FilterAttribute, IExceptionFilter
 {
 public void OnException(ExceptionContext filterContext)
 {
 filterContext.Result = new RedirectResult("~/content/Error.html");
 filterContext.ExceptionHandled = true;
 }
 }

The most important thing here is I used FilterAttribute along with IExceptionFilter. You must be wondering, why we are doing it? Well, answer is for making any .NET attribute to MVC filter, the attribute class must implement IMvcFilter. Yes, we can use this interface directly but again same problem, need to implement all the methods of interface. So just used the already implemented class, that is FilterAttribute.

Use –

 [MyExceptionFilter]
 public string Index()
 {
 int num = 10;
 int denom = 0;

int result = num / denom;

return Convert.ToString(result);
 }

I had added one folder content and then one html page Error.html for setting the result to the Exception Context.

Using built in Exception Filter –
We can use the built in exception filter HandleError also. For using built in exception filter we need to provide two things
1. The ExceptionType and
2. View

One of the most important setting which we need to do is to set customErrors mode On in Web.Config file. By default it will be RemoteOnly so while developing you will be getting the error and once you will upload you will get the desired error page. Here is the synatx. You need to put this inside System.web

<customErrors mode="On" defaultRedirect="/content/Error.html"></customErrors>

Example –

 [HandleError(ExceptionType = typeof(ArgumentOutOfRangeException), View = "AgeError")]
 public string AgeTest(int id)
 {
 if (id > 100)
 {
 throw new ArgumentOutOfRangeException();
 }
 else
 {
 return String.Format("Your age is {0}", id);
 }
 }

Note – I had added Shared folder in View and then added AgeError.cshtml.

Using Action Filter And Result Filter –

We can create our own custom action filter and result filter in two ways. We can use the interface IActionFilter, IResultFilter or we can use the default implementation class ActionFilterAttribute. In my opinion we should be using the class by inheriting it. We can use interface too but in this condition we will be needing to implement all the methods of interface, but in case of class we can only override those method which are required. We can use this filter to do something while executing action method and result of action method in OnActionExecuting and OnResultExecuting method respectively. And we can do something after the execution of Action method and result of Action Method in OnActionExecuted and OnResultExecuted method respectively.

IactionFilter Interface
 namespace System.Web.Mvc
 {
 public interface IActionFilter
 {
 void OnActionExecuting(ActionExecutingContext filterContext);
 void OnActionExecuted(ActionExecutedContext filterContext);
 }
 }

IResultFilter Interface
 namespace System.Web.Mvc
 {
 public interface IResultFilter
 {
 void OnResultExecuting(ResultExecutingContext filterContext);
 void OnResultExecuted(ResultExecutedContext filterContext);
 }
 }

ActionFilterAttribute class-

public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter,IResultFilter
 {
 public virtual void OnActionExecuting(ActionExecutingContext filterContext) {}
 public virtual void OnActionExecuted(ActionExecutedContext filterContext) {}
 public virtual void OnResultExecuting(ResultExecutingContext filterContext) {}
 public virtual void OnResultExecuted(ResultExecutedContext filterContext) {}
 }

Here is implementation of custom Action Filter by using IActionFilter-

public class MyActionFilterAttribute : FilterAttribute, IActionFilter
 {
 StringBuilder sbTestActionFilter = new StringBuilder();

public void OnActionExecuting(ActionExecutingContext filterContext)
 {
 sbTestActionFilter.Append("<div>In OnActionExecuting</div>");
 }
 public void OnActionExecuted(ActionExecutedContext filterContext)
 {
 sbTestActionFilter.Append("<div>In OnActionExecutedMethod</div>");

filterContext.HttpContext.Response.Write(sbTestActionFilter);
 }
 }

using this filter in controller –

[MyActionFilterAttribute]
 public string Index()
 {
 return string.Empty;
 }

Result in browser –
In OnActionExecuting
In OnActionExecutedMethod

Here is implementation of Custom Result Filter By Using IResultFilter-

public class MyResultFilterAttribute : FilterAttribute, IResultFilter
 {
 StringBuilder sbTestResultFilter = new StringBuilder();

public void OnResultExecuting(ResultExecutingContext filterContext)
 {
 sbTestResultFilter.Append("<div>In OnResultExecuting Method</div>");
 }

public void OnResultExecuted(ResultExecutedContext filterContext)
 {
 sbTestResultFilter.Append("<div>In OnResultExecuted Method</div>");

filterContext.HttpContext.Response.Write(sbTestResultFilter);
 }
 }

using this filter in controller –

[MyResultFilter]
 public string Index()
 {
 return string.Empty;
 }

Result in browser-
In OnResultExecuting Method
In OnResultExecuted Method

Implementation of Custom Action and Result Filter by using ActionFilter attribute class –
As per the implementation of ActionFilter attribute we will have all the methods of IResultFilter and IActionFilter but here I will be using only two methods OnActionExecuting of IActionFilter and OnResultExecuted of IResultFilter.

Here is the example –

public class MyActionAndResultFilterAttribute : ActionFilterAttribute
 {
 StringBuilder sbTestActionAndResult = new StringBuilder();

public override void OnActionExecuting(ActionExecutingContext filterContext)
 {
 sbTestActionAndResult.Append("<div>In OnActionExecuting method</div>");
 }

public override void OnResultExecuted(ResultExecutedContext filterContext)
 {
 sbTestActionAndResult.Append("<div>In OnResultExecuted method</div>");

filterContext.HttpContext.Response.Write(sbTestActionAndResult);
 }
 }

Use in controller –

[MyActionAndResultFilter]
 public string Index()
 {
 return string.Empty;
 }

Result in browser –
In OnActionExecuting method
In OnResultExecuted method

Using Global Filters –
Let say we created one filter and we want to use that filter through out the application. For doing this we will need to register this filter in App_Start/FilterConfig.cs like –

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 {
 filters.Add(new HandleErrorAttribute());
 filters.Add(new MyActionAndResultFilterAttribute());
 }

Please note we used the full name of class including word ‘Attribute’. RegisterGlobalFilters method is called from Application_Start method of Global.asax. So when our application will start all the action method will have impact of this filter.

You can download the source code here.

Please leave your comment below, if you want add something. You can follow me on twitter https://twitter.com/mnarayanjha, connect with me on LinkedIn (http://www.linkedin.com/pub/mukund-narayan/42/2a1/630)

Written By: Mukund Narayan, Software Engineer, Mindfire Solutions

Advertisements

Posted on March 25, 2014, in MVC and tagged , , , , . Bookmark the permalink. Leave a comment.

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

%d bloggers like this: