diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs
index bfc65b70d6..8e68bdae52 100644
--- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs
+++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentExtensionsForModels.cs
@@ -25,15 +25,7 @@ namespace Umbraco.Core.Models.PublishedContent
// get model
// if factory returns nothing, throw
- var model = Current.PublishedModelFactory.CreateModel(content);
- if (model == null)
- throw new Exception("Factory returned null.");
-
- // if factory returns a different type, throw
- if (!(model is IPublishedContent publishedContent))
- throw new Exception($"Factory returned model of type {model.GetType().FullName} which does not implement IPublishedContent.");
-
- return publishedContent;
+ return Current.PublishedModelFactory.CreateModelWithSafeLiveFactoryRefreshCheck(content);
}
}
}
diff --git a/src/Umbraco.Core/PublishedModelFactoryExtensions.cs b/src/Umbraco.Core/PublishedModelFactoryExtensions.cs
index 70bef75192..c36643095b 100644
--- a/src/Umbraco.Core/PublishedModelFactoryExtensions.cs
+++ b/src/Umbraco.Core/PublishedModelFactoryExtensions.cs
@@ -47,6 +47,62 @@ namespace Umbraco.Core
}
}
+ ///
+ /// Creates a strongly typed model while checking if the factory is and if a refresh flag has been set, in which
+ /// case the models will be recompiled before model creation
+ ///
+ ///
+ ///
+ ///
+ internal static IPublishedContent CreateModelWithSafeLiveFactoryRefreshCheck(this IPublishedModelFactory factory, IPublishedContent content)
+ {
+ if (factory is ILivePublishedModelFactory liveFactory && _refresh)
+ {
+ lock (liveFactory.SyncRoot)
+ {
+ if (_refresh)
+ {
+ _refresh = false;
+ //Call refresh on the live factory to re-compile the models
+ liveFactory.Refresh();
+ }
+ }
+ }
+
+ var model = factory.CreateModel(content);
+ if (model == null)
+ throw new Exception("Factory returned null.");
+
+ // if factory returns a different type, throw
+ if (!(model is IPublishedContent publishedContent))
+ throw new Exception($"Factory returned model of type {model.GetType().FullName} which does not implement IPublishedContent.");
+
+ return publishedContent;
+ }
+
+ ///
+ /// Sets a flag to re-compile the models if the is
+ ///
+ ///
+ ///
+ internal static void WithSafeLiveFactoryRefreshSet(this IPublishedModelFactory factory, Action action)
+ {
+ if (factory is ILivePublishedModelFactory liveFactory)
+ {
+ lock (liveFactory.SyncRoot)
+ {
+ _refresh = true;
+ action();
+ }
+ }
+ else
+ {
+ action();
+ }
+ }
+
+ private static volatile bool _refresh = false;
+
public static IDisposable SuspendSafeLiveFactory(this IPublishedModelFactory factory)
{
if (factory is ILivePublishedModelFactory liveFactory)
diff --git a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
index cf90b60d8a..4d339ff336 100644
--- a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
@@ -91,7 +91,8 @@ namespace Umbraco.Web.Cache
// we are using the database to load content into caches
//_publishedModelFactory.WithSafeLiveFactory(() =>
- _publishedSnapshotService.Notify(payloads);
+ _publishedModelFactory.WithSafeLiveFactoryRefreshSet(() =>
+ _publishedSnapshotService.Notify(payloads));
// now we can trigger the event
base.Refresh(payloads);
diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs
index fb4f59fce4..b80542af44 100644
--- a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs
@@ -67,7 +67,8 @@ namespace Umbraco.Web.Cache
// we are using the database to load content into caches
//_publishedModelFactory.WithSafeLiveFactory(() =>
- _publishedSnapshotService.Notify(payloads);
+ _publishedModelFactory.WithSafeLiveFactoryRefreshSet(() =>
+ _publishedSnapshotService.Notify(payloads));
base.Refresh(payloads);
}
diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs
index cde45ae116..66cc5aaed0 100755
--- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs
+++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs
@@ -790,22 +790,23 @@ namespace Umbraco.Web.PublishedCache.NuCache
Notify(_contentStore, payloads, RefreshContentTypesLocked);
Notify(_mediaStore, payloads, RefreshMediaTypesLocked);
- //TODO: I don't think this is necessary with the changes to nucache now that calls to `CreateModel` are lazy!
- //if (_publishedModelFactory.IsLiveFactory())
- //{
- // //In the case of Pure Live - we actually need to refresh all of the content and the media
- // //see https://github.com/umbraco/Umbraco-CMS/issues/5671
- // //The underlying issue is that in Pure Live the ILivePublishedModelFactory will re-compile all of the classes/models
- // //into a new DLL for the application which includes both content types and media types.
- // //Since the models in the cache are based on these actual classes, all of the objects in the cache need to be updated
- // //to use the newest version of the class.
- // using (_contentStore.GetScopedWriteLock(_scopeProvider))
- // using (_mediaStore.GetScopedWriteLock(_scopeProvider))
- // {
- // NotifyLocked(new[] { new ContentCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out var draftChanged, out var publishedChanged);
- // NotifyLocked(new[] { new MediaCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out var anythingChanged);
- // }
- //}
+ //TODO: I don't think this is necessary with the changes to nucache now that calls to `CreateModel` are lazy?
+ // but I may be dreaming here, if i remove this call and save a content type, then the cache doesn't render a lot of the content. hrm.
+ if (_publishedModelFactory.IsLiveFactory())
+ {
+ //In the case of Pure Live - we actually need to refresh all of the content and the media
+ //see https://github.com/umbraco/Umbraco-CMS/issues/5671
+ //The underlying issue is that in Pure Live the ILivePublishedModelFactory will re-compile all of the classes/models
+ //into a new DLL for the application which includes both content types and media types.
+ //Since the models in the cache are based on these actual classes, all of the objects in the cache need to be updated
+ //to use the newest version of the class.
+ using (_contentStore.GetScopedWriteLock(_scopeProvider))
+ using (_mediaStore.GetScopedWriteLock(_scopeProvider))
+ {
+ NotifyLocked(new[] { new ContentCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out var draftChanged, out var publishedChanged);
+ NotifyLocked(new[] { new MediaCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out var anythingChanged);
+ }
+ }
((PublishedSnapshot)CurrentPublishedSnapshot)?.Resync();
}