A result filter runs immediately before and after an MVC action result (`IActionResult`) executes. Use one when you need to adjust how a result produces a response, rather than change the action’s business logic. Result filters are part of the MVC and Razor Pages filter pipeline, not the general middleware pipeline. section 22.1.5 section 21.1 section 21.3
For a synchronous filter, implement `IResultFilter` or derive from `ResultFilterAttribute`. Put work that must happen before result execution in `OnResultExecuting`; the corresponding executed method runs afterward. Choose the asynchronous interface, `IAsyncResultFilter`, if the filter needs asynchronous calls. Do not implement both interfaces: only the asynchronous one will be used. section 21.4 section 22.1.5
Add a Last-Modified header
Suppose an API action returns an `OkObjectResult` containing a detail view model with a `LastModified` value. In `OnResultExecuting`, check both the result type and its value, then set `context.HttpContext.Response.GetTypedHeaders().LastModified` from that value. The checks keep the filter from assuming every action returns the same object. section 22.1.5
Listing 22.9 Setting a response header in a result filter
public class AddLastModifedHeaderAttribute : ResultFilterAttribute #1
{
public override void OnResultExecuting( #2
ResultExecutingContext context) #2
{
if (context.Result is OkObjectResult result #3
&& result.Value is RecipeDetailViewModel detail) #4
{
var viewModelDate = detail.LastModified; #5
context.HttpContext.Response #5
.GetTypedHeaders().LastModified = viewModelDate; #5
}
}
}
The listing shows the result-type checks and header assignment inside `OnResultExecuting`. section 22.1.5
Built-in result filters offer other uses: `ProducesAttribute` specifies an API output format, while `FormatFilterAttribute` selects a format from a route value or `format` query parameter. XML output also requires XML formatters to be configured. section 22.1.5
Watch for short-circuits. If an authorization, resource, or exception filter supplies the result, an ordinary result filter does not run; use `IAlwaysRunResultFilter` when its transformation must also apply to those results. An action or page filter that skips its handler still allows result filters to run. Exception filters do not catch exceptions thrown by result filters. section 22.2 section 22.1.4

