ASP.NET MVC ActionFilter не препятствует работе других фильтров
Я везде читаю этот установочный контекст.Результат к ненулевому значению предотвратит запуск других фильтров в том же классе, но это не работает таким образом для меня. В результате возникает цикл перенаправления между двумя фильтрами:
Глобальный.asax, in Application_Start()
:
GlobalFilters.Filters.Add(new FilterA(), 1);
GlobalFilters.Filters.Add(new FilterB(), 2);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
FilterA:
public class FilterA : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (long thing that evaluates to true)
{
context.Result = new RedirectResult("~/Foo/Bar");
}
}
}
FilterB:
public class FilterB : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (...also true, but shouldn't run...)
{
context.Result = new RedirectResult("~/Foo/Baz");
}
}
}
Должно быть, я что-то упустил... Я пробовал запускать base.OnActionExecuting(context)
как до, так и после того, как я установил результат, но это, кажется, не имеет значения.1 ответ:
Это приводит к циклу перенаправления, вероятно, потому, что ваша логика в фильтрах не исключает запросов для
"Foo/Bar"
и"Foo/Baz"
. В основном установка результата наFilterA
предотвращает запуск другого фильтра в этом запросе и возвращает перенаправление, ноFilterB
выполняется на следующем запросе после перенаправления.Следующее работает для меня в новом приложении MVC5:
public class FilterA : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { if (!context.RouteData.GetRequiredString("controller").Equals("account", StringComparison.CurrentCultureIgnoreCase) //long condition evaluating to true //logic controlling these filters dont apply to Foo/Bar and Foo/Baz && (!context.RouteData.GetRequiredString("controller").Equals("Foo", StringComparison.CurrentCultureIgnoreCase) || (!context.RouteData.GetRequiredString("action").Equals("Bar", StringComparison.CurrentCultureIgnoreCase) && !context.RouteData.GetRequiredString("action").Equals("Baz", StringComparison.CurrentCultureIgnoreCase)) ) ) { context.Result = new RedirectResult("~/Foo/Bar"); } } } public class FilterB : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { if (true /*long condition evaluating to true*/ //logic controlling these filters dont apply to Foo/Bar and Foo/Baz && (!context.RouteData.GetRequiredString("controller").Equals("Foo", StringComparison.CurrentCultureIgnoreCase) || (!context.RouteData.GetRequiredString("action").Equals("Bar", StringComparison.CurrentCultureIgnoreCase) && !context.RouteData.GetRequiredString("action").Equals("Baz", StringComparison.CurrentCultureIgnoreCase)) ) ) { context.Result = new RedirectResult("~/Foo/Baz"); } } }
Я добавил некоторую логику (возможно, вы захотите ее рефакторировать) для обоих фильтров, которые удостоверяются, что текущий контроллер не является контроллером
Это должно предотвратить цикл, в котором фильтрFoo
, или в случае, если текущий контроллер являетсяFoo
, то действия могут отличаться отBar
иBaz
.FilterA
перенаправляет на~/Foo/Bar
, затем новый запрос перехватываетсяFilterB
, который перенаправляет на~/Foo/Baz
, который будет снова перехваченFilterA
и так далее.В качестве примера, если вы создадите новое приложение MVC5 с этими фильтрами, если вы перейдете к
~/
, вы перенаправлены на~/Foo/Bar
черезFilterA
. Однако если вы перейдете к~/Account/Login
, вы будете перенаправлены на~/Foo/Baz
поFilterB
.Надеюсь, это поможет!