Переопределение ResourceFilter на контроллере одним из метода действия - PullRequest
0 голосов
/ 29 октября 2019

Я использую 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[]{"some value",
        "another value"}})]
public class MyController : Controller
{

}

Я хотел бы переопределить этот фильтр для определенногометод действия. Что-то вроде:

[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 () вызывается с экземпляром, свойства которого были переданы ватрибут на контроллере. Если я закомментирую фильтр контроллера, то увижу фильтр со значениями, которые я передал методу. Мой вопрос - есть ли способ сказать методу игнорировать фильтр контроллеров для этого конкретного маршрута и использовать вместо этого фильтр, определенный в атрибуте метода? Любой совет будет принят во внимание. Большое спасибо!

1 Ответ

1 голос
/ 30 октября 2019

Мой вопрос - есть ли способ сообщить методу игнорировать фильтр контроллеров для этого конкретного маршрута и использовать вместо него фильтр, определенный в атрибуте метода

Вы можете динамически изменитьcontext.Filters во время выполнения. Например,

  1. создать фильтр nope, который ничего не делает
    class NopeFilter : IResourceFilter
    {
        public void OnResourceExecuted(ResourceExecutedContext context) { }
        public void OnResourceExecuting(ResourceExecutingContext context) { }
    }
    
  2. проверить условие во время выполнения и заменить другие фильтры этого типа на 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)
        {
        }
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...