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

查看:230
本文介绍了跨请求的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.

我所做的是使用的的Visual Studio 2012 ASP.NET MVC 4 Web应用程序的项目网络API模板创建一个新的空项目。它配备了网络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);
    }
}

和我加入这个属性的 Values​​Controller (默认模板的一部分):

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?

推荐答案

网络API 的是建立在顶部的 MVC 的,因此它使用了大量的它的功能。

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

属性实例可重用性是通过的 MVC 3 的推出了积极的缓存的一部分。这意味着同样的属性比如将最有可能与所有的用动作它应用于。 MVC 的管道将做到这一点,最好在试图威胁就像一个辛格尔顿属性类。

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 threat your Attribute class like a Singleton.

由于相同的属性实例的重复使用,它的的构造的不叫和 ID 不会增加。如果,例如,你增加 ID OnActionExecuting ,都将工作做好。

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天全站免登陆