Steven Steven - 1 year ago 88
ASP.NET (C#) Question

ASP.NET Web API caches action filter attributes across requests

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

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.

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.

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:

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() { = 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( throw new Exception("WAT?");

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

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

// ...

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.

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?

Answer Source

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

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.

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
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download