| File: Filters\FilterContext.cs | Web Access |
| Project: src\aspnetcore\src\Mvc\Mvc.Abstractions\src\Microsoft.AspNetCore.Mvc.Abstractions.csproj (Microsoft.AspNetCore.Mvc.Abstractions) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; namespace Microsoft.AspNetCore.Mvc.Filters; /// <summary> /// An abstract context for filters. /// </summary> public abstract class FilterContext : ActionContext { /// <summary> /// Instantiates a new <see cref="FilterContext"/> instance. /// </summary> /// <param name="actionContext">The <see cref="ActionContext"/>.</param> /// <param name="filters">All applicable <see cref="IFilterMetadata"/> implementations.</param> public FilterContext( ActionContext actionContext, IList<IFilterMetadata> filters) : base(actionContext) { ArgumentNullException.ThrowIfNull(filters); Filters = filters; } /// <summary> /// Gets all applicable <see cref="IFilterMetadata"/> implementations. /// </summary> public virtual IList<IFilterMetadata> Filters { get; } /// <summary> /// Returns a value indicating whether the provided <see cref="IFilterMetadata"/> is the most effective /// policy (most specific) applied to the action associated with the <see cref="FilterContext"/>. /// </summary> /// <typeparam name="TMetadata">The type of the filter policy.</typeparam> /// <param name="policy">The filter policy instance.</param> /// <returns> /// <c>true</c> if the provided <see cref="IFilterMetadata"/> is the most effective policy, otherwise <c>false</c>. /// </returns> /// <remarks> /// <para> /// The <see cref="IsEffectivePolicy{TMetadata}(TMetadata)"/> method is used to implement a common convention /// for filters that define an overriding behavior. When multiple filters may apply to the same /// cross-cutting concern, define a common interface for the filters (<typeparamref name="TMetadata"/>) and /// implement the filters such that all of the implementations call this method to determine if they should /// take action. /// </para> /// <para> /// For instance, a global filter might be overridden by placing a filter attribute on an action method. /// The policy applied directly to the action method could be considered more specific. /// </para> /// <para> /// This mechanism for overriding relies on the rules of order and scope that the filter system /// provides to control ordering of filters. It is up to the implementor of filters to implement this /// protocol cooperatively. The filter system has no innate notion of overrides, this is a recommended /// convention. /// </para> /// </remarks> public bool IsEffectivePolicy<TMetadata>(TMetadata policy) where TMetadata : IFilterMetadata { if (policy == null) { throw new ArgumentNullException(nameof(policy)); } var effective = FindEffectivePolicy<TMetadata>(); return ReferenceEquals(policy, effective); } /// <summary> /// Returns the most effective (most specific) policy of type <typeparamref name="TMetadata"/> applied to /// the action associated with the <see cref="FilterContext"/>. /// </summary> /// <typeparam name="TMetadata">The type of the filter policy.</typeparam> /// <returns>The implementation of <typeparamref name="TMetadata"/> applied to the action associated with /// the <see cref="FilterContext"/> /// </returns> [return: MaybeNull] public TMetadata FindEffectivePolicy<TMetadata>() where TMetadata : IFilterMetadata { // The most specific policy is the one closest to the action (nearest the end of the list). for (var i = Filters.Count - 1; i >= 0; i--) { var filter = Filters[i]; if (filter is TMetadata match) { return match; } } return default; } }