Asp.net Core 1.1 Mvc Filters VS 2017

Everyone wants to work on an application where code speaks for itself. Clean codes are easy to maintain and simple to walk through.

Attributes and Filters are a way provided in the Mvc framework to detach codes that are mostly related to the fan-ins or fan-outs of an action.

You can check validity of the action arguments, apply some business logic to see if these arguments are really needed to be processed or you can even modify the arguments based on some business logic.

Most of them are redundant tasks i.e., if they are to be done in one action there is a chance these changes will be needed in another action too. Thus it needs to be called in every action where they are needed. But wait, why writing a code and call them when we can just annotate our actions with some attributes and get these changes executed.

Filters

Within request pipeline in Asp.net core 1.1, the requests travel through middlewares one by one to reach the Mvc. Interestingly, Mvc has another pipeline architecture to entertain the request called Filter pipeline.

Just like middlewares, Mvc filters also entertain request one by one and can return the response if a filter decides not to process the request any further (called short circuiting the response). The filter pipeline runs after Mvc selects the action to be executed by processing the routing data.

All of the filters are inherited from the markup interface

public interface IFilterMetadata { }

Its an empty interface, cause filters can have a wide variety and can not be generalized by one or two method signatures. Leaving the details to the more specific filter interfaces.

There are two more important interfaces which can be used interchangeably.

public interface IFilter { }
public interface IFilterFactory { }

Attributes

Filters are classes implementing few interfaces that we will walk through later in this post. Another important concept that goes hand in hand with filters is Attributes. Attributes is a feature provided by the .Net for helping compilers and frameworks that decides the behaviors of the application at runtime. These frameworks get to the action/method that is going to be executed and then get the related attributes by using reflection. Based on these attributes the framework can decide what further execution path is to be taken or even can decide to terminate and short circuit the execution. To create an attribute it is important to inherit the class from the parent class Attribute.

public class SystemLogsAttribute : Attribute { }

Coming back to the filters, we will be using filters using attributes. Mvc processes the routes and select an Action to execute but before executing the action, Mvc triggers the Filter pipeline and see if there are any filter attributes added to the action using reflection. If the filters are found, a new filter pipeline will be created for the action to be executed.

A filter attribute works together with IFilterFactory for Mvc framework to create a filter pipeline. As soon as Mvc finds a filter attribute, it tries to convert the filter into IFilterFactory. If the conversion is successful, Mvc executes the method on IFilterFactory reference

public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)

This will create a filter, attach it to the filter pipeline and will execute according the the filter pipeline order.

Types

Asp.net Mvc divides the filters into five different types.

  • Authorization Filters
  • Resource Filters
  • Action Filters
  • Exception Filters
  • Result Filters

All of the above filters are triggered at a certain stage of action method execution. All of the above filters are already implemented in Mvc using abstract class and attributes. If we need to control the flow we will need to inherit one of these filters to work with. More control on the execution pipeline can be attained  by using

  • Global Filters
  • Middleware Filters

Global filters works globally on all actions and are executed on priority by default. Middleware Filters works on certain actions where the attribute was found. These filters can control the middleware and can execute different middleware specifically when these actions are requested.

Async Filters

As asp.net Mvc is providing async actions, filters can also be called async. For async implementations Mvc provide different abstract classes to inherit from.

Following are the brief details of common filters provided by Asp.net Mvc.

Authorization Filter

After global filters they are the top priority filters to be triggered when an action receives a request. As authorization is executed at the earliest, they are used to check for permissions, authorizations or authentications of the user. If the logic decides a failure state and do not wish to continue the execution of the action, this filter can short circuit the execution and send a response without engaging any other filter or the action itself.

Resource Filter

After authorization is executed, the control is passed down to the resource filters, if there are any. Resource filter is executed before the model bindings. Which means the objects being accepted in the action can not be checked for fluent validations or any modifications can not be performed to the model yet. The best use case for resource filter can be sending a response based on the request and without processing the request. It can happen with cached responses. Or it can also be used to present I/O resources without exposing the directory structures of the application like minified CSS, JS or even certain images or files that are needed on the client side. It can also be used to manipulate the data for model binding.

Action Filter

Action filters are the most commonly used or needed in the development of applications with Mvc. Action filters are have two methods to implement. One is automatically called before the execution of an action and the other method is called after the execution of the action. Hence we can manipulate the inputs or short circuit them before the execution and we can also change the output or add headers to the output after the action is completely executed.

Exception Filter

Exception filters are triggered when the action throws an exception. Exception filters can ease up the handling and sending a uniformed response for all kind of exceptions. These filters are called before the response is sent to clients hence we can modify or format the response for better user experience.

Result Filters

While using razor views or any other custom views engine for viewresults, when we call the IActionResult and ask it to create a view and return, we do not have much control over the process of creation of the view results completely. Result filters are executed before and after the view result is calculated. While before view is calculated we can change the view result with a more generic one to control things centrally. But once that portion is executed the control is given back to the result filter OnResultExecuted method, where we can either store the result in cache, create logs, but we cannot make changes the response as the response has already begun.

Creating a Filter with Attribute

You can create filters by implementing IFilterFactory along with attribute or you can just inherit the built-in filter attributes and extend them with your own implementation. Following are the available built-in filter attributes

ActionFilterAttribute
ExceptionFilterAttribute
ResultFilterAttribute
FormatFilterAttribute
MiddlewareFilterAttribute
ServiceFilterAttribute
TypeFilterAttribute

First three filters are in Microsoft.AspNetCore.Mvc.Filters namespace. Others are available in Microsoft.AspNetCore.Mvc namespace. Let’s implement an ActionFilterAttribute. You need to declare a class with the following signatures

public class SampleFilterAttribute : ActionFilterAttribute { }

Action filters provide overrides for following methods

public override void OnActionExecuting(ActionExecutingContext context);
public override void OnActionExecuted(ActionExecutedContext context);
public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next);

public override void OnResultExecuting(ResultExecutingContext context);
public override void OnResultExecuted(ResultExecutedContext context);
public override Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next);

You can either override synchronous methods or asynchronous methods but not both. If a class implements both synchronous and asynchronous methods, only asynchronous method will be executed. Asp.net Mvc looks for async implementations first, if they are found they are executed and synchronous implementations are ignored.

and the output is
SampleActionFilterOutput

Output doesn’t contain information about OnResultExecuted, because when that method triggers the result is already executed and has started the response stream to render on the browser.

Filter attributes keep the programmer in control of where the filter is to be applied and where to ignore. If a filter attribute is intended to be applied on all actions of a controller, it can only be applied to the controller and compiler will understand that it is applied on all actions. What if you want to apply the filter to all the controllers?

Global Filters

Filters can be added globally to an Asp.net core mvc application in startup.cs file.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc((options) => {
        options.Filters.Add(new SampleActionFilterAttribute());
    });
    services.AddTransient<Person>();
}
  • If we add a global filter using new instance, same instance will be used for multiple requests.
  • options.Filters.Add(), resolves the filter by instance or type. Instances are created using Activator utilities/Type activation (Controllers are type activated, since we do not need to register controllers with dependency resolvers). For type we can call the Add as follows

options.Filters.Add(typeof(SampleActionFilterAttribute));

Adding by instance will use the same instance in all requests. Whereas adding by type will create new instance every time the filter is referred by the compiler.

We can also use AddService method to register global filters in Mvc.

options.Filters.AddService(new SampleActionFilterAttribute());
options.Filters.AddService(typeof(SampleActionFilterAttribute));

AddService method initiate the instances using dependency injection and can create objects with registered scopes. For using AddService SampleActionFilterAttribute should be registered with dependency resolver services.

services.AddTransient<SampleActionAttribute>();

When we initiate a filter using new instance we can pass the constructor arguments but what if our filter class has few dependencies?

Dependency Injection with Attributes

The filters that are directly inherited from Attribute class and are applied to controllers or actions directly, cannot resolve arguments in their constructor using dependency injection. This is because compiler expects their parameters to be provided when attributes are applied, if their are any.

Even a simple filter for writing logs to a text file will depend on some log engine provider like NLog or Log4net.

You do not want to register a filter as a global filter and want to use attributes with specific controllers or actions but also needs to work with dependencies, you need service filters or type filters.

Service Filters

If we register a filter with services in our startup.cs class we can use it in an attribute and bind it to specific controllers or actions. For binding the attribute following example can be considered. Dependency resolvers will be used to create the instance of a service filter.

[ServiceFilter(typeof(SampleActionFilterAttribute))]
public IActionResult Index() { … }

Type Filters

Type filters are like service filters, the only difference is that they are not resolved using dependency injection. Rather they use typed activation. Thus you don’t need to register filter with dependency resolver first. Additionally, you can also send collection of objects as arguments of the constructor in the attribute.

[TypeFilter(typeof(SampleActionFilterAttribute), Arguments = new object[] { “Author”, “Azmat” })]
public IActionResult Index() { … }

You can also engage asp.net core middle wares in filters pipeline but that is going to be an advanced topic and rarely used. I will definitely write about it in future.

Order of Filters

Filters are by default ordered in the following order

  1. Global Filters
  2. Authorization Filter
  3. Resource Filter
  4. Action Filter
  5. Exception Filter
  6. Result Filter

We can change order by implementing IOrderedFilter on your filter. If we are using built-in Attributes and overrides, almost all the attributes let you set the order. If you are using global filters, both methods (Add, AddService) that we discussed has overloads accepting the filter order.

For more details you can visit the following URL from microsoft
https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters

Advertisements

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