Passive Attributes
If we think about it, it does not make sense for action filter attributes to house complex logic and interactions with other components. Attributes are best for identification and by choosing which actions or controllers we belong to. They are also best for individual actions or configurations of controllers. They probably shouldn't be full of complex code.
The presence of a ThrottleAttribute on the action indicates that it should be throttled. This is an opt-in approach but we can easily use an opt-out approach where an attribute indicates that we do not want to throttle the action.
We also want to be able to alternately refer to maximum requests per second. Implementation is trivial:
public class ThrottleAttribute : Attribute, IFilterMetadata
{
public intMaxRequestPerSecond{ get; set; }
}
Note that we apply IFilterMetadata. This is a marker interface that makes it easier to read our attributes from the global filters.
The global action filter is registered with MVC in the same way as we showed at the beginning of the section. All dependencies are resolved automatically by the built-in IoC container.
public class ThrottleFilter :IActionFilter
{
private readonlyIDistributedCache _cache;
public ThrottleFilter(IDistributedCache cache)
{
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
}
public void OnActionExecuted(ActionExecutedContext context)
{
//noop
}
public void OnActionExecuting(ActionExecutingContext context)
{
varthrottleAttribute = context.ActionDescriptor.FilterDescriptors
.Select(x =>x.Filter).OfType().FirstOrDefault();
if (throttleAttribute != null)
{
}
}
}