【问题标题】:ASP.NET MVC ActionFilter is not preventing other filters from runningASP.NET MVC ActionFilter 不会阻止其他过滤器运行
【发布时间】:2014-03-31 22:18:29
【问题描述】:

我到处读到将 context.Result 设置为非空值会阻止同一类中的其他过滤器运行,但它对我来说不起作用。以下导致两个过滤器之间的重定向循环:

Global.asax,在Application_Start()

GlobalFilters.Filters.Add(new FilterA(), 1);
GlobalFilters.Filters.Add(new FilterB(), 2);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

过滤器A:

public class FilterA : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (long thing that evaluates to true)
        {
            context.Result = new RedirectResult("~/Foo/Bar");
        }
    }
}

过滤器B:

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),但这似乎并不重要。

【问题讨论】:

  • 我认为,这些过滤器将评估 Foo/Bar 和 Foo/Baz 的 false ...否则您将处于重定向循环中
  • 我不确定你的意思。过滤器不评估任何东西。两个 if 语句都评估为 true,并且为两者设置了 context.Result。该逻辑是正确的,但是只有一个过滤器应该运行,而第二个不应该运行,这会导致重定向循环。根据我的阅读,FilterA 设置 Result 应该会阻止 FilterB 运行。
  • 我不确定过滤器是否正在运行,但它会停止执行操作。您是否尝试过在每个过滤器上添加测试以查看结果是否不为空,然后从过滤器返回?

标签: c# asp.net-mvc asp.net-mvc-5 action-filter


【解决方案1】:

这可能会导致重定向循环,因为您在过滤器中的逻辑未排除对"Foo/Bar""Foo/Baz" 的请求。基本上在FilterA 上设置结果会阻止其他过滤器在该请求中运行 并返回重定向,但FilterB 会在next 请求之后执行重定向。

以下内容适用于新的 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的循环,然后新请求被重定向到~/Foo/BazFilterB拦截,~/Foo/Baz将再次被FilterA拦截等等。

例如,如果您使用这些过滤器创建一个新的 MVC5 应用程序,如果您转到 ~/,您将被 FilterA 重定向到 ~/Foo/Bar。但是,如果您转到~/Account/Login,您将被FilterB 重定向到~/Foo/Baz

希望对你有帮助!

【讨论】:

  • 我实际上是自己想出来的,但这正是我的困惑所在。谢谢! :)
猜你喜欢
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-17
  • 1970-01-01
相关资源
最近更新 更多