Introduction

ASP.NET Boilerplate provides an abstraction for caching. It internally uses this cache abstraction. While default implementation uses MemoryCache, it can be implemented and changable for any other caching provider.

ICacheManager

Main interface for caching is ICacheManager. We can inject it and use it to get a cache. Example:

public class TestAppService : ApplicationService
{
    private readonly ICacheManager _cacheManager;

    public TestAppService(ICacheManager cacheManager)
    {
        _cacheManager = cacheManager;
    }

    public Item GetItem(int id)
    {
        //Try to get from cache
        return _cacheManager
                .GetCache("MyCache")
                .Get(id.ToString(), () => GetFromDatabase(id)) as Item;
    }

    public Item GetFromDatabase(int id)
    {
        //... retrieve item from database
    }
}

In this sample, we're injecting ICacheManager and getting a cache named MyCache.

WARNING: GetCache Method

Do not use GetCache method in your constructor. This may dispose the Cache if your class is transient.

ICache

ICacheManager.GetCache method returns an ICache. A cache is singleton (per cache name). It is created first time it's requested, then returns always the same cache object. So, we can share same cache with same name in different classes (clients).

In the sample code, we see simple usage of ICache.Get method. It has two arguments:

ICache interface also has methods like GetOrDefault, Set, Remove and Clear. There are also async versions of all methods.

ITypedCache

ICache interface works string as key and object as value. ITypedCache is a wrapper to ICache to provide type safe, generic cache. We can use generic GetCache extension method to get an ITypedCache:

ITypedCache<int, Item> myCache = _cacheManager.GetCache<int, Item>()("MyCache");

Also, we can use AsTyped extension method to convert an existing ICache instance to ITypedCache.

Configuration

Default cache expire time is 60 minutes. It's sliding. So, if you don't use an item in the cache for 60 minutes, it's automatically removed from the cache. You can configure it for all caches or for a specific cache.

//Configuration for all caches
Configuration.Caching.ConfigureAll(cache =>
{
    cache.DefaultSlidingExpireTime = TimeSpan.FromHours(2);
});

//Configuration for a specific cache
Configuration.Caching.Configure("MyCache", cache =>
{
    cache.DefaultSlidingExpireTime = TimeSpan.FromHours(8);
});

This code should be placed PreInitialize method of your module. With such a code, MyCache will have 8 hours expire time while all other caches will have 2 hours.

Your configuration action is called once cache is first created (on first request). Configuration is not restricted to DefaultSlidingExpireTime only, since cache object is an ICache, you can use it's properties and methods freely configure and initialize it.

Redis Cache Integration

Default cache manager uses in-memory caches. So, it can be a problem if you have more than one concurrent web server running the same application. In that case, you may want to a distributed/central cache server. You can use Redis as your cache server easily.

First, you need to install Abp.RedisCache nuget package to your application (you can install it to your Web project, for example). Then you need to add a DependsOn attribute for AbpRedisCacheModule and call UseRedis extension method in PreInitialize method of your module, as shown below:

//...other namespaces
using Abp.Runtime.Caching.Redis;

namespace MyProject.AbpZeroTemplate.Web
{
    [DependsOn(
        //...other module dependencies
        typeof(AbpRedisCacheModule))]
    public class MyProjectWebModule : AbpModule
    {
        public override void PreInitialize()
        {
            //...other configurations
            
            Configuration.Caching.UseRedis();
        }
        
        //...other code
    }
}