How to create Action Filters in ASP.NET Core Web API

To create an Action filter, we need to create a class that inherits either from the IActionFilter interface or IAsyncActionFilter interface or from the ActionFilterAttribute class.


In our example, we will use the IActionFIlter interface which has everything we need.


- Launch the Visual Studio IDE


Click on File > New > Project


- Select the "ASP.NET Core Web Application" option from the incoming dialog. Click Next.


- Name the project as "ActionFilters". Click Create.


- Select the ".NET Core" and "ASP.NET Core 3.1" options form the drop-down list at the top. Then select the "API" option as shown below. Click Create.


- Ensure that the check boxes "Enable Docker Support" and "Configure for HTTPS" are unchecked.


ActionFilters-1.PNG

In this way, you will create a new ASP.NET Core Web API Application


Create a new folder named Entities and then create a new class named Person in the Entities folder as shown below


using System.ComponentModel.DataAnnotations;

namespace ActionFilters.Entities
{
    public class Person
    {
        [Key]
        public int ID { get; set; }

        [Required(ErrorMessage = "FirstName is required")]
        public string FirstName { get; set; }

        [Required(ErrorMessage = "LastName is required")]
        public string LastName { get; set; }

        public string Gender { get; set; }
    }
}

Create a synchronous action filter in ASP.NET Core MVC


We need to implement the OnActionExecuting and OnActionExecuted methods to apply the synchronous Action filter that runs before and after the execution of the Action method.


- Right-click the project and select Add > Folder. Name the folder as ActionFilters


- Create a class named SimpleActionFilter


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

namespace ActionFilters.ActionFilters
{
    public class SimpleActionFilter : IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context)
        {
            //the code before action executes
            var temp = context.ActionArguments.SingleOrDefault(x => x.Value is Person);
            if (temp.Value == null)
            {
                context.Result = new BadRequestObjectResult("Object is null");
                return;
            }

            if (!context.ModelState.IsValid)
            {
                context.Result = new BadRequestObjectResult(context.ModelState);
                return;
            }

        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            ////the code after action executes
        }
    }
}

Action Filters Scope


The action filter can be added to different scope levels: Global, Action, Controller.


If you want to use the SimpleActionFilter filter globally, you need to register it in the AddControllers() method in the ConfigureServices method as shown below.


public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(config =>
    {
        config.Filters.Add(new SimpleActionFilter());
    });
}

If you want to use the SimpleActionFilter filter as a service type on the Action or Controller level, you need to register it in the ConfigureServices method as follows.


In our example, we will use the Action level.


- Add the following code snippet in the ConfigureServices method in the Startup.cs file


services.AddScoped<SimpleActionFilter>();

Finally, to use a filter registered on the Action or Controller level, you need to place it on top of the Controller or Action as a ServiceFilter:


In our example, we will use the Action level.


- Add a new API controller named PersonController in the Controllers folder.


ActionFilters-2.PNG

- Add the following code snippet in the ConfigureServices method in the Startup.cs file


using ActionFilters.ActionFilters;
using ActionFilters.Entities;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace ActionFilters.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class PersonController : ControllerBase
    {
        private static List<Person> people = new List<Person>
        {
            new Person { ID = 1, FirstName = "Mike", LastName = "Anderson", Gender = "Male" },
            new Person { ID = 2, FirstName = "Tom", LastName = "Donald", Gender = "Male" },
            new Person { ID = 3, FirstName = "Ricky", LastName = "Wasson", Gender = "Male" },
            new Person { ID = 4, FirstName = "Andy", LastName = "Anderson", Gender = "Male" }
        };


        [HttpPost]
        [ServiceFilter(typeof(SimpleActionFilter))]
        public IActionResult Post([FromBody]Person person)
        {
            int pID = people[people.Count - 1].ID + 1;
            person.ID = pID;
            people.Add(person);

            return CreatedAtRoute("PersonById", new { id = person.ID }, person);
        }

        [HttpGet("{id}", Name = "PersonById")]
        public IActionResult Get(int id)
        {
            Person person = people.Find(x => x.ID == id);
            return Ok(person);
        }
    }
}

The OnActionExecuted method runs after the action method.


- Start the project ans test the project with POSTMAN


ActionFilters-3.PNG

ActionFilters-4.PNG

ActionFilters-5.PNG

ActionFilters-6.PNG

ActionFilters-7.PNG

ActionFilters-8.PNG

Download the source code.