C# 使用一个From Action方法重写控制器上的ResourceFilter

C# 使用一个From Action方法重写控制器上的ResourceFilter,c#,asp.net-mvc,asp.net-core,C#,Asp.net Mvc,Asp.net Core,我使用的是ASP.NET Core 2.2,我有一个ResourceFilter,它接受一些参数。我正在控制器上使用ResourceFilter。我想做的是在控制器中的特定操作上使用相同的过滤器类型和不同的参数 我有点像: public class MyRequestFilter : IResourceFilter { private readonly string[] _someValues; MyRequestFilter(string[] someValues)

我使用的是ASP.NET Core 2.2,我有一个ResourceFilter,它接受一些参数。我正在控制器上使用ResourceFilter。我想做的是在控制器中的特定操作上使用相同的过滤器类型和不同的参数

我有点像:

public class MyRequestFilter : IResourceFilter
{
    private readonly string[] _someValues;

    MyRequestFilter(string[] someValues)
    {
        _someValues = someValues;
    }

    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        // do some checks here using _someValues
    }
}

[TypeFilter(typeof(MyRequestFilter),
    IsReusable = false,
    Arguments = new object[] {
        new[]{"value for this action",
        "another value just for this action"}})]
public async Task<IActionResult> MyAction()
{

}
我在控制器上使用它,如:

[TypeFilter(typeof(MyRequestFilter),
    IsReusable = false,
    Arguments = new object[] {
        new[]{"some value",
        "another value"}})]
public class MyController : Controller
{

}
我想做的是在特定的操作方法上重写该过滤器。比如:

public class MyRequestFilter : IResourceFilter
{
    private readonly string[] _someValues;

    MyRequestFilter(string[] someValues)
    {
        _someValues = someValues;
    }

    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        // do some checks here using _someValues
    }
}

[TypeFilter(typeof(MyRequestFilter),
    IsReusable = false,
    Arguments = new object[] {
        new[]{"value for this action",
        "another value just for this action"}})]
public async Task<IActionResult> MyAction()
{

}
当我尝试上述操作并向操作绑定到的端点发出请求时,我看到MyRequestFilter.OnResourceExecuting被调用 具有已传递到控制器上属性的属性的实例。如果我注释掉控制器过滤器,那么 我看到过滤器带有我在方法上传入的值。我的问题是-有没有办法告诉方法忽略控制器过滤器 对于此特定路由,是否改为使用在方法属性上定义的筛选器?如有任何建议,将不胜感激。多谢

我的问题是-有没有办法告诉该方法忽略此特定路由的控制器过滤器,而使用在该方法的属性上定义的过滤器

您可以在运行时动态更改context.Filters。比如说,

创建一个不执行任何操作的nope筛选器
class NopeFilter : IResourceFilter
{
    public void OnResourceExecuted(ResourceExecutedContext context) { }
    public void OnResourceExecuting(ResourceExecutingContext context) { }
}
在运行时检查一个条件,并用NopeFilter替换此类型的其他过滤器。假设我们只想保留第一个,下面是一个实现:

public class MyRequestFilter : IResourceFilter
{
    // ... fields and constructor 

    // a helper method that will replace the extra MyRequestFilters with NopeFilter at runtime
    private void  DistinctThisTypeFilters(IList<IFilterMetadata> filters){
        var nopeFilter = new NopeFilter() ;
        var count = filters.Count();
        var thisTypeFilterCount = filters.OfType<MyRequestFilter>().Count();  // the total number: filters of this type 
        if(thisTypeFilterCount > 1){
            var alreadyReplaced = 0;  // the number that we have replaced till now
            for(var i = count -1 ; i > 0 ; i--){    // replace in reverse order
                var filter = filters[i];
                if(filter.GetType()== typeof(MyRequestFilter))
                {
                    if(alreadyReplaced < thisTypeFilterCount -1 ){
                        filters[i]= nopeFilter;
                        alreadyReplaced++;
                    }
                }
            }
        }
    }

    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        this.DistinctThisTypeFilters(context.Filters);  // add this line so that only the first one will take effect. 
        // do some checks here using _someValues
        ...
    }

    public void OnResourceExecuted(ResourceExecutedContext context)
    {
    }
}