Search code examples
razorasp.net-coreoutputcacheasp.net-core-viewcomponentresponsecache

How to pull a ViewComponent outside a response cached controller's action in ASP.NET Core


For performance purposes, I need to cache the results of the homepage action, while allowing the display name of the logged-in user to remain uncached.

I used to achieve something similar on ASP.NET MVC Framework projects using DonutOutputCache. This system was very useful because you were able to put an entire action into the output cache while maintaining partial view results outside of the cache. I could thus have three or four partials who needed personalization—e.g., a survey, an analytic tag, the user name and avatar, a behavior based article list, etc.).

Do you know if I could handle this with ASP.NET Core's new [OutputCache] attribute or <cache /> Tag Helper?

At the moment, I put the whole home page into a classic memory cache. It would be fantastic to have this kind of Tag Helper:

<cache expires-after="TimeSpan.FromMinutes(60)">
  @*Cached part*@
  <cache-hole>
    @*Refreshed on each page refresh. This could work with a ResponseCache attribute too.*@
    @await Components.InvokeAsync("UserProfile")
  </cache-hole>
</cache>

Solution

  • I'm not sure about what you were using previously, but I don't think it was actually doing what you think. The whole point of an output cache is bypassing the view rendering process, as such, whatever you cache is just returned as-is, not further processed to determine if something inside needs to be rendered.

    If you cache your entire page, then you cannot have any part inside that needs to vary per user. You'll simply need to reduce the scope of what you're caching. Cache the parts of the page that don't vary, and that will at least give the main page a leg up in rendering. This is what the cache tag helper is for. You can also cache just for a particular user with this tag helper:

    <cache vary-by-user="true">
        <!-- user-specific stuff -->
    </cache>
    

    This will still render multiple times, but only once per user. After it has been cached for a particular user, then the cache will be used.