What are attributes and filters
MVC provides a very clean way of injecting the pre-processing and post-processing logic for actions and controllers. They way we can put the pre-processing and post-processing logic is by decorating the actions with attributes which will invoke an attribute class implementing the filter's logic.
For example, If we need some action to be executed when the user has been authenticated then we can adorn the action with the
[Authorize]
attribute. This will take care of calling the attribute class which implements the authorization filter to check whether the user has is authorized or not.
Hide Copy Code
[Authorize]
public ActionResult Index()
{
return View();
}
So the way to implement custom filters would be to implement the interface that is needed for implementing the required filter. Now we can decorate the actions with this attribute so that our filter logic will be executed when this action is called. If we want all the actions of a controller to use this filter we can decorate the controller itself with this attribute.
Using the code
Let us now try to look at the type of filters we can implement to inject our custom processing logic.
Type of filters
Now taking this discussion further, Let us first discuss the various types of filters that can be implemented to inject custom processing logic.
- Authorization filter
- Action filter
- Result filter
- Exception filter
Implementing Custom Filters
Now let us try to look at implement these filters. We will simply implement the custom filters and put a simple message in the
ViewBag
collection. We will then use these filters with an action of controller and try to see the custom messages we inserted in the ViewBag
collection on our view page.Authorization filter
This filter provides authentication and authorization logic. It will be executed before the action gets executed. To implement this action the interface
IAuthorizationFilter
should be implemented by the custom attribute class.
Hide Copy Code
public class CustomAuthorizationAttribute : FilterAttribute, IAuthorizationFilter
{
void IAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext)
{
filterContext.Controller.ViewBag.OnAuthorization = "IAuthorizationFilter.OnAuthorization filter called";
}
}
Now when we decorate the action method with this attribute the
OnAuthorize
filter method will be called and our custom logic will get executed.
Note: In the above code we have created an attribute which will only run when the authorization is being done by the application. In our own filter method we are not doing anything related to authorization. If we were to do custom authentication and authorization then we will have to derive this attribute from
AuthorizeAttribute
class and implement custom authorization logic. Perhaps we will discuss that separately. For now this filter will run run when the authorization is being done and before calling the action method so that we can inject our custom logic in it.Action filter
This filter will be called before and after the action starts executing and after the action has executed. We can put our custom pre-processing and post-processing logic in this filter.
Now to implement this filter we need to create a custom filter attribute class and implement the
Hide Copy Code
IActionFilterfilter interface. This interface provides us two methods
OnActionExecuting
and OnActionExecuted
which will be called before and after the action gets executed respectively.
Hide Copy Code
public class CustomActionAttribute : FilterAttribute, IActionFilter
{
void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.Controller.ViewBag.OnActionExecuted = "IActionFilter.OnActionExecuted filter called";
}
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.Controller.ViewBag.OnActionExecuting = "IActionFilter.OnActionExecuting filter called";
}
}
Result filter
This filter will execute before and after the result of the action method has been executed. We can use this filter if we want some modification to be done in the action's result.
To implement the result filters we need to create a custom filter attribute class and implement the
Hide Copy Code
IResultFilterinterface. this interface provides two methods
OnResultExecuting
and OnResultExecuted
which will be called before and after the action result respectively.
Hide Copy Code
public class CustomResultAttribute : FilterAttribute, IResultFilter
{
void IResultFilter.OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.Controller.ViewBag.OnResultExecuted = "IResultFilter.OnResultExecuted filter called";
}
void IResultFilter.OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.Controller.ViewBag.OnResultExecuting = "IResultFilter.OnResultExecuting filter called";
}
}
Exception filter
This filter will be invoked whenever a controller or action of the controller throws an exception. This is particularly useful when we need custom error logging module.
To implement this filter we need to create a custom filter attribute class which implements
IExceptionFilter
. This interface gives us a methods called OnException
which is a perfect place to call the exception logging module and to redirect to some error page.
Hide Copy Code
public class CustomExceptionAttribute : FilterAttribute, IExceptionFilter { void IExceptionFilter.OnException(ExceptionContext filterContext) { filterContext.Controller.ViewBag.OnException = "IExceptionFilter.OnException filter called"; } }
Order of Execution
Now with all the above filters we have the following filter methods.
IAuthorizationFilter.OnAuthorization
IActionFilter.OnActionExecuted
IActionFilter.OnActionExecuting
IResultFilter.OnResultExecuted
IResultFilter.OnResultExecuting
IExceptionFilter.OnException
Now assuming that we have all the filters attached to a single action method what will be the order of execution of these filers. These filters will execute in following order under normal(non-exception) scenario.
IAuthorizationFilter.OnAuthorization
IActionFilter.OnActionExecuting
IActionFilter.OnActionExecuted
IResultFilter.OnResultExecuting
IResultFilter.OnResultExecuted
In case there is an exception,
OnException
will will be called as instead of the result filters.Using the Custom Filters
Now from our application we just need to decorate the actions on which we need the custom filter functionality. Lets try to do this on a single action method as:
Hide Copy Code
public class HomeController : Controller
{
[CustomAuthorization]
[CustomAction]
[CustomResultAttribute]
[CustomExceptionAttribute]
public ActionResult Index()
{
//throw new Exception("Dummy Exception");
ViewBag.Message = "Index Action of Home controller is being called.";
return View();
}
}
And the code to see these on the view page:
And when we try to run the application:
The important thing to note in the running application is that
ViewBag.OnResultExecuted
is empty. the reason for this is that the function IResultFilter.OnResultExecuted
gets called when the view has been rendered i.e. the action result has been completed.
Note: It is advisable to put breakpoints on all filter methods and then run the application to understand the sequence of these filter methods. Also, un-commenting the line in controller which throws a dummy exception will invoke the
IExceptionFilter.OnException
filter method too.
Comments
Post a Comment