【问题标题】:same action filter on different action不同动作的相同动作过滤器
【发布时间】:2014-01-09 01:41:08
【问题描述】:

我正在实现一个从 AuthorizeAttribute 继承的自定义授权过滤器。经过我的研究,我发现动作过滤器被缓存了,所以它们只被实例化一次。

这是我的问题。如果我实现并使用如下所示的自定义操作过滤器,它应该无法正常工作,因为它会被实例化一次并且永远不会再次调用构造函数。但是当我测试时,效果很好,所以我在想有些东西我不知道。

谁能解释清楚(动作过滤器生命周期?)?

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
  private readonly string value = string.Empty;

  public CustomAuthorizeAttribute(string value)
  {
     this.value = value;
  }

  protected override bool AuthorizeCore(HttpContextBase httpContext)
  {
     // Do something with this.value
  }
}

public class HomeController : Controller
{
  [CustomAuthorize("ACCESS_INDEX")]
  public ActionResult Index()
  {
  }

  [CustomAuthorize("ACCESS_LOGIN")]
  public ActionResult Login()
  {
  }
}

【问题讨论】:

  • 您使用的是哪个版本的 MVC?
  • @thepirat000 这是 mvc3。
  • 在 CustomAuthorizeAttribute 构造函数上放置一个断点,您将看到它被调用两次,用于两个操作,即 Index 和 Login,但任何后续对 Index 和 Login 的请求都不会达到断点,因为缓存了操作过滤器,因此它们被每个控制器操作缓存,或者您可以说如果您在 10 个操作处使用操作属性,那么该操作属性将最多有 10 个实例。

标签: asp.net-mvc lifecycle actionfilterattribute custom-action-filter


【解决方案1】:

不要这样做。

根据我自己的经验,在 Action 上使用私有变量并不可靠,即使它有时看起来有效,您最终也可能会得到一些不确定的结果。

请注意,您的代码可能适用于 1 个请求,但在同时处理多个请求时根本不起作用。

此用户的问题是声称与您完全相反的体验:How to use ActionFilterAttribute to log running times?

我唯一的解释是,如果 Action Invoker 实例化了动作过滤器,并且要么:它不会将其保留很长时间,要么它会创建一个实例池(或两者兼而有之)。

我有一个原型,它将上下文作为私有操作属性,它偶尔会(不是每次)抛出与并发使用相关的 EF 错误(这是 EF 的一个问题。 )

这告诉我,我的操作被同时使用了不止一次。

我建议将他们的操作集中在使用过滤器上下文。过滤器上下文包含此请求当前正在发生的所有事情。在 MVC 中,您可以利用 filterContext.HttpContext.Items 来存储用于此特定请求的项目。 (见Accessing Action Filter's data in Controller Action

最后,不同版本的 MVC 框架也可能会以不同的方式优化操作过滤器的生命周期。

几个关于该主题的有用链接:

关于一般 MVC 生命周期的一些细节 http://blog.christopheargento.net/2012/06/11/detailed-life-cycle-of-an-asp-net-mvc-request/

在谈到如何创建动态操作过滤器(以编程方式即时插入和更改)时,Dino Esposito 研究了正在发生的事情的一些不足之处 https://msdn.microsoft.com/en-us/magazine/gg309182.aspx

自定义操作过滤器和多个存在时的过滤器顺序 http://www.asp.net/mvc/overview/older-versions/hands-on-labs/aspnet-mvc-4-custom-action-filters

【讨论】:

    【解决方案2】:

    这个网站对 MVC 中的页面生命周期有一个非常好的概述

    http://blogs.msdn.com/b/varunm/archive/2013/10/03/understanding-of-mvc-page-life-cycle.aspx

    您的测试显示过滤器一直在运行的原因是,当从 URL MVC 调用路由时,会将其与控制器匹配,然后在该控制器中执行操作。找到一个动作 MVC 看到上面有一个动作过滤器,并将首先执行动作过滤器。如果在同一控制器中同时调用两个操作(来自两个不同的 Web 用户),则会调用控制器的两个唯一实例,因此一个实例不知道另一个实例已运行过滤器。

    【讨论】:

    • 感谢您的回答,但我不明白您的意思,也无法从该链接中找到我的问题的任何线索(虽然这是一篇好文章。)无论如何我的问题与生命周期无关控制器,它是关于动作过滤器的生命周期。我所知道的是动作过滤器被缓存,所以它只被实例化一次。 (这意味着它的构造函数只被调用一次,所以内部变量不能改变。)这是我理解的,但我的测试证明它是错误的。那我错过了什么?
    • 据我所知,过滤器没有缓存在客户端,代码被编译并且编译的代码被缓存,就像控制器代码一样,但是变量在过滤器之后被处理掉执行完毕。
    猜你喜欢
    • 1970-01-01
    • 2014-09-21
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 2017-08-10
    相关资源
    最近更新 更多