In ASP.NET Core MVC, Resource Filters are a special type of filter that allow you to execute code before and after the rest of the filter pipeline, but crucially, after authentication and before model binding. This makes them ideal for scenarios where you need to perform logic early in the request lifecycle—such as modifying route data, short-circuiting requests, or implementing custom caching mechanisms.

Resource Filters can be particularly useful when you want to intercept requests to apply global logic, manipulate model binding behavior, or manage resource-intensive operations. Since they execute before model binding, they offer a unique opportunity to optimize performance and control the request flow more effectively.

In this article, we’ll explore how to implement and use Resource Filters in ASP.NET Core MVC, with examples to demonstrate their practical applications.

If you want to run logic just after the execution of an authentication filter then use ResourceFilter. ResourceFilter can be used for caching and make changes to model binding because it runs before model binding take place.

Project showing Added Filters in folder

We have 2 types of Resource filter one is Sync and another is Async, for implementing Sync type we need to inherit IResourceFilter and for implementing Async type we need to inherit IAsyncResourceFilter Filter.

  1. IResourceFilter
    1. OnResourceExecuting
    2. OnResourceExecuted
  2. IAsyncResourceFilter
    1. OnResourceExecutionAsync

IResourceFilter

OnResourceExecuting can run code before the rest of the filter pipeline.
OnResourceExecuted can run code after the rest of the pipeline has completed.

For example- OnResourceExecuting can run code before model binding.

Reference: –
https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.2#resource-filters

Implementation

using Microsoft.AspNetCore.Mvc.Filters;
using System;

namespace WebApplication4.Filters
{
    public class CustomResourceFilter : Attribute, IResourceFilter
    {
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
        }
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
        }
    }
}

Let’s create Custom ResourceFilter with name CustomResourceFilter after creating class next we are going to inherit it with IResourceFilter interface and then implement 2 methods in it OnResourceExecuting, OnResourceExecuted in OnResourceExecuting method we are going to check for custom headers if it does not contains headers which is required then we are going to show error message.

Code Snippet of CustomResourceFilter

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Linq;

namespace WebApplication4.Filters
{
    public class CustomResourceFilter : Attribute, IResourceFilter
    {
        private readonly string[] _headers;

        public CustomResourceFilter(params string[] headers)
        {
            _headers = headers;
        }
        public void OnResourceExecuted(ResourceExecutedContext context)
        {

        }

        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            if (_headers == null) return;

            if (!_headers.All(m => context.HttpContext.Request.Headers.ContainsKey(m)))
            {
                context.Result = new JsonResult(
                    new { Error = "Headers Missing" }
                )
                { StatusCode = 400 };
                ;
            }
        }
    }
}

Next, we are going to apply this filter on Post method of Default controller API and pass names of the header as string array which are required.

Code Snippet of Default1Controller

using Microsoft.AspNetCore.Mvc;
using WebApplication4.Filters;
using WebApplication4.Models;

namespace WebApplication4.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class Default1Controller : ControllerBase
    {

        // POST: api/Default1
        [HttpPost]
        [CustomResourceFilter("X-Value", "Y-Value")]
        public void Post([FromBody] UserRoles value)
        {

        }
    }
}

IAsyncResourceFilter

IAsyncResourceFilter is an async version of the resource filter to use it we need to implement IAsyncResourceFilter interface which contains OnResourceExecutionAsync method.

Let’s create Custom Async ResourceFilter with name CustomAsyncResourceFilter after creating class next we are going to inherit it with IAsyncResourceFilter interface and then implement 1 methods in it OnResourceExecutionAsync in OnResourceExecutionAsync method we are going to check for custom headers if it does not contains headers which is required then we are going to show error message.

using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication4.Filters
{
    public class CustomAsyncResourceFilter : Attribute, IAsyncResourceFilter
    {
        public Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
        {
          
        }
    }
}

Code Snippet of IAsyncResourceFilter

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication4.Filters
{
    public class CustomAsyncResourceFilter : Attribute, IAsyncResourceFilter
    {
        private readonly string[] _headers;

        public CustomAsyncResourceFilter(params string[] headers)
        {
            _headers = headers;
        }
        public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
        {
            if (_headers == null) return;

            if (!_headers.All(m => context.HttpContext.Request.Headers.ContainsKey(m)))
            {
                context.Result = new JsonResult(new { Error = "Headers Missing" })
                { StatusCode = 400 };
                ;
                return;

                throw new NotImplementedException();
            }
            ResourceExecutedContext executedContext = await next();

        }
    }
}

Next, we are going to apply this filter on Post method of Default controller API and pass names of the header as string array which are required.

How to Apply Filter

using Microsoft.AspNetCore.Mvc;
using WebApplication4.Filters;
using WebApplication4.Models;

namespace WebApplication4.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class Default1Controller : ControllerBase
    {

        // POST: api/Default1
        [HttpPost]
        [CustomAsyncResourceFilter("X-Value", "Y-Value")]
        public void Post([FromBody] UserRoles value)
        {

        }
    }
}

By Saineshwar

Microsoft MVP for Developer Technologies | C# Corner MVP | Code project MVP | Senior Technical Lead | Author | Speaker | Love .Net | Full Stack developer | Open source contributor.