1

So I have a need to use IMemoryCache in my ASP.NET Core application, in most places it is DI'd into the controllers and works as expected. Now I have a need to cache part of the menu, and the menu logic is called as part of the layout view. So, there isn't a controller to speak of. My Startup has the following in it already, which works well for other things:

services.AddMemoryCache();

The call that is part of the layout looks like this:

@(await new MenuUtility().DisplayNavBar(Html, showMenus))

The MenuUtility class, which is where the cache will be used, has a call that looks like this:

public class MenuUtility
{
  private IMemoryCache _cache;

    public MenuUtility()
    {
       _cache = HttpContext.Current.RequestServices.GetService<MemoryCache>();
    }

    // Rest of class logic
}

The problem is, the cache service I am looking to return is always null. Is there something I am forgetting? I tried to add services.AddScoped<MenuUtility>(); to the ConfigureServices call, thinking that this would allow me to pass the cache interface in the constructor, but since I am calling the MenuUtility explicitly I don't have the parameter of the cache to pass in.

I see a few questions here in SO that talk around this issue, but nothing that directly and correctly answers it.

Since this is my project for which I will forever be the only programmer, I would prefer a simple solution instead of suggestions to rearchitect a bunch of it, if I can't come up with a good solution I will just leave out the cache for this.

1
  • did you try, var x = new MemoryCache(); Commented Dec 21, 2019 at 6:35

1 Answer 1

4

the menu logic is called as part of the layout view

You can still use the @inject directive inside layout Razor views to inject services into the view:

@inject MenuUtility menuUtility

@await menuUtility.DisplayNavBar(Html, showMenus)

To make that work, you will just need to register the MenuUtility as a service and then use constructor injection in your MenuUtility to resolve the IMemoryCache:

// in Startup.ConfigureServices
services.AddTransient<MenuUtility>();
public class MenuUtility
{
    private readonly IMemoryCache _cache;

    public MenuUtility(IMemoryCache cache)
    {
       _cache = cache;
    }

    // …
}

You should generally avoid having to create utilities and services using new. The chance is high that you do have some dependency on some framework component, and then you should definitely use dependency injection to resolve this dependency automatically.

Btw. HttpContext.Current should not compile in ASP.NET Core. If it does, chances are that you are running on the .NET Framework with System.Web referenced. That is the old ASP.NET which is completely incompatible to ASP.NET Core. You should absolutely not mix these two frameworks. In ASP.NET Core, there is no way to retrieve the current HttpContext statically. You have to use dependency injection at some point.

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

2 Comments

Thanks! This exactly solved the problem! Upvoted and marked as answer.
BTW, regarding the framework version, looks like somewhere I manually referenced System.Web (for grabbing an IP address) so this might be why the relevant line above didn't cause the compiler to complain. Didn't see it in the references though. Going to sort this out.

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.