MVCCaching.Base.Core 3.0.2

There is a newer version of this package available.
See the version list below for details.
dotnet add package MVCCaching.Base.Core --version 3.0.2                
NuGet\Install-Package MVCCaching.Base.Core -Version 3.0.2                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MVCCaching.Base.Core" Version="3.0.2" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add MVCCaching.Base.Core --version 3.0.2                
#r "nuget: MVCCaching.Base.Core, 3.0.2"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install MVCCaching.Base.Core as a Cake Addin
#addin nuget:?package=MVCCaching.Base.Core&version=3.0.2

// Install MVCCaching.Base.Core as a Cake Tool
#tool nuget:?package=MVCCaching.Base.Core&version=3.0.2                

XperienceCommunity.MVCCaching

This package contains interfaces and extensions to build, store, and use Cache Dependencies, as well as an Attribute to automatically set up Dependency Injection on your custom interfaces/implementations.

This version is only compatible Kentico Xperience 13 with .Net Core (3.1+) applications. If you are running KX12 MVC or KX13 on MVC 5 (.Net 4.8 Framework), please see the .Net 4.8 branch and packages.

Migration

If migrating from KX12 MVCCaching.Kentico, or KX13 MVCCaching.Kentico / MVCCaching.Kentico.Core, please see the Migration Readme

Installation

  1. Install the Nuget Package XperienceCommunity.MVCCaching on your MVC.Net Core application.
  • If you have Kentico-Agnostic libraries and need to implement the basic interfaces (such as ICacheKey) or leverage the Automatic DI, you can add the MVCCaching.Base.Core nuget package.
  1. On your IServiceCollection, add MVCCaching and optionally the automatic Dependency injection:
public void ConfigureServices(IServiceCollection services)
        {
        services.AddMVCCaching();
        // optional Automatic DI setup, see documentation
	    // services.AddMVCCachingAutoDependencyInjectionByAttribute();
	    // services.AddMVCCachingAutoDependencyInjectionBySuffixes(new string[] {"Repository", "Service"});
	    ...
        }

Usage

Caching in Xperience / MVC

Kentico Xperience provides it's integrated Cache Dependency system, which triggers cache clearing when certain objects are touched, and it's own IProgressiveCache and IPageRetriever interfaces which have caching built in.

During the calling of these operations, you define Cache Dependency Keys, which are attached to that cached operation . If the keys get touched (can be manually touched or automatically by Kentico Xperience), the caches automatically 'clear' for that item.

MVC.Net Core provides output caching using the <cache> tag helper. Kentico Xperience has added a <cache-depencency /> tag helper within that to allow you to pass cache dependencies, and thus also properly clear the <cache> content if the keys are touched.

The problems are:

  1. There is no default way to know what all cache dependencies are added within a <cache> tag
  2. Any logic / dependencies defined within IProgressiveCache / IPageRetriever are only executed if the cache misses.

How MVCCaching Works

The MVCCaching System works by solving the 2 problems mentioned above, as well as adding useful tools.

First, it provides the ICacheDependencyStore and ICacheDependencyScope interfaces.

The ICacheDependencyStore stores cache dependencies in a central scoped array, which makes it possible to determine what dependencies are called within the <cache> tag.

The ICacheDependencyScope allows you to tracking dependencies between the Begin() and End(). Simply call ICacheDependencyScope.Begin() before you make any operations that may have caching/cache dependencies, then call ICacheDependencyScope.End() into the <cache-dependency key=@scope.End() />

SAMPLE

@inject ICacheDependencyScope CacheScope 
<cache expires-after=@CacheMinuteType.Long.ToTimeSpan() >
	@{
		CacheScope.Begin();
	}
	<vc:some-thing />
    <cache-dependency cache-keys="@CacheScope.End()" />
</cache>

SAMPLE View Component

public async Task<IViewComponentResult> InvokeAsync()
        {
            _cacheDependenciesScope.Begin();
            // This repository should leverage the ICacheDependencyStore via ICacheDependencyBuilderFactory/ICacheDependencyBuilder
			var model = await	_someRepsitory.GetStuffAsync();
			return View("mycomponent.cshtml", model);
		}
/// mycomponent.cshtml
@inject ICacheDependencyScope CacheScope 
<cache duration=@CacheMinuteType.Long>
	<h1>@Model.Greeting</h1>
	<p>Some lengthy operation warranty caching...</p>
    <cache-dependency cache-keys="@CacheScope.End()" />
</cache>

ICacheDependencyBuilderFactory and ICacheDependencyBuilder

As mentioned, another issue with dependency keys are that Kentico Xperience's IPageRetriever and IProgressiveCache need the dependency keys to properly cache, but if you define them within those interfaces, they are only processed if the cache misses and the logic is executed.

Thus, you need to define your cache dependencies outside of these interfaces (so the ICacheDependencyStore can track them), as well as pass them into the Kentico Xperience Interfaces so data-level caching can occur.

MVCCaching introduces the ICacheDependencyBuilderFactory interface which has a Create(bool addKeysToStore = true); method. Inject this into your repositories and call this method to retrieve an ICacheDependencyBuilder class.

This class has a plethora of built in extension methods to accommodate easily define your dependency keys and can easily be extended.

Additionally, it provides a quick IPageCacheBuilder.Configure method to integrate with the IPageRetriever interface, and a ICacheDependencyBuilder.GetCMSCacheDependency() method to integrate with IProgressiveCache

SAMPLE

// IPageRetriever
public async Task<IEnumerable<TabItem>> GetTabsAsync(string path)
        {
            var builder = _cacheDependencyBuilderFactory.Create()
                .PagePath(path, PathTypeEnum.Children);

            var retriever = await _pageRetriever.RetrieveAsync<Tab>(
                query => query
                    .Path(path, PathTypeEnum.Children)
                    .Columns(new string[] {
                        nameof(Tab.DocumentID),
                        nameof(Tab.TabName)
                    })
                    .OrderBy(nameof(TreeNode.NodeLevel), nameof(TreeNode.NodeOrder)),
                cacheSettings => cacheSettings.Configure(builder, CacheMinuteTypes.Medium.ToDouble(), "GetTabsAsync", path)
            );

            return retriever.Select(x => _mapper.Map<TabItem>(x));
        }

// IProgressiveCache
public async Task<Maybe<RoleItem>> GetRoleAsync(string roleName, string siteName)
        {
            var builder = _cacheDependencyBuilderFactory.Create()
                                .Object(RoleInfo.OBJECT_TYPE, roleName);

            var role = await _progressiveCache.LoadAsync(async cs =>
            {
                if (cs.Cached)
                {
                    cs.CacheDependency = builder.GetCMSCacheDependency();
                }
                return await _roleInfoProvider.GetAsync(roleName, await _siteRepository.GetSiteIDAsync(siteName));
            }, new CacheSettings(CacheMinuteTypes.Medium.ToDouble(), "GetRoleAsync", roleName, siteName));

            if (role != null)
            {
                return Maybe.From(_mapper.Map<RoleItem>(role));
            }
            else
            {
                return Maybe.None;
            }
        }

Extending ICacheDependencyBuilder

You can easily create your own extension methods to suit your purposes for your site. You can reference the ICacheDependencyBuilderExtensions.cs File in this repository to get an idea of how to add your own.

If needed as well, you implement your own Factory and Builder object to add even further functionality, however in most cases this is not warranted.

Other Tools

Cache Durations

This package comes with 2 Enum Extension methods, Enum.ToDouble() and Enum.ToTimeSpan(), this converts the int value of the enum into a double or timespan (as minutes). We recommend creating a Cache Duration Enum (ex CacheMinutesType ) that has int values corresponding to the minutes you wish to cache for. This makes changing and managing different 'durations' of caching easy.

Object.ToCacheNameIdentifier() / ICacheKey

When building out a Cache Name (unique identifier for the cache to hit on), it must ultimately resolve to a string. If you are using a model, the .ToString() will not be unique to what your object actually is. You can implement ICacheKey on your model and define the GetCacheKey() to return a unique string based on the model itself.

The object.ToCacheNameIdentifier() extension method also properly retrieves the object's identifier, be it string.Empty if null, the ICacheKey.GetCacheKey() if it implements, or the object.ToString() otherwise. It also handles IEnumerables of objects and joins their own ToCacheNameIdentifier() together in a pipe delimited string.

The IPageCacheBuilder.Configure extension method automatically leverages this, however if you use IProgressiveCache's new CacheSettings(duration, nameparams) you will need to call .ToCacheNameIdentifier() on any parameter passed into it if you wish to leverage this functionality.

ICacheRepositoryContext

This interface provides quick helper methods to determine if the site is in PreviewMode or not and the current culture. IProgressiveCache already handles Preview Mode or not, however your <cache enabled=bool /> may benefit from the repoContext.CacheEnabled() method so it doesn't MVCCache during Preview mode.

CacheEnabled() is short for !PreviewEnabled()

IContentItemMetadataProvider

This interface helps retrieve Kentico Xperience's CodeName for the given object (TreeNode or BaseInfo.

Contributions, bug fixes and License

Feel free to Fork and submit pull requests to contribute.

You can submit bugs through the issue list and I will get to them as soon as i can, unless you want to fix it yourself and submit a pull request!

Check the License.txt for License information

Compatability

Can be used on any Kentico Xperience 13 for .Net Core

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages (5)

Showing the top 5 NuGet packages that depend on MVCCaching.Base.Core:

Package Downloads
XperienceCommunity.Baseline.Core.Models

The Baseline a set of Core Systems, Tools, and Structure to ensure a superior Kentico Website that's easy to migrate, for Kentico Xperience 13 and eventually Xperience by Kentico

MVCCaching.Kentico.Core

MVC Caching for Kentico Xperience 13 MVC.Net Core, provides attribute level caching and dependency injecting for IRepository and IService. Also provides ICacheDependenciesScope to track Dependencies and retrieve them and ICacheDependenciesStore to store them (all MVCCaching attributed dependencies automatically added to ICacheDependenciesStore). While these can be used manually with any Kentico Xperience 13 version, it is primarily created for KX 13 Refresh 1 and above (Hotfix 16+)

XperienceCommunity.MVCCaching

Caching interfaces and extensions for Kentico Xperience .net 5.0 MVC Sites

MVCCaching.Base.Core.Components

Tag Helper Components used with MVCCaching.Base.Core. This one is built for .net 8.0

XperienceCommunity.DevTools.MVCCaching

Adjusted Get Default Language to fall back to Content Default Language. Changed ICachingReferenceService to ICacheReferenceService to fit other ICache motif.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
4.5.0 185 10/4/2024
4.4.0 10,832 10/26/2023
4.3.0 296 10/26/2023
4.2.0 9,319 6/30/2023
4.1.0 312 6/30/2023
4.0.2 851 6/30/2023
4.0.1 389 6/30/2023
4.0.0 5,015 5/22/2023
3.0.2 5,379 11/22/2022
3.0.1 737 10/25/2022
3.0.0-beta 379 10/24/2022
3.0.0-alpha 348 10/24/2022
2.1.1 28,619 3/12/2021
2.0.0 2,669 10/5/2020

Removed IRepository and IService, CacheDependency Attributes added ICacheDependencyKeyBuilderFactory and ICacheDependencyKeyBuilder types.