When a user tries to access a page, sometimes we want to run checks before the action executes. For example: is the product in stock, is the user active, is the membership valid?
Instead of repeating those checks inside every action, we use an Action Filter.
An Action Filter is an intermediate control layer that runs before the controller action executes.
Now imagine a different example. In a cafe system, a customer wants to place a coffee order from a screen.
But some drinks may be out of stock. Before the user enters the order page, the system wants to check whether the selected product is available.
If stock exists, the request continues. If not, the user is redirected directly to the OutOfStock page instead of opening a useless form.
Instead of writing this check inside every action, we can centralize it with a filter.
Suppose you have multiple actions such as create order, quick order, discounted order, and mobile order. Repeating the same stock check in all of them makes the code longer.
And if the rule changes one day, you would need to update all of them one by one.
With a filter, you place the rule in one location. That reduces repetition and makes the code easier to read.
In the example below, the filter reads the incoming productId value from the action. Then it asks the stock service: “Is this product currently available?”
If the product is unavailable, it redirects the user. Otherwise, it allows the action to run.
public class RequireStockFilter : IAsyncActionFilter
{
private readonly IStockService _stockService;
public RequireStockFilter(IStockService stockService)
{
_stockService = stockService;
}
public async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
var productId = context.ActionArguments["productId"] as int?;
if (productId.HasValue)
{
var hasStock = await _stockService
.HasStockAsync(productId.Value);
if (!hasStock)
{
context.Result = new RedirectToActionResult(
"OutOfStock",
"Shop",
null);
return;
}
}
await next();
}
}
One of the most important ideas in a filter is this: if you assign context.Result, the action no longer executes.
In other words, the system says: “The rest is cancelled, I have already decided the result.”
We use that behavior to redirect the user when the product is out of stock.
context.Result = new RedirectToActionResult(
"OutOfStock",
"Shop",
null);
return;
This is where the real power of the filter appears. Once attached to the controller, the relevant actions automatically pass through that rule.
That means you no longer need to repeat the stock-check logic inside each action.
[ServiceFilter(typeof(RequireStockFilter))]
public class OrderController : Controller
{
[HttpGet]
public IActionResult Create(int productId)
{
return View();
}
}
Here, when the user tries to access the Create action, the filter runs first. If the product is valid, the action opens; otherwise, the user is redirected.
When writing an Action Filter, it is not enough for it to merely work technically. Its purpose should also be easy to understand.
A good filter centralizes repeated checks and keeps the controller clean.