ASP.NET Core – Disable an action filter for specific actions

Action filters can be added globally, per-controller, and for specific actions. When you add filters globally or per-controller, it applies the filter to multiple actions. This is convenient, but what if you want to add the filter for *most* actions, but not all of them? One way to do that is by disabling the filter for specific actions by using an IActionModelConvention attribute.

First, implement a generalized IActionModelConvention attribute that removes filters by name:

using Microsoft.AspNetCore.Mvc.ApplicationModels; using System; [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public class DisableActionFilterAttribute : Attribute, IActionModelConvention { private readonly string ActionFilterTypeNameToDisable; public DisableActionFilterAttribute(string actionFilterTypeName) { ActionFilterTypeNameToDisable = actionFilterTypeName; } public void Apply(ActionModel action) { //Search for the action filter and remove it for (var i = 0; i < action.Filters.Count; i++) { if (action.Filters[i].GetType().Name == ActionFilterTypeNameToDisable) { action.Filters.RemoveAt(i); return; } } } }
Code language: C# (cs)

Now apply this attribute to an action to remove one or more filters that you specify:

[ApiController] [Route("[controller]")] [LogStats] public class StocksController : ControllerBase { [HttpPost()] [DisableActionFilter("ModelStateInvalidFilterFactory")] //global action filter [DisableActionFilter(nameof(LogStats))] //controller-level action filter public IActionResult Post(Stock stock) { //do stuff return Ok(); } }
Code language: C# (cs)

Note: Use nameof() instead of hardcoding strings when possible.

As you can see, you can use this to disable action filters that were added at the controller-level and globally (including ones that were auto added like ModelStateInvalidFilterFactory).

Conventions only run once

You may be wondering, won’t adding the IActionModelConvention to my actions slow down my requests?

No, not really. The framework only runs these once during initialization. It doesn’t run them every time there’s a request. That would be inefficient.

Leave a Comment