Information on how to insert and delete from the runtime cache
This article will show you how to insert and delete from the runtime cache.
Scenario
For this example we're working with tags. On my site I have two tag properties:
One on every page using the tag group default
One on my blog posts using the tag group blog
We're going to expose an endpoint that allows us to get the tags from each group.
The tags from the default should be cached for a minute. The blog tags will be cached until site restart or if you publish a blog post node in the Backoffice.
Example
Why work with tags? Because they're not cached by default.. which makes them ideal for demo purposes :)
TagService
First we want to create our CacheTagService. In this example it's a basic class with one method (GetAll) that wraps Umbraco's TagQuery.GetAllTags().
usingSystem;usingSystem.Collections.Generic;usingUmbraco.Cms.Core.Cache;usingUmbraco.Cms.Core.Models;usingUmbraco.Cms.Core.PublishedCache;usingUmbraco.Extensions;namespaceDoccers.Core.Services.Implement;publicclassCacheTagService:ICacheTagService{privatereadonlyITagQuery _tagQuery;privatereadonlyIAppPolicyCache _runtimeCache;publicCacheTagService(ITagQuery tagQuery,AppCaches appCaches) { _tagQuery = tagQuery; // Get the RuntimeCache from appCaches // and assign to our private field. _runtimeCache =appCaches.RuntimeCache; }publicIEnumerable<TagModel> GetAll(string group,string cacheKey,TimeSpan? timeout =null) { // GetCacheItem will automatically insert the object // into cache if it doesn't exist.return_runtimeCache.GetCacheItem(cacheKey, () => {return_tagQuery.GetAllTags(group); }, timeout); }}
As you can see we inherit from the ICacheTagService interface. All that has is:
Now you can inject ICacheTagService in any constructor in your project - wohooo!
API
Now that we have our service it's time to create an endpoint where we can fetch the (cached) tags.
usingSystem;usingSystem.Collections.Generic;usingMicrosoft.AspNetCore.Mvc;usingDoccers.Core.Services;usingUmbraco.Cms.Core.Models;namespaceDoccers.Core.Controllers.Api;[ApiController][Route("/umbraco/api/tags")]publicclassTagsController:Controller{privatereadonlyICacheTagService _cacheTagService; // Dependency injection rocks!publicTagsController(ICacheTagService cacheTagService) { _cacheTagService = cacheTagService; } [HttpGet("getdefaulttags")]publicIEnumerable<TagModel> GetDefaultTags() { // As mentioned earlier we want tags from "default" // group to be cached for a minute.return_cacheTagService.GetAll("default","defaultTags",TimeSpan.FromMinutes(1)); } [HttpGet("getblogtags")]publicIEnumerable<TagModel> GetBlogTags() { // If you don't specify a TimeSpan the object(s) // will be cached until manually removed or // if the site restarts.return_cacheTagService.GetAll("blog","blogTags"); }}
/umbraco/api/tags/getblogtags
/umbraco/api/tags/getdefaulttags
Everything should now work as expected when it comes to getting tags. However, if I go to my Backoffice and add a new tag to the blog group the changes aren't shown on the endpoint. Let's fix that.
Clearing cache on publish
To clear the cache we need a notification handler in which we register to the ContentPublishedNotification event on the ContentService. This allows us to run a piece of code whenever you publish a node.
Now that we have our notification we also need to register it. Add builder.AddNotificationHandler<ContentPublishedNotification, Notification>(); to the Compose method in the Composer class so it becomes: