【问题标题】:Execute global filter before controller's OnActionExecuting, in ASP.NET Core在 ASP.NET Core 中,在控制器的 OnActionExecuting 之前执行全局过滤器
【发布时间】:2018-04-18 19:59:24
【问题描述】:

在 ASP.NET Core 2.0 应用程序中,我试图在执行控制器的变体之前执行全局过滤器的 OnActionExecuting。预期的行为是我可以在全局之前准备一些东西并将结果值传递给控制器​​。但是,当前的行为是设计颠倒了执行顺序。

文档告诉我default order of execution

从 Controller 基类继承的每个控制器都包含 OnActionExecuting 和 OnActionExecuted 方法。这些方法包装了针对给定操作运行的过滤器:在任何过滤器之前调用 OnActionExecuting,在所有过滤器之后调用 OnActionExecuted。

这使我解释为控制器的OnActionExecuting 在任何过滤器之前执行。说得通。但是文档还通过实现IOrderedFilter 声明the default order can be overridden

我在过滤器中实现这一点的尝试是这样的:

public class FooActionFilter : IActionFilter, IOrderedFilter
{
    // Setting the order to 0, using IOrderedFilter, to attempt executing
    // this filter *before* the BaseController's OnActionExecuting.
    public int Order => 0;

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // removed logic for brevity
        var foo = "bar";

        // Pass the extracted value back to the controller
        context.RouteData.Values.Add("foo", foo);
    }
}

此过滤器在启动时注册为:

services.AddMvc(options => options.Filters.Add(new FooActionFilter()));

最后,我的 BaseController 看起来像下面的示例。这最好地解释了我想要实现的目标:

public class BaseController : Controller
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // The problem: this gets executed *before* the global filter.
        // I actually want the FooActionFilter to prepare this value for me.
        var foo = context.RouteData.Values.GetValueOrDefault("foo").ToString();
    }
}

Order 设置为 0,甚至是像 -1 这样的非零值,似乎对执行顺序没有任何影响。

我的问题:我可以做些什么来让我的全局过滤器执行OnActionExecuting之前(基本)控制器的OnActionExecuting

【问题讨论】:

  • 根据文档,我想说Order 属性只能用于覆盖过滤器的默认顺序,并且该属性不会影响控制器方法和过滤器的顺序。跨度>

标签: c# asp.net-core .net-core action-filter


【解决方案1】:

你快到了。您的小错误是控制器过滤器执行的默认顺序不是0。此顺序在ControllerActionFilter 类中定义为int.MinValue (source code):

public class ControllerActionFilter : IAsyncActionFilter, IOrderedFilter
{
    // Controller-filter methods run farthest from the action by default.
    /// <inheritdoc />
    public int Order { get; set; } = int.MinValue;

    // ...
}

因此,您应该对当前代码进行的唯一更改是将FooActionFilter.Order 设置为int.MinValue

public class FooActionFilter : IActionFilter, IOrderedFilter
{
    public int Order => int.MinValue;

    //  ...
}

现在FooActionFilterControllerActionFilter 具有相同的顺序。但是FooActionFilter 是全局过滤器,而ControllerActionFilter 是控制器级过滤器。这就是为什么FooActionFilter 将首先执行,基于this statement

在确定过滤器的运行顺序时,Order 属性胜过范围。过滤器首先按顺序排序,然后使用范围打破关系

【讨论】:

  • 就是这样,@CodeFuller!非常感谢。
  • @CodeFuller 异步操作过滤器是否也需要此 order 属性?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多