c# - 在ASP.NET Core中在 Controller OnActionExecuting之前执行全局过滤器

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

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

该文档告诉我有关default order of execution的信息:

Every controller that inherits from the Controller base class includes OnActionExecuting and OnActionExecuted methods. These methods wrap the filters that run for a given action: OnActionExecuting is called before any of the filters, and OnActionExecuted is called after all of the filters.



这使我解释说, Controller 的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),似乎都不会对执行顺序产生任何影响。

我的问题:我该怎么做才能使全局过滤器在(Base)Controller的OnActionExecuting之前执行OnActionExecuting

最佳答案

你快到了。您的小错误是 Controller 过滤器执行的默认顺序不是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是 Controller 级过滤器。这就是为什么基于this statement首先执行FooActionFilter的原因:

The Order property trumps scope when determining the order in which filters will run. Filters are sorted first by order, then scope is used to break ties.

关于c# - 在ASP.NET Core中在 Controller OnActionExecuting之前执行全局过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49908073/

相关文章:

c# - 显示来自 Reporting Services 的 PDF

C#奎因问题

c# - WCF 和日期时间解析?

c# - 由缓慢的客户端引起的 BadHttpRequestException 出现在我的应用程序见解中

.net - 在ASP.NET Core网站中使用Reporting Services(SSRS)作为引用

c# - dotnet core/corefx 中是否有与 HtmlTextWriter 等效的类?

c# - Xamarin.iOS 上的 sqlite 中的缓慢 SELECT

iis - Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException : Request body too large

c# - 如何修复代码以便 C# 中的斐波那契搜索算法正常​​工作

c# - 如何在 Blazor 服务器应用程序中访问 WCF 服务