65

I am using ASP.NET MVC 4 with WEB API

I have the following action, in the action shown below, my service method makes a db call to DoMagic() method and returns an integer value which I am then using on every page, this action is called using an ajax call.

Below is my WEB API action :

[OutputCache(Duration = 86400, VaryByParam = "none")]
[ActionName("GetMyMagicNumber")]
public int GetMyMagicNumber()
{
    if (WebSecurity.IsAuthenticated)
    {
        var revenue = _magicService.DoMagic();
        return revenue;
    }
    return 0;
}

My question : I haved tried using [OutputCache(Duration = 86400, VaryByParam = "none")] and I excepted that only the first time the db call will be made and next subsequent request to this action will return me the cached value, but this is not happening.

A db call is again made, the db call takes time how do I get this working ?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Yasser Shaikh
  • 46,934
  • 46
  • 204
  • 281

4 Answers4

61

Unfortunately, caching is not built into ASP.NET Web API.

Check this out to get you on track: http://www.strathweb.com/2012/05/output-caching-in-asp-net-web-api/

An updated resource here: https://github.com/filipw/AspNetWebApi-OutputCache

EDIT: As of 2020-02-03, even though this answer is quite old, it's still valid.

Both of the URL's above lead to the same project, ASP.NET Web API CacheOutput by Filip W

OakNinja
  • 2,326
  • 18
  • 20
  • broken link, do update the answer with necessary information – Pranesh Janarthanan Apr 13 '19 at 04:32
  • @pranesh-janarthanan what link is broken? Both works for me. Maybe you’re be behind a corporate firewall? – OakNinja Apr 13 '19 at 08:44
  • 1
    this morning when i attempted to open the first link strathweb, it responded with an error, I good practice in answer with code instead of specifying reference link only. – Pranesh Janarthanan Apr 13 '19 at 09:07
  • 1
    @PraneshJanarthanan I agree, but it's not good practice to answer by posting thousands of lines of code from a bunch of files in an open source github project. – OakNinja Jun 06 '20 at 21:59
  • @OakNinja not a very constructive comment. It's generally a bad practice to answer with links for the very reason that Pranesh provided. Please provide code snippets that demonstrate the usage of this tool to solve the OP's problem and avoid link-only answers in the future. – BLAZORLOVER Oct 20 '20 at 16:44
  • 1
    If the GitHub repo is taken down and the library is removed from the Visual Studio Marketplace, a snippet would do no good. And since the question is a general one, a snippet would soon be outdated since it won’t automatically change as the official documentation evolves. While I generally agree, this is a typical case where a snippet add no value at all. – OakNinja Oct 20 '20 at 20:08
38

Add a reference to System.Runtime.Caching in your project. Add a helper class :

using System;
using System.Runtime.Caching;


public static class MemoryCacher
{
    public static object GetValue(string key)
    {
        MemoryCache memoryCache = MemoryCache.Default;
        return memoryCache.Get(key);
    }

    public static bool Add(string key, object value, DateTimeOffset absExpiration)
    {
        MemoryCache memoryCache = MemoryCache.Default;
        return memoryCache.Add(key, value, absExpiration);
    }

    public static  void Delete(string key)
    {
        MemoryCache memoryCache = MemoryCache.Default;
        if (memoryCache.Contains(key))
        {
            memoryCache.Remove(key);
        }
    }
}

Then from your code get or set objects in the cache :

list = (List <ChapterEx>)MemoryCacher.GetValue("CacheItem1");

and

MemoryCacher.Add("CacheItem1", list, DateTimeOffset.UtcNow.AddYears(1));
Sagi
  • 981
  • 11
  • 15
  • Downvoting because the original question was about HTTP caching, not in-memory caching on the server side (hence the `http-caching` tag) – torvin Oct 01 '17 at 02:59
  • 6
    Web API is server-side. Hence the server-side caching solution. – Sagi Oct 03 '17 at 00:31
  • 1
    Up voting, because I was not familiar with term "in-memory caching" ;) – Adil Ansari Nov 16 '17 at 07:15
  • 1
    Found this to be the best solution for Web API 2.2 currently makes a lot of sense as once a request comes in it is essentially handled server side as mentioned by Sagi. – Trevor Sep 19 '18 at 23:11
  • 2
    FYI you need to set a few HTTP headers. Cache-Control and MaxAge of course, but most importantly the NoStore header. Not necessary if you don't need it, but in complex REST APIs where the response content is filtered and processed based on the current user, and not any query string params, it is extremely important to make sure you're not serving invalid data to your users. Let's say you sign in with a user, request a resource and get your data, then sign in with a second user and you get the cached content from the first user. which would be a catastrophic failure. Test your cached entries :) – Nexus Oct 27 '18 at 22:20
  • A wrapper made entirely of static methods is unnecessary and you can just use `MemoryCache.Default` directly. – Matti Virkkunen Nov 19 '18 at 14:30
  • @MattiVirkkunen Isn't the wrapper around to facilitate calls like MemoryCacher.GetValue (straight with class name) ? – Sangeeta Nov 22 '18 at 05:49
  • @MattiVirkkunen, What else you suggest to use as it's alternative in that case ? – Sangeeta Nov 22 '18 at 10:36
  • 2
    @Sangeeta Nothing. Just use `MemoryCache` directly. – Matti Virkkunen Nov 23 '18 at 16:08
  • Correct me if I am wrong...but this doesn't look thread-safe. Yes, it is a Static Class...so each thread can access it...but it isn't Thread-Safe – Prisoner ZERO Jul 01 '19 at 14:55
  • Why would this not be threadsafe? I've done this on multiple threads and it works fine. each thread had their own key in the memory cache – Terrance Jackson Jan 20 '21 at 01:36
18

As already mentioned by OakNinja, output caching via [OutputCache] attributes is currently not supported by the ASP.NET Web API.

However, there are a few open source implementations filling the gap:

Strathweb.CacheOutput

A small library bringing caching options, similar to MVC's "OutputCacheAttribute", to Web API actions.

Github: https://github.com/filipw/Strathweb.CacheOutput
License: Apache v2

CacheCow

An implementation of HTTP Caching in ASP.NET Web API for both client-side and server-side.

Github: https://github.com/aliostad/CacheCow
License: MIT

There is a nice blog post by Scott Hanselmann covering both feature sets.

Johann
  • 4,107
  • 3
  • 40
  • 39
CodeZombie
  • 5,367
  • 3
  • 30
  • 37
  • Can one not add specific headers to the http request which will inform the clients that they CAN cache this request if they desire? – Zapnologica Dec 23 '15 at 03:59
  • @Zapnologica: The question and answers are focused on server side caching. What you mentioned is client caching. To get best experience you should use both technologies together. – CodeZombie Dec 23 '15 at 10:46
  • There is no specific mention of server side caching? The Attribute which the OP uses does both in MVC as far as I know? However point noted. – Zapnologica Dec 24 '15 at 04:18
  • 1
    Looks like CacheCow now supports Attribute Routing. https://github.com/aliostad/CacheCow/commit/73b4417ce906da3ad6742130458ead808f8077d4 – antmeehan Nov 25 '18 at 13:40
  • Just a heads up to anyone looking to use `CacheCow` in a aspnet **_framework_** web API project: the last commit of the repo that has a relevant sample is [9635b94](https://github.com/aliostad/CacheCow/tree/9635b9463a7c63eddcbb51038abd72917fff2242). The documentation is very limited (you will only find something by **manually** cloning the [wiki repo](https://github.com/aliostad/CacheCow.wiki)). – somethingRandom Feb 01 '23 at 10:22
8

[ResponseCache] is now supported in ASP.NET Core

Features may look identical to [OutputCache] but [ResponseCache] is only for the client side.

Response caching adds cache-related headers to responses. These headers specify how you want client, proxy and middleware to cache responses.

https://learn.microsoft.com/en-us/aspnet/core/performance/caching/response

[ResponseCache(Duration = 3600)]
[HttpGet]
public IEnumerable<Product> Get()
{
  return _service.GetAll();
}
torvin
  • 6,515
  • 1
  • 37
  • 52
wonster
  • 746
  • 1
  • 9
  • 11
  • 8
    [ResponseCache] is not [OutputCache] equivalent, it's just caching things client-side by adding cache-related headers to response. Which would reduce the number of requests a client or proxy makes to the web server. [ResponseCaching] does not cache responses on the web server. – Vasan Feb 02 '17 at 16:50
  • 2
    I'll also add this is for .Net Core – TombMedia Jan 10 '19 at 18:02