In ASP.NET Core MVC, Result Filters allow you to execute logic before or after the action result is executed and returned to the client. These filters are particularly useful for tasks like logging, modifying the response, or adding custom headers.
Result filters can be applied globally, at the controller level, or to specific action methods.
Types of Result Filters
There are two types of result filters in ASP.NET Core:
1. Synchronous Result Filter
Implemented by the IResultFilter interface, it contains two methods:
OnResultExecuting(ResultExecutingContext context)
Executed before the result is processed. You can modify the result or short-circuit the pipeline.OnResultExecuted(ResultExecutedContext context)
Executed after the result has been processed. Commonly used for logging or cleanup logic.
2. Asynchronous Result Filter
Implemented by the IAsyncResultFilter interface, it contains one method:
OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
Allows asynchronous logic before and after the result execution by usingawait next().
💡 Important: Result filters are only executed for successful results, meaning they are skipped if an exception is thrown and not handled.
When to Use Result Filters
Use result filters when you need to:
- Modify the response (e.g., headers)
- Log output-related metadata
- Perform actions before or after the response is sent to the client
Let’s Get Started

To Create Sync Result filters, we need to implement the IResultFilter interface.
Implementation
using Microsoft.AspNetCore.Mvc.Filters;
using System;
namespace WebApplication4.Filters
{
public class CustomResultFilterAttribute : Attribute, IResultFilter
{
public void OnResultExecuted(ResultExecutedContext context)
{
}
public void OnResultExecuting(ResultExecutingContext context)
{
}
}
}
Let’s create a Custom ResultFilter with name CustomResultFilterAttribute and we are going to inherit it with Attribute class and IResultFilter interface and implement OnResultExecuted and OnResultExecuting method and in OnResultExecuting method, we are going to add headers to a page with the name MyPageHeader.
Code Snippet of CustomResultFilterAttribute
using Microsoft.AspNetCore.Mvc.Filters;
using System;
namespace WebApplication4.Filters
{
public class CustomResultFilterAttribute : Attribute, IResultFilter
{
public void OnResultExecuted(ResultExecutedContext context)
{
if (context.Exception == null)
{
}
}
public void OnResultExecuting(ResultExecutingContext context)
{
var headerName = "MyPageHeader";
context.HttpContext.Response.Headers.Add(headerName, new string[] { "MyPageHeader" });
}
}
}
How to Apply Filter on Controller
using System;
using Microsoft.AspNetCore.Mvc;
using WebApplication4.Filters;
namespace WebApplication4.Controllers
{
[TypeFilter(typeof(CustomResourceFilter))]
public class DefaultController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
View after adding the header

IAsyncResultFilter
The asynchronous version of the result filter to use Result filters, we need to implement the IAsyncResultFilter interface.
IAsyncResultFilter has 1 method in it OnResultExecutionAsync in this method we are going to add a header. After adding a header, we are going to execute the action method and see if we have any exception in it if yes then we have set ResultExecutedContext.Cancelled to true then action result execution was short-circuited by another filter.
Implementation
using Microsoft.AspNetCore.Mvc.Filters;
using System.Threading.Tasks;
namespace WebApplication4.Filters
{
public class CustomAsyncResultFilterAttribute : IAsyncResultFilter
{
public Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
throw new System.NotImplementedException();
}
}
}
Code Snippet of CustomAsyncResultFilterAttribute
using Microsoft.AspNetCore.Mvc.Filters;
using System.Threading.Tasks;
namespace WebApplication4.Filters
{
public class CustomAsyncResultFilterAttribute : IAsyncResultFilter
{
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
var headerName = "MyPageHeader";
context.HttpContext.Response.Headers.Add(headerName, new string[] { "MyPageHeader" });
ResultExecutedContext resultContext = await next();
if (resultContext.Exception != null)
{
resultContext.ExceptionHandled = true;
resultContext.Canceled = true;
}
}
}
}
How to Apply Filter on Controller
using System;
using Microsoft.AspNetCore.Mvc;
using WebApplication4.Filters;
namespace WebApplication4.Controllers
{
[TypeFilter(typeof(CustomAsyncResultFilterAttribute))]
public class DefaultController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
Conclusion
Result Filters in ASP.NET Core MVC give you control over the processing of the action result. Whether you’re working with the synchronous (IResultFilter) or asynchronous (IAsyncResultFilter) version, these filters are powerful tools for injecting logic into the result pipeline.
Key Points:
- Use
IResultFilterfor sync logic withOnResultExecutingandOnResultExecuted. - Use
IAsyncResultFilterfor async logic withOnResultExecutionAsync. - Filters apply only to successful responses.
- Apply filters globally, to a controller, or to specific actions.
Let me know if you’d like a downloadable PDF version or want to explore global filter registration and filter ordering.