2

There are a few things I'd like to cache without relying on Redis. My app is an ASP.NET Core API app running on Azure App Service.

For example, I create a list of countries from

CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);

I can save this in Redis but it'll cost money and this is not a list that changes often and is produced from the framework so even if I'm running multiple instances of my API app, lists will be identical.

How do I save this in memory without Redis? I can call a method that generates this list in my Startup.cs but where do I store it and how do I retrieve it?

1
  • You can put this on web server cache with longer expiration such as 1 day. This would work even with multiple servers serving the traffic. Commented Feb 7, 2018 at 4:42

1 Answer 1

2

AspNetCore has a built-in memory cache that you can use to store pieces of data that are shared between requests.

Register the cache at startup...

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMemoryCache();
        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseMvcWithDefaultRoute();
    }
}

And you can inject it like...

public class HomeController : Controller
{
    private IMemoryCache _cache;

    public HomeController(IMemoryCache memoryCache)
    {
        _cache = memoryCache;
    }

    public IActionResult Index()
    {
        string cultures = _cache[CacheKeys.Cultures] as CultureInfo[];

        return View();
    }

To make it work application wide, you can use a facade service with strongly-typed members combined with some sort of cache refresh pattern:

  1. Attempt to get the value from the cache
  2. If the attempt fails
    • Lookup the data from the data source
    • Repopulate the cache
  3. Return the value

public CultureInfo[] Cultures { get { return GetCultures(); } }

private CultureInfo[] GetCultures()
{
    CultureInfo[] result;

    // Look for cache key.
    if (!_cache.TryGetValue(CacheKeys.Cultures, out result))
    {
        // Key not in cache, so get data.
        result = CultureInfo.GetCultures(CultureTypes.SpecificCultures);

        // Set cache options.
        var cacheEntryOptions = new MemoryCacheEntryOptions()
            // Keep in cache for this time, reset time if accessed.
            .SetSlidingExpiration(TimeSpan.FromMinutes(60));

        // Save data in cache.
        _cache.Set(CacheKeys.Cultures, result, cacheEntryOptions);
    }

    return result;
}

Of course, you could clean that up by making it into a service that accepts the cache as a dependency which you can inject wherever it is needed, but that is the general idea.

Note also there is a distributed cache in case you want to share data between web servers.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.