2014-03-31 39 views
3

我在任何地方都能看到设置context.Result为非null值将会阻止同一个类中的其他过滤器运行,但它不适用于我。在两个过滤器之间的重定向循环的结果如下:ASP.NET MVC ActionFilter并没有阻止其他过滤器运行

Global.asax中,在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) Resu但它似乎并不重要。

+0

我会假设,这些过滤器将为Foo/Bar和Foo/Baz评估false ...否则您将处于重定向循环 –

+0

我不确定你的意思。过滤器不计算任何东西。 if语句的结果均为true,并为两者设置context.Result。该逻辑是正确的,但是只有一个过滤器应该运行,而第二个过滤器不应该,这导致了重定向循环。从我读到的,FilterA设置结果应该阻止FilterB运行。 – Josh

+0

我不确定运行的过滤器,但它会停止执行的动作。您是否曾尝试在每个过滤器上添加一个测试,以查看结果是否为空,然后从过滤器返回? – Slicksim

回答

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的情况下,则动作可能不同于BarBaz

这应该防止一个循环,过滤FilterA重定向到~/Foo/Bar,那么新的请求被FilterB重定向到~/Foo/Baz这将再次通过FilterA等被拦截拦截。例如,如果您使用这些过滤器创建新的MVC5应用程序,如果您转到~/,您将被重定向到~/Foo/BarFilterA。但是,如果您转到~/Account/Login,则会被FilterB重定向到~/Foo/Baz

希望它有帮助!

+0

我其实是自己想出来的,但这正是我的困惑所在。谢谢! :) – Josh