I did some investigation on my previous question: No matching Localization found for Url
Below is Stack Trace:
2017-11-23 15:50:41.3358|ERROR|Global.Exception.Handling|System.Exception: No matching Localization found for URL 'http://SomeUrl/' ---> System.NullReferenceException: Object reference not set to an instance of an object. at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) at Tridion.ContentDelivery.DynamicContent.DynamicMappingsRetriever.GetPublicationMapping(String url) at Application.Resolvers.PublicationResolver.Resolve(Uri uri) in E:\LocalAgent4\work\eba82aa7dfd1d8ff\src\Application\Resolver\PublicationResolver.cs:line 109
The exception occurs internally in a SDL library on the GetPublicationMapping
method of Tridion.ContentDelivery.DynamicContent.DynamicMappingRetriever
class on the following line, but those values are not null:
this._mappings[url] = publicationMapping;
Note: We are using DD4T 2.1.4 for DD4T.model, So 2.1 for DD4T and Web 8 for Tridion.
8.1.0.1239 for Tridion.ContentDelivery
I found an article https://stackoverflow.com/questions/1320621/throw-a-nullreferenceexception-while-calling-the-set-item-method-of-a-dictionary That explains that NullReferenceException could be triggered when several threads try access the same dictionary object simultaneously, and this is most probably what is happening in our case, since we only see this error sporadically and cannot reproduce it on lower environments, since those does not have too many requests coming in at the same time.
The DynamicMappingsRetriever
class from SDL assembly is not thread safe, but our code is using it as if it was thread safe. That is why sometimes we get this error.
On our code we are using below:
try
{
// NOTE: we're not using UrlToLocalizationMapping here, because we may match too eagerly on a base URL when there is a matching mapping with a more specific URL.
var mapping = _mappingsRetriever.GetPublicationMapping(url);
if (mapping == null || (!mapping.Port.IsNullOrEmpty() && mapping.Port != uri.Port.ToString()))
{
throw new Exception(string.Format("No matching Localization found for URL '{0}'", url));
}
return mapping;
}
So _mappingsRetriever.GetPublicationMapping(url);
is returning null.
Is there any hotfix SDL provided for this issue?
A solution is to make our code thread safe like below, but I am not sure how it would impact the sites on production.
lock (_publicationResolverLocker)
{
var mapping = _mappingsRetriever.GetPublicationMapping(url);
if (mapping == null || (!mapping.Port.IsNullOrEmpty() && mapping.Port != uri.Port.ToString()))
{
throw new Exception(string.Format("No matching Localization found for URL '{0}'", url));
}
return mapping;
}