ASP.NET Web API缓存跨请求的动作过滤器属性 [英] ASP.NET Web API caches action filter attributes across requests

查看:142
本文介绍了ASP.NET Web API缓存跨请求的动作过滤器属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ASP.NET Web API(4.0.30506)中似乎有一些奇怪的行为,我以前没有见过。

There seems to be some weird behavior in ASP.NET Web API (4.0.30506) that I haven't witnessed before.

我看到的是相同的动作过滤器属性实例被重用于Web API请求。这是特别是一个问题,如果这个属性获得依赖注入到它,因为这些依赖可能是特定于Web请求。我知道更好的属性是被动的,但我的假设是这样的行动过滤属性,而不是缓存。

What I'm seeing is that the same action filter attribute instance is reused over Web API requests. This is especially a problem in case this attribute gets dependencies injected to it, since those dependencies might be specific to the web request. I'm aware that it's better for attributes to be passive, but my assumption was that action filter attributes where not cached.

我搜索了任何文章,博客文章或Microsoft更改描述此信息的原因及其背后的原因,但我找不到一个事情。这使我想知道我的配置是否有问题导致这种情况发生。然而,事实上,我可以在一个新的和空的Visual Studio 2012 Web API项目中重现这个问题。

I searched for any articles, blog posts or Microsoft change logs that described this and the reason behind this, but I couldn't find a single thing. That makes me wonder whether there is something wrong with my configuration that makes this happening. Thing is however, that I'm able to reproduce this issue in a new and empty Visual Studio 2012 Web API project.

我所做的是创建一个新的空项目,使用具有Web API模板的Visual Studio 2012 ASP.NET MVC 4 Web应用程序项目。它附带了Web API 4.0.20710.0 NuGet软件包。之后,我添加了以下属性:

What I did was create a new empty project using the Visual Studio 2012 ASP.NET MVC 4 Web Application project with the "Web API" template. It comes with the Web API 4.0.20710.0 NuGet package. After that I added the following attribute:

[DebuggerDisplay("{id}")]
public class TestFilterAttribute : System.Web.Http.Filters.ActionFilterAttribute {
    private static readonly List<int> used = new List<int>();

    private static int counter;
    private readonly int id;

    public TestFilterAttribute() {
        this.id = Interlocked.Increment(ref counter);
    }

    public override void OnActionExecuting(HttpActionContext actionContext) {
        // Just for testing: I would expect this line never to throw, but it does.
        if (used.Contains(this.id)) throw new Exception("WAT?");
        used.Add(this.id);
        base.OnActionExecuting(actionContext);
    }
}

我将此属性添加到 ValuesController (默认模板的一部分):

And I add this attribute to the ValuesController (part of the default template):

public class ValuesController : ApiController {
    // GET api/values
    [TestFilterAttribute]
    public IEnumerable<string> Get() {
        return new string[] { "value1", "value2" };
    }

    // ...
}

现在,当我启动项目,浏览器中的/ api /值,刷新该页面几次,WAT?抛出异常。

Now when I start the project, go to the /api/values in the browser and refresh that page a few times, the "WAT?" exception is thrown.

这是Web API的正常行为,如果是这样,这是什么原因?还是我想过一些关于这个变化的备忘录?这是否使Web API属性不适合进行依赖注入?或者我正在做错事?

Is this normal behavior of Web API and if so, what's the reasoning about this? Or Did I miss some memo about this change somewhere? Does this make Web API attributes extra unsuited for doing dependency injection? Or am I'm doing something wrong?

推荐答案

Web API 建立在 MVC ,因此它使用了很多功能。

Web API is built on top of MVC, thus it uses a lot of it's functionality.

属性实例可重用性是由MVC 3引入的积极缓存的一部分的。这意味着相同的属性实例将很可能与所应用的所有操作一起使用。 MVC 管道将尽力以 Singleton 的方式对待您的属性类。

Attribute instance re-usability is part of the aggressive caching introduced by MVC 3. This means that the same Attribute instance will most likely be used with all the Actions it is applied on. MVC pipeline will do it's best at trying to treat your Attribute class like a Singleton.

因为相同的属性 实例被重用, em>不被调用,并且 id 不增加。例如,如果您在 OnActionExecuting 内增加 id ,则所有内容都可以正常运行。

Because the same Attribute instance is reused, it's Constructor is not called and id is not incremented. If, for example, you increment id inside OnActionExecuting, all will work well.

您还可以使用属性执行所需的所有操作。您只需要记住,您不能保证始终获得创建的新的实例

You can still do everything you want with your Attribute. You only need to keep in mind that you are not guaranteed to always get a new instance created. The constructor shouldn't contain anything but initial initialization.

public TestFilterAttribute() {
    // Instance will be reused thus this will not be called for each Action
}

public override void OnActionExecuting(HttpActionContext actionContext) {
    // Called on each Action
}

这篇关于ASP.NET Web API缓存跨请求的动作过滤器属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆