C# .NET Core Filters

.NET Core Filters

Filters are used to implement reusable MVC pipeline logic that can be applied across the system, without writing that logic in all of your actions. Examples might be Exception handling, authorization, response caching etc. Filters intercept the stages of the MVC pipeline and allows us to run code before/after their executions.

There are different types of filters, and each happens in a different stage of the pipeline.

  • Authorization Filters run first to determine if the request is authorized and can short-circuit the pipeline if it is unauthorized.
  • Resource Filters are first after authorization. They can run code against the request on the way in and on the way out. Often used for caching or influencing the model binding. Can short-circuit the pipeline.
  • Action Filters are used to run code immediately before and/or immediately after the controller action. Can manipulate the arguments or results of the action.
  • Exception Filters are used go apply global policies to unhandled exceptions before anything is written to the response.
  • Result Filters are used to run code immediately before and/or after successful execution of action results. Useful for view formatting.

Filter Scopes

You can add a filter to request pipelines in 3 scope levels:

  • Globally using MvcOptions.Filters in ConfigureServices of your Startup
  • Controller level via Attributes
  • Specific action via Attributes
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add(typeof(ExceptionFilter));
    });
}

As an attribute

public class ExceptionFilter : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        ILogger logger = LogManager.GetLogger(context.ActionDescriptor?.DisplayName);

        logger.Error(context.Exception);
    }
}

On the Controller


[ExceptionFilter]
public class TestController : Controller
{
    // GET: api/test
    [HttpGet]
    public IEnumerable Get()
    {
        return View(new HomeViewModel());
    }
}

On the Action


public class TestController : Controller
{
    // GET: api/test
    [HttpGet]
    [ExceptionFilter]
    public IEnumerable Get()
    {
        return View(new HomeViewModel());
    }
}

You can set order on Filters with an Order property.
[ExceptionFilter, Order = 5]

Filters with the same Order run outside-in, meaning first global, then controller and then action-level filters are run.

Async / Sync Filters

Filter supports synchronous and asynchronous filters; The implementations use different interfaces.

Synchronous filters specify directly what happens in order using OnActionExecuting and OnActionExecuted. OnActionExecuting method is called before the action method and OnActionExecuted method is called after the action method.


public class CustomActionFilter : IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context)
        {
            //To do : before the action executes
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            //To do : after the action executes
        }
    }

Asynchronous filters are implemented with a single method, OnStageExecutionAsync


public class CustomAsyncActionFilter : IAsyncActionFilter
    {
        public async Task OnActionExecutionAsync(ActionExecutingContext context,
            ActionExecutionDelegate next)
        {
            //To do : before the action executes
            await next();
            //To do : after the action executes
        }
    }

.NET checks first for async filters, if found is called. If it is not found it calls the synchronous interface’s method(s). If both are implemented, the sync version will not be called.