2

I am having a problem with using a memory cache (tried both IMemoryCache and IDistributedCache with respectively AddMemoryCache() and AddDistributedMemoryCache). It seems that the cache is not shared between endpoints of my ASP.NET Core 2.2 Web API, but it is shared for requests of 1 endpoint. The cache is injected in constructor of singleton service.

And here is what is my concern:

  1. Request go to endpoint A, it calls API, store response to cache and return it.
  2. Next request go for endpoint A and... successfully get response for cache - OK.
  3. But when calling an endpoint B then I cannot get response for cache (using same key) and the cache seems to be empty

EDIT: after checking I found out that I really get another instances of MemoryCache for different endpoints of my API.

EDIT #2: code samples

DI:

        services.AddDistributedMemoryCache();
        services.AddSingleton<ICacheStore, CacheStore>();
        services.AddScoped<CosmosDbUserRepository>();
        services.AddScoped<IUserRepository>(sp =>
        {
            var realRepository = sp.GetRequiredService<CosmosDbUserRepository>();
            var cache = sp.GetRequiredService<ICacheStore>();
            return new CachedUserRepository(realRepository, cache);
        });

CacheStore:

internal class CacheStore : ICacheStore
{
    private static readonly JsonSerializer Serializer = new JsonSerializer();
    private readonly IDistributedCache _cache;

    public CacheStore(IDistributedCache cache)
    {
        _cache = cache ?? throw new ArgumentNullException(nameof(cache));
    }
}

Sample endpoints:

    [HttpGet]
    [ProducesResponseType(typeof(UserDetails), (int)HttpStatusCode.OK)]
    public async Task<IActionResult> GetUserDetails(
        [FromServices] QueryMediator mediator)
    {
        return Ok(
            await mediator.HandleQuery<GetUserDetailsQuery, UserDetails>(null));
    }

    [HttpPatch("username")]
    [ProducesResponseType((int)HttpStatusCode.NoContent)]
    public async Task<IActionResult> ChangeUsername(
        [FromBody] ChangeUsernameCommand command,
        [FromServices] CommandMediator mediator)
    {
        await mediator.HandleCommand(command);
        return NoContent();
    }
4
  • You need to give more detail about the implementation. At first glance though, it seems like you're expecting the in memory cache on A and B to be the same, even though they're completely separate. A cannot access B's in memory cache and visa versa. So you need a shared data store (probably key/value pair) between the two. Redis is a good possible solution - as are many other - depending on the requirements / need / available resources etc. Commented May 10, 2020 at 21:24
  • Hello! Thanks for the response. I know about possibility od using Redis or sql server but I thought that memory cache is shared for one service (the endpoints called A and B comes from one api, and even one controller). In this one I'll have to reimplement caching mechanism, for now I do not want to spend money on Redis. Thanks! Commented May 11, 2020 at 5:09
  • 1
    This sounds weird. Using AddMemoryCache() registers a singleton memory cache on the DI container so it should be the same between your requests no matter what endpoint. Show us the code for the controller for one of the endpoints and we might be able to help. Commented May 11, 2020 at 6:16
  • Hi! Thanks for the response. I also think that is's strange and should not work in this way. I've put code samples for clarifications. Commented May 11, 2020 at 6:22

1 Answer 1

2

Problem solved: After hours I've tried to create an instance of cache in startup and register the specific instance as Singleton. It worked! But for now I'm trying to reproduce the issue with smaller application and create an issue for this :) Code below:

            var memoryCache = new MemoryDistributedCache(
                Options.Create(new MemoryDistributedCacheOptions()));
            services.AddSingleton<IDistributedCache>(memoryCache);
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.