I went for the IContentUrlCache approach. My scenario is that one product can belong to two different root (segment) categories and based on current segment context (selected by user), the product should have a unique URL.
I think you might get problems with invalidating cache. If there are multiple markets for one language, they will invalidate each other, leading to very few cache hits.
My implementation for IContentUrlCache was quite simple actually. I created an interceptor that looks like this (more information at the end about registering the interceptor):
public class CustomContentUrlCache : IContentUrlCache
{
private readonly IContentUrlCache _contentUrlCache;
private readonly ISiteSegmentContext _siteSegmentContext;
public CustomContentUrlCache(
IContentUrlCache contentUrlCache,
ISiteSegmentContext siteSegmentContext)
{
_contentUrlCache = contentUrlCache;
_siteSegmentContext = siteSegmentContext;
}
public string Get(ContentUrlCacheContext context)
{
var newContext = new ContentUrlCacheContextWrapper(context, _siteSegmentContext.GetCurrentSegment());
return _contentUrlCache.Get(newContext);
}
public void Remove(ContentUrlCacheContext context) => _contentUrlCache.Remove(context);
public void Insert(string url, ContentUrlCacheContext context)
{
var newContext = new ContentUrlCacheContextWrapper(context, _siteSegmentContext.GetCurrentSegment());
_contentUrlCache.Insert(url, newContext);
}
}
This is the ContentUrlCacheContextWrapper implementation:
public class ContentUrlCacheContextWrapper : ContentUrlCacheContext
{
public ContentReference CurrentSegment { get; }
public ContentUrlCacheContextWrapper(ContentUrlCacheContext context, ContentReference currentSegment)
: base(context.ContentLink, context.Language, context.Host, context.VirtualPathArguments)
{
CurrentSegment = currentSegment;
}
public override int GetHashCode()
{
var hashCodeCombiner = new HashCode();
hashCodeCombiner.Add(base.GetHashCode());
hashCodeCombiner.Add(CurrentSegment);
return hashCodeCombiner.ToHashCode();
}
}
The HashCode class used above comes from the Nuget package Microsoft.Bcl.HashCode.
If you haven't registered an interceptor before, here is sample code for it:
[ModuleDependency(typeof(ServiceContainerInitialization))]
[InitializableModule]
public class InterceptorsInitialization : IConfigurableModule
{
public void ConfigureContainer(ServiceConfigurationContext context)
{
AddInterceptors(context.Services);
}
private void AddInterceptors(IServiceConfigurationProvider services)
{
services.Intercept<IContentUrlCache>((locator, contentUrlCache) =>
{
var routingOptions = locator.GetInstance<RoutingOptions>();
return routingOptions.UrlCacheEnabled()
? new CustomContentUrlCache(contentUrlCache, locator.GetInstance<ISiteSegmentContext>())
: contentUrlCache;
});
}
public void Initialize(InitializationEngine context)
{
}
public void Uninitialize(InitializationEngine context)
{
}
}
Hi all,
We're working on a CMS/Commerce upgrade piece of work and have noticed a bug with UrlResolver pulling the wrong URL when the user switches market. This has been introduced in the upgrade and is observable on the integration environment where this code has been deployed, compared to the pre-production environment where it has not. The CMS and Commerce versions we have upgraded to are:
CMS: 11.20.11
Commerce: 13.32.0
We have a custom language and market segment class inheriting from SegmentBase to insert an initial segment of {domain}/{language}-{market}/{path}, e.g www.domain.com/en-gb/ or www.domain.com/fr-fr/.
This issue only occurs when the user switches to a market with the same language, so user switches from www.domain.com/en-gb/ to www.domain.com/en-ie/ for example, all links generated using UrlResolver (or Url.ContentUrl()) will point to www.domain.com/en-gb/. This would suggest that there is cache invalidation around the current language.
Anything I've found around this, points to a URL caching issue that was resolved by Optimizely in bugs CMS-16555 and CMS-16839. Fixed in CMS version 11.20.0+. From what I can tell those issues are regarding cache invalidation when the content item URL has changed, which isn't relevent to this scenario.
I've found this post (https://world.optimizely.com/blogs/Daniel-Ovaska/Dates/2020/9/improved-url-caching-in-episerver/), which might be an approach to invalidate the cache but I wanted to check if this is an issue anyone else has experienced? Possibly, if there is a solution without needing to implement a custom IContentUrlCache.
Thanks,
Niall