
Filters in ASP.NET Core offer an advantage if you use it properly. As a matter of fact, there's built-in filters that handle tasks such as: Authorization and Response caching. Custom filters can also be created to handle cross-cutting concerns like error handling, caching, configuration, authorization, and logging.
Not all filter executes at the same in the filter pipeline but each filter type is executed at a different stage. As you can see at the image below: Authorization filters run first followed by Resource filters and so on and so forth.

In this post, I'll guide you step by step on how to create basic action filter that checks if the id is already exist inside our record.
IAsyncActionFilter
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace ActionFilterSampApp
{
public class PersonIdFilter : IAsyncActionFilter
{
private readonly RecordDbContext recordDbcontext;
public PersonIdFilter(RecordDbContext recordDbcontext)
{
this.recordDbcontext = recordDbcontext;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
try
{
if (context.ActionArguments.ContainsKey("id"))
{
var id = (int)context.ActionArguments["id"];
var person = await recordDbcontext.Person.FirstOrDefaultAsync(x => x.PersonId == id);
if (person == null) {
context.Result = new NotFoundResult();
return;
}
}
await next();
}
catch (Exception e)
{
context.Result = new BadRequestObjectResult($"Something went wrong. {e.Message}");
return;
}
}
}
}
In the code example above, we are using the IAsyncActionFilter
but if you're working with synchronous, you can use the IActionFilter
interface.
IAsyncActionFilter
has only one require method which is the OnActionExecutionAsync
compare to IActionFilter
which has 2 contracts that need to be implemented. These are the OnActionExecuted
: a method before action executes and the OnActionExecuted
: after the action executes.
services.AddScoped<PersonIdFilter>();
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
[ServiceFilter(typeof(PersonIdFilter))]
public async Task<IActionResult> Get(int id)
{
// do something...
}
[ServiceFilter(typeof(PersonIdFilter))]
public async Task<IActionResult> Put(int id)
{
// do something...
}
}
Depending on your requirement: You can also create the other filters and use it above your controller so that filter can be automatically applied to its methods.
I hope this post helps you. Have a good day!