Resource Filter in ASP.NET CORE MVC

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.

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 Bageri

I am Microsoft MVP | C# Corner MVP | Code Project MVP | FULL STACK .NET Developer and working on .Net Web Technology (Asp.net, Asp.net Core,.Net Core, C#, Sqlserver, MVC, Windows, Console Application, javascript, jquery, json, ORM Dapper) and also a freelance developer.