diff --git a/NuGet.Config b/NuGet.Config
index d6c63173f8..92eaf83792 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -1,13 +1,15 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/src/Umbraco.Core/Cache/DistributedCache.cs b/src/Umbraco.Core/Cache/DistributedCache.cs
index 698e97c610..7ad9f9569f 100644
--- a/src/Umbraco.Core/Cache/DistributedCache.cs
+++ b/src/Umbraco.Core/Cache/DistributedCache.cs
@@ -46,7 +46,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || instances.Length == 0 || getNumericId == null) return;
- _serverMessenger.PerformRefresh(
+ _serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
getNumericId,
instances);
@@ -61,7 +61,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || id == default(int)) return;
- _serverMessenger.PerformRefresh(
+ _serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
id);
}
@@ -75,7 +75,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || id == Guid.Empty) return;
- _serverMessenger.PerformRefresh(
+ _serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
id);
}
@@ -86,7 +86,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || payload == null) return;
- _serverMessenger.PerformRefresh(
+ _serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
payload);
}
@@ -97,7 +97,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || payloads == null) return;
- _serverMessenger.PerformRefresh(
+ _serverMessenger.QueueRefresh(
GetRefresherById(refresherGuid),
payloads.ToArray());
}
@@ -125,7 +125,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty) return;
- _serverMessenger.PerformRefreshAll(
+ _serverMessenger.QueueRefreshAll(
GetRefresherById(refresherGuid));
}
@@ -138,7 +138,7 @@ namespace Umbraco.Web.Cache
{
if (refresherGuid == Guid.Empty || id == default(int)) return;
- _serverMessenger.PerformRemove(
+ _serverMessenger.QueueRemove(
GetRefresherById(refresherGuid),
id);
}
@@ -155,7 +155,7 @@ namespace Umbraco.Web.Cache
///
public void Remove(Guid refresherGuid, Func getNumericId, params T[] instances)
{
- _serverMessenger.PerformRemove(
+ _serverMessenger.QueueRemove(
GetRefresherById(refresherGuid),
getNumericId,
instances);
@@ -164,9 +164,15 @@ namespace Umbraco.Web.Cache
#endregion
// helper method to get an ICacheRefresher by its unique identifier
- private ICacheRefresher GetRefresherById(Guid refresherGuid)
+ private ICacheRefresher GetRefresherById(Guid refresherGuid)
{
- return _cacheRefreshers[refresherGuid];
+ ICacheRefresher refresher = _cacheRefreshers[refresherGuid];
+ if (refresher == null)
+ {
+ throw new InvalidOperationException($"No cache refresher found with id {refresherGuid}");
+ }
+
+ return refresher;
}
}
}
diff --git a/src/Umbraco.Core/Cache/DistributedCacheBinderComponent.cs b/src/Umbraco.Core/Cache/DistributedCacheBinderComponent.cs
deleted file mode 100644
index 31e876892e..0000000000
--- a/src/Umbraco.Core/Cache/DistributedCacheBinderComponent.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Umbraco.Core.Composing;
-
-namespace Umbraco.Web.Cache
-{
- public class DistributedCacheBinderComponent : IComponent
- {
- private readonly IDistributedCacheBinder _binder;
-
- public DistributedCacheBinderComponent(IDistributedCacheBinder distributedCacheBinder)
- {
- _binder = distributedCacheBinder;
- }
-
- public void Initialize()
- {
- _binder.BindEvents();
- }
-
- public void Terminate()
- { }
- }
-}
diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs
index 1c4de6cd8e..14089ba924 100644
--- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs
+++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs
@@ -1,7 +1,8 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
+using Umbraco.Core.DependencyInjection;
namespace Umbraco.Core.Composing
{
diff --git a/src/Umbraco.Core/Composing/Composers.cs b/src/Umbraco.Core/Composing/Composers.cs
index 47f272cbf4..91c8244324 100644
--- a/src/Umbraco.Core/Composing/Composers.cs
+++ b/src/Umbraco.Core/Composing/Composers.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@@ -70,7 +70,6 @@ namespace Umbraco.Core.Composing
foreach (var composer in composers)
{
- var componentType = composer.GetType();
composer.Compose(_builder);
}
}
diff --git a/src/Umbraco.Core/Composing/CompositionExtensions.cs b/src/Umbraco.Core/Composing/CompositionExtensions.cs
index e4e02443eb..d7b143df38 100644
--- a/src/Umbraco.Core/Composing/CompositionExtensions.cs
+++ b/src/Umbraco.Core/Composing/CompositionExtensions.cs
@@ -1,5 +1,4 @@
-using System;
-using Umbraco.Core;
+using System;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Composing;
using Umbraco.Web.PublishedCache;
diff --git a/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs
index edbf554a2c..9229a95cc3 100644
--- a/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs
+++ b/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
+using Umbraco.Core.DependencyInjection;
namespace Umbraco.Core.Composing
{
diff --git a/src/Umbraco.Core/CompositionExtensions.cs b/src/Umbraco.Core/CompositionExtensions.cs
deleted file mode 100644
index 58aac7b811..0000000000
--- a/src/Umbraco.Core/CompositionExtensions.cs
+++ /dev/null
@@ -1,123 +0,0 @@
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Composing;
-using Umbraco.Core.HealthCheck;
-using Umbraco.Core.Manifest;
-using Umbraco.Core.PropertyEditors;
-using Umbraco.Web.Actions;
-using Umbraco.Web.ContentApps;
-using Umbraco.Web.Dashboards;
-using Umbraco.Web.Editors;
-using Umbraco.Web.Routing;
-using Umbraco.Web.Sections;
-using Umbraco.Web.Tour;
-
-namespace Umbraco.Core
-{
- public static partial class CompositionExtensions
- {
-
- #region Collection Builders
-
- ///
- /// Gets the actions collection builder.
- ///
- /// The builder.
- ///
- public static ActionCollectionBuilder Actions(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the content apps collection builder.
- ///
- /// The builder.
- ///
- public static ContentAppFactoryCollectionBuilder ContentApps(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the content finders collection builder.
- ///
- /// The builder.
- ///
- public static ContentFinderCollectionBuilder ContentFinders(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the editor validators collection builder.
- ///
- /// The builder.
- ///
- public static EditorValidatorCollectionBuilder EditorValidators(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the health checks collection builder.
- ///
- /// The builder.
- public static HealthCheckCollectionBuilder HealthChecks(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the TourFilters collection builder.
- ///
- public static TourFilterCollectionBuilder TourFilters(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the URL providers collection builder.
- ///
- /// The builder.
- public static UrlProviderCollectionBuilder UrlProviders(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the media url providers collection builder.
- ///
- /// The builder.
- public static MediaUrlProviderCollectionBuilder MediaUrlProviders(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the backoffice sections/applications collection builder.
- ///
- /// The builder.
- public static SectionCollectionBuilder Sections(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- ///
- /// Gets the components collection builder.
- ///
- public static ComponentCollectionBuilder Components(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
-
- ///
- /// Gets the backoffice dashboards collection builder.
- ///
- /// The builder.
- public static DashboardCollectionBuilder Dashboards(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add()
- .Add();
-
-
- ///
- /// Gets the content finders collection builder.
- ///
- /// The builder.
- ///
- public static MediaUrlGeneratorCollectionBuilder MediaUrlGenerators(this IUmbracoBuilder builder)
- => builder.WithCollectionBuilder();
-
- #endregion
- }
-}
diff --git a/src/Umbraco.Core/ServiceCollectionExtensions.cs b/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs
similarity index 89%
rename from src/Umbraco.Core/ServiceCollectionExtensions.cs
rename to src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs
index d1c89ea17e..97e70da9be 100644
--- a/src/Umbraco.Core/ServiceCollectionExtensions.cs
+++ b/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs
@@ -1,9 +1,10 @@
-using System;
+using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
+using Umbraco.Core;
using Umbraco.Core.Composing;
-namespace Umbraco.Core
+namespace Umbraco.Core.DependencyInjection
{
public static class ServiceCollectionExtensions
{
@@ -21,7 +22,7 @@ namespace Umbraco.Core
where TImplementing : class, TService1, TService2
{
services.AddUnique();
- services.AddUnique(factory => (TImplementing) factory.GetRequiredService());
+ services.AddUnique(factory => (TImplementing)factory.GetRequiredService());
}
public static void AddUnique(this IServiceCollection services)
@@ -48,9 +49,9 @@ namespace Umbraco.Core
///
public static void AddUnique(this IServiceCollection services, TService instance)
where TService : class
- => services.Replace(ServiceDescriptor.Singleton(instance));
+ => services.Replace(ServiceDescriptor.Singleton(instance));
- public static IServiceCollection AddLazySupport(this IServiceCollection services)
+ internal static IServiceCollection AddLazySupport(this IServiceCollection services)
{
services.Replace(ServiceDescriptor.Transient(typeof(Lazy<>), typeof(LazyResolve<>)));
return services;
diff --git a/src/Umbraco.Core/ServiceProviderExtensions.cs b/src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs
similarity index 96%
rename from src/Umbraco.Core/ServiceProviderExtensions.cs
rename to src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs
index e0d3da2c03..a1cc779500 100644
--- a/src/Umbraco.Core/ServiceProviderExtensions.cs
+++ b/src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs
@@ -1,11 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
+using System;
using Microsoft.Extensions.DependencyInjection;
-using Umbraco.Core.Composing;
-namespace Umbraco.Core
+namespace Umbraco.Core.DependencyInjection
{
///
/// Provides extension methods to the class.
diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs
new file mode 100644
index 0000000000..f6dc6fd6ff
--- /dev/null
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs
@@ -0,0 +1,275 @@
+using System.Security.Cryptography;
+using Umbraco.Core.Cache;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Dashboards;
+using Umbraco.Core.HealthCheck;
+using Umbraco.Core.Manifest;
+using Umbraco.Core.PackageActions;
+using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.PropertyEditors.Validators;
+using Umbraco.Core.Strings;
+using Umbraco.Core.Trees;
+using Umbraco.Web.Actions;
+using Umbraco.Web.ContentApps;
+using Umbraco.Web.Dashboards;
+using Umbraco.Web.Editors;
+using Umbraco.Web.HealthCheck;
+using Umbraco.Web.HealthCheck.NotificationMethods;
+using Umbraco.Web.Media.EmbedProviders;
+using Umbraco.Web.Routing;
+using Umbraco.Web.Sections;
+using Umbraco.Web.Tour;
+
+namespace Umbraco.Core.DependencyInjection
+{
+ ///
+ /// Extension methods for
+ ///
+ public static partial class UmbracoBuilderExtensions
+ {
+ ///
+ /// Adds all core collection builders
+ ///
+ internal static void AddAllCoreCollectionBuilders(this IUmbracoBuilder builder)
+ {
+ builder.CacheRefreshers().Add(() => builder.TypeLoader.GetCacheRefreshers());
+ builder.DataEditors().Add(() => builder.TypeLoader.GetDataEditors());
+ builder.Actions().Add(() => builder.TypeLoader.GetTypes());
+ // register known content apps
+ builder.ContentApps()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append();
+ // all built-in finders in the correct order,
+ // devs can then modify this list on application startup
+ builder.ContentFinders()
+ .Append()
+ .Append()
+ .Append()
+ /*.Append() // disabled, this is an odd finder */
+ .Append()
+ .Append();
+ builder.EditorValidators().Add(() => builder.TypeLoader.GetTypes());
+ builder.HealthChecks().Add(() => builder.TypeLoader.GetTypes());
+ builder.HealthCheckNotificationMethods().Add(() => builder.TypeLoader.GetTypes());
+ builder.TourFilters();
+ builder.UrlProviders()
+ .Append()
+ .Append();
+ builder.MediaUrlProviders()
+ .Append();
+ // register back office sections in the order we want them rendered
+ builder.Sections()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append();
+ builder.Components();
+ // register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards
+ builder.Dashboards()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add(builder.TypeLoader.GetTypes());
+ builder.PackageActions().Add(() => builder.TypeLoader.GetPackageActions());
+ builder.DataValueReferenceFactories();
+ builder.PropertyValueConverters().Append(builder.TypeLoader.GetTypes());
+ builder.UrlSegmentProviders().Append();
+ builder.ManifestValueValidators()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add()
+ .Add();
+ builder.ManifestFilters();
+ builder.MediaUrlGenerators();
+ // register OEmbed providers - no type scanning - all explicit opt-in of adding types, IEmbedProvider is not IDiscoverable
+ builder.OEmbedProviders()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append()
+ .Append();
+ builder.SearchableTrees().Add(() => builder.TypeLoader.GetTypes());
+ }
+
+ ///
+ /// Gets the actions collection builder.
+ ///
+ /// The builder.
+ public static ActionCollectionBuilder Actions(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the content apps collection builder.
+ ///
+ /// The builder.
+ public static ContentAppFactoryCollectionBuilder ContentApps(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the content finders collection builder.
+ ///
+ /// The builder.
+ public static ContentFinderCollectionBuilder ContentFinders(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the editor validators collection builder.
+ ///
+ /// The builder.
+ public static EditorValidatorCollectionBuilder EditorValidators(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the health checks collection builder.
+ ///
+ /// The builder.
+ public static HealthCheckCollectionBuilder HealthChecks(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ public static HealthCheckNotificationMethodCollectionBuilder HealthCheckNotificationMethods(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the TourFilters collection builder.
+ ///
+ public static TourFilterCollectionBuilder TourFilters(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the URL providers collection builder.
+ ///
+ /// The builder.
+ public static UrlProviderCollectionBuilder UrlProviders(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the media url providers collection builder.
+ ///
+ /// The builder.
+ public static MediaUrlProviderCollectionBuilder MediaUrlProviders(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the backoffice sections/applications collection builder.
+ ///
+ /// The builder.
+ public static SectionCollectionBuilder Sections(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the components collection builder.
+ ///
+ public static ComponentCollectionBuilder Components(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the backoffice dashboards collection builder.
+ ///
+ /// The builder.
+ public static DashboardCollectionBuilder Dashboards(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the cache refreshers collection builder.
+ ///
+ /// The builder.
+ public static CacheRefresherCollectionBuilder CacheRefreshers(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the package actions collection builder.
+ ///
+ /// The builder.
+ internal static PackageActionCollectionBuilder PackageActions(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the data editor collection builder.
+ ///
+ /// The builder.
+ public static DataEditorCollectionBuilder DataEditors(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the data value reference factory collection builder.
+ ///
+ /// The builder.
+ public static DataValueReferenceFactoryCollectionBuilder DataValueReferenceFactories(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the property value converters collection builder.
+ ///
+ /// The builder.
+ public static PropertyValueConverterCollectionBuilder PropertyValueConverters(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the url segment providers collection builder.
+ ///
+ /// The builder.
+ public static UrlSegmentProviderCollectionBuilder UrlSegmentProviders(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the validators collection builder.
+ ///
+ /// The builder.
+ internal static ManifestValueValidatorCollectionBuilder ManifestValueValidators(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the manifest filter collection builder.
+ ///
+ /// The builder.
+ public static ManifestFilterCollectionBuilder ManifestFilters(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the content finders collection builder.
+ ///
+ /// The builder.
+ public static MediaUrlGeneratorCollectionBuilder MediaUrlGenerators(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the backoffice OEmbed Providers collection builder.
+ ///
+ /// The builder.
+ public static EmbedProvidersCollectionBuilder OEmbedProviders(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+
+ ///
+ /// Gets the back office searchable tree collection builder
+ ///
+ public static SearchableTreeCollectionBuilder SearchableTrees(this IUmbracoBuilder builder)
+ => builder.WithCollectionBuilder();
+ }
+}
diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs
new file mode 100644
index 0000000000..5bd2fe9e8c
--- /dev/null
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Composers.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.Extensions.Logging;
+using Umbraco.Core.Composing;
+
+namespace Umbraco.Core.DependencyInjection
+{
+ ///
+ /// Extension methods for
+ ///
+ public static partial class UmbracoBuilderExtensions
+ {
+ ///
+ /// Adds Umbraco composers for plugins
+ ///
+ public static IUmbracoBuilder AddComposers(this IUmbracoBuilder builder)
+ {
+ // TODO: Should have a better name
+
+ IEnumerable composerTypes = builder.TypeLoader.GetTypes();
+ IEnumerable enableDisable = builder.TypeLoader.GetAssemblyAttributes(typeof(EnableComposerAttribute), typeof(DisableComposerAttribute));
+ new Composers(builder, composerTypes, enableDisable, builder.BuilderLoggerFactory.CreateLogger()).Compose();
+
+ return builder;
+ }
+ }
+}
diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs
new file mode 100644
index 0000000000..a31a44beeb
--- /dev/null
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs
@@ -0,0 +1,52 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Umbraco.Core.Configuration.Models;
+using Umbraco.Core.Configuration.Models.Validation;
+
+namespace Umbraco.Core.DependencyInjection
+{
+ ///
+ /// Extension methods for
+ ///
+ public static partial class UmbracoBuilderExtensions
+ {
+ ///
+ /// Add Umbraco configuration services and options
+ ///
+ public static IUmbracoBuilder AddConfiguration(this IUmbracoBuilder builder)
+ {
+ // Register configuration validators.
+ builder.Services.AddSingleton, ContentSettingsValidator>();
+ builder.Services.AddSingleton, GlobalSettingsValidator>();
+ builder.Services.AddSingleton, HealthChecksSettingsValidator>();
+ builder.Services.AddSingleton, RequestHandlerSettingsValidator>();
+
+ // Register configuration sections.
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigActiveDirectory));
+ builder.Services.Configure(builder.Config.GetSection("ConnectionStrings"), o => o.BindNonPublicProperties = true);
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigContent));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigCoreDebug));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigExceptionFilter));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigGlobal));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigHealthChecks));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigHosting));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigImaging));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigExamine));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigKeepAlive));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigLogging));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigMemberPassword));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigModelsBuilder), o => o.BindNonPublicProperties = true);
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigNuCache));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigRequestHandler));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigRuntime));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigSecurity));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigTours));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigTypeFinder));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigUserPassword));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigWebRouting));
+ builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigPlugins));
+
+ return builder;
+ }
+ }
+}
diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs
index a21ae74976..c24936b4fb 100644
--- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs
@@ -2,6 +2,7 @@
// See LICENSE for more details.
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
using Umbraco.Core.Events;
namespace Umbraco.Core.DependencyInjection
@@ -23,7 +24,15 @@ namespace Umbraco.Core.DependencyInjection
where TNotification : INotification
{
// Register the handler as transient. This ensures that anything can be injected into it.
- builder.Services.AddTransient(typeof(INotificationHandler), typeof(TNotificationHandler));
+ var descriptor = new ServiceDescriptor(typeof(INotificationHandler), typeof(TNotificationHandler), ServiceLifetime.Transient);
+
+ // TODO: Waiting on feedback here https://github.com/umbraco/Umbraco-CMS/pull/9556/files#r548365396 about whether
+ // we perform this duplicate check or not.
+ if (!builder.Services.Contains(descriptor))
+ {
+ builder.Services.Add(descriptor);
+ }
+
return builder;
}
}
diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
index d56712cdcf..96f01d111a 100644
--- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
@@ -3,28 +3,65 @@
using System;
using System.Collections.Generic;
+using System.Runtime.InteropServices;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.Extensions.Options;
+using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Configuration.Grid;
+using Umbraco.Core.Configuration.Models;
+using Umbraco.Core.Diagnostics;
+using Umbraco.Core.Dictionary;
using Umbraco.Core.Events;
+using Umbraco.Core.Hosting;
+using Umbraco.Core.IO;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Mail;
+using Umbraco.Core.Manifest;
+using Umbraco.Core.Models.PublishedContent;
+using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Runtime;
+using Umbraco.Core.Security;
+using Umbraco.Core.Services;
+using Umbraco.Core.Sync;
+using Umbraco.Web;
+using Umbraco.Web.Cache;
+using Umbraco.Web.Editors;
+using Umbraco.Web.Features;
+using Umbraco.Web.Install;
+using Umbraco.Web.Models.PublishedContent;
+using Umbraco.Web.Routing;
+using Umbraco.Web.Services;
+using Umbraco.Web.Templates;
namespace Umbraco.Core.DependencyInjection
{
public class UmbracoBuilder : IUmbracoBuilder
{
- public IServiceCollection Services { get; }
- public IConfiguration Config { get; }
- public TypeLoader TypeLoader { get; }
- public ILoggerFactory BuilderLoggerFactory { get; }
-
private readonly Dictionary _builders = new Dictionary();
+ public IServiceCollection Services { get; }
+
+ public IConfiguration Config { get; }
+
+ public TypeLoader TypeLoader { get; }
+
+ public ILoggerFactory BuilderLoggerFactory { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
public UmbracoBuilder(IServiceCollection services, IConfiguration config, TypeLoader typeLoader)
: this(services, config, typeLoader, NullLoggerFactory.Instance)
{ }
+ ///
+ /// Initializes a new instance of the class.
+ ///
public UmbracoBuilder(IServiceCollection services, IConfiguration config, TypeLoader typeLoader, ILoggerFactory loggerFactory)
{
Services = services;
@@ -43,10 +80,12 @@ namespace Umbraco.Core.DependencyInjection
public TBuilder WithCollectionBuilder()
where TBuilder : ICollectionBuilder, new()
{
- var typeOfBuilder = typeof(TBuilder);
+ Type typeOfBuilder = typeof(TBuilder);
- if (_builders.TryGetValue(typeOfBuilder, out var o))
+ if (_builders.TryGetValue(typeOfBuilder, out ICollectionBuilder o))
+ {
return (TBuilder)o;
+ }
var builder = new TBuilder();
_builders[typeOfBuilder] = builder;
@@ -55,8 +94,10 @@ namespace Umbraco.Core.DependencyInjection
public void Build()
{
- foreach (var builder in _builders.Values)
+ foreach (ICollectionBuilder builder in _builders.Values)
+ {
builder.RegisterWith(Services);
+ }
_builders.Clear();
}
@@ -66,6 +107,115 @@ namespace Umbraco.Core.DependencyInjection
// Register as singleton to allow injection everywhere.
Services.AddSingleton(p => p.GetService);
Services.AddSingleton();
+
+ Services.AddLazySupport();
+
+ // Adds no-op registrations as many core services require these dependencies but these
+ // dependencies cannot be fulfilled in the Core project
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+
+ Services.AddUnique(factory =>
+ {
+ IHostingEnvironment hostingEnvironment = factory.GetRequiredService();
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ return new IOHelperLinux(hostingEnvironment);
+ }
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ return new IOHelperOSX(hostingEnvironment);
+ }
+
+ return new IOHelperWindows(hostingEnvironment);
+ });
+
+ Services.AddUnique(factory => factory.GetRequiredService().RuntimeCache);
+ Services.AddUnique(factory => factory.GetRequiredService().RequestCache);
+ Services.AddUnique();
+ Services.AddUnique();
+
+ this.AddAllCoreCollectionBuilders();
+ this.AddNotificationHandler();
+
+ Services.AddSingleton();
+ this.AddNotificationHandler();
+
+ Services.AddUnique();
+
+ // by default, register a noop factory
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddSingleton(f => f.GetRequiredService().CreateDictionary());
+
+ Services.AddUnique();
+
+ Services.AddUnique();
+
+ // will be injected in controllers when needed to invoke rest endpoints on Our
+ Services.AddUnique();
+ Services.AddUnique();
+
+ // Grid config is not a real config file as we know them
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+
+ // register properties fallback
+ Services.AddUnique();
+
+ Services.AddUnique();
+
+ // register published router
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+
+ // register distributed cache
+ Services.AddUnique(f => new DistributedCache(f.GetRequiredService(), f.GetRequiredService()));
+
+ // register the http context and umbraco context accessors
+ // we *should* use the HttpContextUmbracoContextAccessor, however there are cases when
+ // we have no http context, eg when booting Umbraco or in background threads, so instead
+ // let's use an hybrid accessor that can fall back to a ThreadStatic context.
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+ Services.AddUnique();
+
+ Services.AddUnique();
+ Services.AddUnique();
+
+ // register a server registrar, by default it's the db registrar
+ Services.AddUnique(f =>
+ {
+ GlobalSettings globalSettings = f.GetRequiredService>().Value;
+ var singleServer = globalSettings.DisableElectionForSingleServer;
+ return singleServer
+ ? (IServerRoleAccessor)new SingleServerRoleAccessor()
+ : new ElectedServerRoleAccessor(f.GetRequiredService());
+ });
}
}
}
diff --git a/src/Umbraco.Core/Diagnostics/NoopMarchal.cs b/src/Umbraco.Core/Diagnostics/NoopMarchal.cs
new file mode 100644
index 0000000000..09629f9595
--- /dev/null
+++ b/src/Umbraco.Core/Diagnostics/NoopMarchal.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Umbraco.Core.Diagnostics
+{
+ internal class NoopMarchal : IMarchal
+ {
+ public IntPtr GetExceptionPointers() => IntPtr.Zero;
+ }
+}
diff --git a/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
index d29f3ccb0b..ad92886ecd 100644
--- a/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
+++ b/src/Umbraco.Core/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
@@ -5,6 +5,7 @@ using Microsoft.Extensions.Options;
using Umbraco.Core;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.HealthCheck;
+using Umbraco.Core.Mail;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Infrastructure.HealthCheck;
diff --git a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs
similarity index 73%
rename from src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs
rename to src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs
index a032720d46..a4368a2634 100644
--- a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs
+++ b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs
@@ -1,25 +1,20 @@
using System;
-namespace Umbraco.Net
+namespace Umbraco.Core.Hosting
{
- // TODO: This shouldn't be in this namespace?
public interface IUmbracoApplicationLifetime
{
///
/// A value indicating whether the application is restarting after the current request.
///
bool IsRestarting { get; }
+
///
/// Terminates the current application. The application restarts the next time a request is received for it.
///
void Restart();
+ // TODO: Should be killed and replaced with UmbracoApplicationStarting notifications
event EventHandler ApplicationInit;
}
-
-
- public interface IUmbracoApplicationLifetimeManager
- {
- void InvokeApplicationInit();
- }
}
diff --git a/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetimeManager.cs b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetimeManager.cs
new file mode 100644
index 0000000000..778edc24dd
--- /dev/null
+++ b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetimeManager.cs
@@ -0,0 +1,8 @@
+namespace Umbraco.Core.Hosting
+{
+ // TODO: Should be killed and replaced with UmbracoApplicationStarting notifications
+ public interface IUmbracoApplicationLifetimeManager
+ {
+ void InvokeApplicationInit();
+ }
+}
diff --git a/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs b/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs
new file mode 100644
index 0000000000..3ffef04410
--- /dev/null
+++ b/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs
@@ -0,0 +1,8 @@
+namespace Umbraco.Core.Hosting
+{
+ internal class NoopApplicationShutdownRegistry : IApplicationShutdownRegistry
+ {
+ public void RegisterObject(IRegisteredObject registeredObject) { }
+ public void UnregisterObject(IRegisteredObject registeredObject) { }
+ }
+}
diff --git a/src/Umbraco.Core/Hosting/NoopUmbracoApplicationLifetimeManager.cs b/src/Umbraco.Core/Hosting/NoopUmbracoApplicationLifetimeManager.cs
new file mode 100644
index 0000000000..7833fd1224
--- /dev/null
+++ b/src/Umbraco.Core/Hosting/NoopUmbracoApplicationLifetimeManager.cs
@@ -0,0 +1,7 @@
+namespace Umbraco.Core.Hosting
+{
+ internal class NoopUmbracoApplicationLifetimeManager : IUmbracoApplicationLifetimeManager
+ {
+ public void InvokeApplicationInit() { }
+ }
+}
diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs
index b078172213..62f46edce4 100644
--- a/src/Umbraco.Core/IO/FileSystems.cs
+++ b/src/Umbraco.Core/IO/FileSystems.cs
@@ -6,6 +6,7 @@ using Microsoft.Extensions.Logging;
using Umbraco.Core.Hosting;
using Umbraco.Core.Configuration.Models;
using Microsoft.Extensions.Options;
+using Umbraco.Core.DependencyInjection;
namespace Umbraco.Core.IO
{
diff --git a/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs
index e3cd56c5c1..4866c472e6 100644
--- a/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs
+++ b/src/Umbraco.Core/Install/InstallSteps/StarterKitInstallStep.cs
@@ -2,9 +2,9 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
+using Umbraco.Core.Hosting;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
-using Umbraco.Net;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install.InstallSteps
diff --git a/src/Umbraco.Core/Logging/VoidProfiler.cs b/src/Umbraco.Core/Logging/NoopProfiler.cs
similarity index 89%
rename from src/Umbraco.Core/Logging/VoidProfiler.cs
rename to src/Umbraco.Core/Logging/NoopProfiler.cs
index d771fd7630..e7b43e5e2d 100644
--- a/src/Umbraco.Core/Logging/VoidProfiler.cs
+++ b/src/Umbraco.Core/Logging/NoopProfiler.cs
@@ -1,8 +1,8 @@
-using System;
+using System;
namespace Umbraco.Core.Logging
{
- public class VoidProfiler : IProfiler
+ public class NoopProfiler : IProfiler
{
private readonly VoidDisposable _disposable = new VoidDisposable();
diff --git a/src/Umbraco.Core/IEmailSender.cs b/src/Umbraco.Core/Mail/IEmailSender.cs
similarity index 78%
rename from src/Umbraco.Core/IEmailSender.cs
rename to src/Umbraco.Core/Mail/IEmailSender.cs
index aab944e04d..3862d0e717 100644
--- a/src/Umbraco.Core/IEmailSender.cs
+++ b/src/Umbraco.Core/Mail/IEmailSender.cs
@@ -1,7 +1,7 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Umbraco.Core.Models;
-namespace Umbraco.Core
+namespace Umbraco.Core.Mail
{
///
/// Simple abstraction to send an email message
diff --git a/src/Umbraco.Core/ISmsSender.cs b/src/Umbraco.Core/Mail/ISmsSender.cs
similarity index 84%
rename from src/Umbraco.Core/ISmsSender.cs
rename to src/Umbraco.Core/Mail/ISmsSender.cs
index f296a2ea9b..a2ff054c48 100644
--- a/src/Umbraco.Core/ISmsSender.cs
+++ b/src/Umbraco.Core/Mail/ISmsSender.cs
@@ -1,6 +1,6 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
-namespace Umbraco.Core
+namespace Umbraco.Core.Mail
{
///
/// Service to send an SMS
diff --git a/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs b/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs
new file mode 100644
index 0000000000..bb8d787cbf
--- /dev/null
+++ b/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Threading.Tasks;
+using Umbraco.Core.Models;
+
+namespace Umbraco.Core.Mail
+{
+ internal class NotImplementedEmailSender : IEmailSender
+ {
+ public Task SendAsync(EmailMessage message)
+ => throw new NotImplementedException("To send an Email ensure IEmailSender is implemented with a custom implementation");
+ }
+}
diff --git a/src/Umbraco.Infrastructure/NotImplementedSmsSender.cs b/src/Umbraco.Core/Mail/NotImplementedSmsSender.cs
similarity index 90%
rename from src/Umbraco.Infrastructure/NotImplementedSmsSender.cs
rename to src/Umbraco.Core/Mail/NotImplementedSmsSender.cs
index ffc33373d0..16c3d04711 100644
--- a/src/Umbraco.Infrastructure/NotImplementedSmsSender.cs
+++ b/src/Umbraco.Core/Mail/NotImplementedSmsSender.cs
@@ -1,7 +1,7 @@
-using System;
+using System;
using System.Threading.Tasks;
-namespace Umbraco.Core
+namespace Umbraco.Core.Mail
{
///
/// An that throws
diff --git a/src/Umbraco.Core/Manifest/ManifestWatcher.cs b/src/Umbraco.Core/Manifest/ManifestWatcher.cs
index e74393a179..b6cd82b31f 100644
--- a/src/Umbraco.Core/Manifest/ManifestWatcher.cs
+++ b/src/Umbraco.Core/Manifest/ManifestWatcher.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Extensions.Logging;
-using Umbraco.Net;
+using Umbraco.Core.Hosting;
namespace Umbraco.Core.Manifest
{
diff --git a/src/Umbraco.Infrastructure/Media/IImageDimensionExtractor.cs b/src/Umbraco.Core/Media/IImageDimensionExtractor.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/IImageDimensionExtractor.cs
rename to src/Umbraco.Core/Media/IImageDimensionExtractor.cs
diff --git a/src/Umbraco.Infrastructure/Media/ImageSize.cs b/src/Umbraco.Core/Media/ImageSize.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/ImageSize.cs
rename to src/Umbraco.Core/Media/ImageSize.cs
diff --git a/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs b/src/Umbraco.Core/Media/UploadAutoFillProperties.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs
rename to src/Umbraco.Core/Media/UploadAutoFillProperties.cs
diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs
index 2149ece02a..a3c02aeb0d 100644
--- a/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs
+++ b/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs
@@ -1,11 +1,9 @@
-using System.Linq;
+using System.Linq;
using Umbraco.Core.Composing;
using Umbraco.Core.Manifest;
namespace Umbraco.Core.PropertyEditors
{
-
-
public class PropertyEditorCollection : BuilderCollectionBase
{
public PropertyEditorCollection(DataEditorCollection dataEditors, IManifestParser manifestParser)
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/TextStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs
similarity index 100%
rename from src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/TextStringValueConverter.cs
rename to src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TinyMceValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs
similarity index 95%
rename from src/Umbraco.Core/PropertyEditors/ValueConverters/TinyMceValueConverter.cs
rename to src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs
index 51471f6da7..64ecba5c7c 100644
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TinyMceValueConverter.cs
+++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Strings;
@@ -8,7 +8,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
/// Value converter for the RTE so that it always returns IHtmlString so that Html.Raw doesn't have to be used.
///
[DefaultPropertyValueConverter]
- public class TinyMceValueConverter : PropertyValueConverterBase
+ public class SimpleTinyMceValueConverter : PropertyValueConverterBase
{
public override bool IsConverter(IPublishedPropertyType propertyType)
=> propertyType.EditorAlias == Constants.PropertyEditors.Aliases.TinyMce;
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueConverter.cs
deleted file mode 100644
index 7caa9a90cc..0000000000
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueConverter.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System;
-using System.Linq;
-using Umbraco.Core.Models.PublishedContent;
-
-namespace Umbraco.Core.PropertyEditors.ValueConverters
-{
- [DefaultPropertyValueConverter]
- public class TextStringValueConverter : PropertyValueConverterBase
- {
- private static readonly string[] PropertyTypeAliases =
- {
- Constants.PropertyEditors.Aliases.TextBox,
- Constants.PropertyEditors.Aliases.TextArea
- };
-
- public override bool IsConverter(IPublishedPropertyType propertyType)
- => PropertyTypeAliases.Contains(propertyType.EditorAlias);
-
- public override Type GetPropertyValueType(IPublishedPropertyType propertyType)
- => typeof (string);
-
- public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType)
- => PropertyCacheLevel.Element;
-
- public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview)
- {
- // in xml a string is: string
- // in the database a string is: string
- // default value is: null
- return source;
- }
-
- public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
- {
- // source should come from ConvertSource and be a string (or null) already
- return inter ?? string.Empty;
- }
-
- public override object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
- {
- // source should come from ConvertSource and be a string (or null) already
- return inter;
- }
- }
-}
diff --git a/src/Umbraco.Core/ITagQuery.cs b/src/Umbraco.Core/PublishedCache/ITagQuery.cs
similarity index 100%
rename from src/Umbraco.Core/ITagQuery.cs
rename to src/Umbraco.Core/PublishedCache/ITagQuery.cs
diff --git a/src/Umbraco.Infrastructure/Runtime/AppPluginsManifestWatcherNotificationHandler.cs b/src/Umbraco.Core/Runtime/AppPluginsManifestWatcherNotificationHandler.cs
similarity index 96%
rename from src/Umbraco.Infrastructure/Runtime/AppPluginsManifestWatcherNotificationHandler.cs
rename to src/Umbraco.Core/Runtime/AppPluginsManifestWatcherNotificationHandler.cs
index b67f41136a..5f219ac51f 100644
--- a/src/Umbraco.Infrastructure/Runtime/AppPluginsManifestWatcherNotificationHandler.cs
+++ b/src/Umbraco.Core/Runtime/AppPluginsManifestWatcherNotificationHandler.cs
@@ -2,12 +2,11 @@ using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
-using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Hosting;
using Umbraco.Core.Manifest;
-namespace Umbraco.Infrastructure.Runtime
+namespace Umbraco.Core.Runtime
{
///
/// Starts monitoring AppPlugins directory during debug runs, to restart site when a plugin manifest changes.
diff --git a/src/Umbraco.Infrastructure/Runtime/EssentialDirectoryCreator.cs b/src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs
similarity index 96%
rename from src/Umbraco.Infrastructure/Runtime/EssentialDirectoryCreator.cs
rename to src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs
index 5543662464..92ad5808b3 100644
--- a/src/Umbraco.Infrastructure/Runtime/EssentialDirectoryCreator.cs
+++ b/src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs
@@ -1,13 +1,12 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
-using Umbraco.Core;
using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Events;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
-namespace Umbraco.Infrastructure.Runtime
+namespace Umbraco.Core.Runtime
{
public class EssentialDirectoryCreator : INotificationHandler
{
diff --git a/src/Umbraco.Infrastructure/Runtime/MainDomSemaphoreLock.cs b/src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs
similarity index 92%
rename from src/Umbraco.Infrastructure/Runtime/MainDomSemaphoreLock.cs
rename to src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs
index eed13f5060..74dea6742c 100644
--- a/src/Umbraco.Infrastructure/Runtime/MainDomSemaphoreLock.cs
+++ b/src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Runtime
_logger = logger;
}
- //WaitOneAsync (ext method) will wait for a signal without blocking the main thread, the waiting is done on a background thread
+ // WaitOneAsync (ext method) will wait for a signal without blocking the main thread, the waiting is done on a background thread
public Task ListenAsync() => _signal.WaitOneAsync();
public Task AcquireLockAsync(int millisecondsTimeout)
@@ -44,7 +44,7 @@ namespace Umbraco.Core.Runtime
// if more than 1 instance reach that point, one will get the lock
// and the other one will timeout, which is accepted
- //This can throw a TimeoutException - in which case should this be in a try/finally to ensure the signal is always reset.
+ // This can throw a TimeoutException - in which case should this be in a try/finally to ensure the signal is always reset.
try
{
_lockRelease = _systemLock.Lock(millisecondsTimeout);
diff --git a/src/Umbraco.Core/Services/Implement/DashboardService.cs b/src/Umbraco.Core/Services/DashboardService.cs
similarity index 100%
rename from src/Umbraco.Core/Services/Implement/DashboardService.cs
rename to src/Umbraco.Core/Services/DashboardService.cs
diff --git a/src/Umbraco.Core/Services/IServerRegistrationService.cs b/src/Umbraco.Core/Services/IServerRegistrationService.cs
index 62bb68eb14..f0246dd287 100644
--- a/src/Umbraco.Core/Services/IServerRegistrationService.cs
+++ b/src/Umbraco.Core/Services/IServerRegistrationService.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using Umbraco.Core.Models;
using Umbraco.Core.Sync;
@@ -11,9 +11,8 @@ namespace Umbraco.Core.Services
/// Touches a server to mark it as active; deactivate stale servers.
///
/// The server URL.
- /// The server unique identity.
/// The time after which a server is considered stale.
- void TouchServer(string serverAddress, string serverIdentity, TimeSpan staleTimeout);
+ void TouchServer(string serverAddress, TimeSpan staleTimeout);
///
/// Deactivates a server.
@@ -38,11 +37,6 @@ namespace Umbraco.Core.Services
/// from the database.
IEnumerable GetActiveServers(bool refresh = false);
- ///
- /// Gets the current server identity.
- ///
- string CurrentServerIdentity { get; }
-
///
/// Gets the role of the current server.
///
diff --git a/src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs b/src/Umbraco.Core/Services/InstallationService.cs
similarity index 87%
rename from src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs
rename to src/Umbraco.Core/Services/InstallationService.cs
index a1f74e0862..6e283a61d7 100644
--- a/src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs
+++ b/src/Umbraco.Core/Services/InstallationService.cs
@@ -1,8 +1,8 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Repositories;
-namespace Umbraco.Core.Services.Implement
+namespace Umbraco.Core.Services
{
public class InstallationService : IInstallationService
{
diff --git a/src/Umbraco.Core/Services/UpgradeService.cs b/src/Umbraco.Core/Services/UpgradeService.cs
index ead5270b41..b36eac7789 100644
--- a/src/Umbraco.Core/Services/UpgradeService.cs
+++ b/src/Umbraco.Core/Services/UpgradeService.cs
@@ -1,10 +1,9 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Semver;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Repositories;
-using Umbraco.Core.Services;
-namespace Umbraco.Core
+namespace Umbraco.Core.Services
{
public class UpgradeService : IUpgradeService
{
diff --git a/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs b/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs
index 7438762295..f7dafac7a6 100644
--- a/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs
+++ b/src/Umbraco.Core/Sync/DatabaseServerMessengerCallbacks.cs
@@ -1,10 +1,10 @@
-using System;
+using System;
using System.Collections.Generic;
namespace Umbraco.Core.Sync
{
///
- /// Holds a list of callbacks associated with implementations of .
+ /// Holds a list of callbacks associated with implementations of .
///
public class DatabaseServerMessengerCallbacks
{
diff --git a/src/Umbraco.Core/Sync/DatabaseServerRegistrar.cs b/src/Umbraco.Core/Sync/DatabaseServerRegistrar.cs
deleted file mode 100644
index f361eb7a67..0000000000
--- a/src/Umbraco.Core/Sync/DatabaseServerRegistrar.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Umbraco.Core.Services;
-
-namespace Umbraco.Core.Sync
-{
- ///
- /// A registrar that stores registered server nodes in the database.
- ///
- ///
- /// This is the default registrar which determines a server's role by using a master election process.
- /// The master election process doesn't occur until just after startup so this election process doesn't really affect the primary startup phase.
- ///
- public sealed class DatabaseServerRegistrar : IServerRegistrar
- {
- private readonly Lazy _registrationService;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The registration service.
- /// Some options.
- public DatabaseServerRegistrar(Lazy registrationService)
- {
- _registrationService = registrationService ?? throw new ArgumentNullException(nameof(registrationService));
- }
-
- ///
- /// Gets the registered servers.
- ///
- public IEnumerable Registrations => _registrationService.Value.GetActiveServers();
-
- ///
- /// Gets the role of the current server in the application environment.
- ///
- public ServerRole GetCurrentServerRole()
- {
- var service = _registrationService.Value;
- return service.GetCurrentServerRole();
- }
-
- }
-}
diff --git a/src/Umbraco.Core/Sync/ElectedServerRoleAccessor.cs b/src/Umbraco.Core/Sync/ElectedServerRoleAccessor.cs
new file mode 100644
index 0000000000..e4accd046b
--- /dev/null
+++ b/src/Umbraco.Core/Sync/ElectedServerRoleAccessor.cs
@@ -0,0 +1,29 @@
+using System;
+using Umbraco.Core.Services;
+
+namespace Umbraco.Core.Sync
+{
+ ///
+ /// Gets the current server's based on active servers registered with
+ ///
+ ///
+ /// This is the default service which determines a server's role by using a master election process.
+ /// The master election process doesn't occur until just after startup so this election process doesn't really affect the primary startup phase.
+ ///
+ public sealed class ElectedServerRoleAccessor : IServerRoleAccessor
+ {
+ private readonly IServerRegistrationService _registrationService;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The registration service.
+ /// Some options.
+ public ElectedServerRoleAccessor(IServerRegistrationService registrationService) => _registrationService = registrationService ?? throw new ArgumentNullException(nameof(registrationService));
+
+ ///
+ /// Gets the role of the current server in the application environment.
+ ///
+ public ServerRole CurrentServerRole => _registrationService.GetCurrentServerRole();
+ }
+}
diff --git a/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs
deleted file mode 100644
index 560b7fb235..0000000000
--- a/src/Umbraco.Core/Sync/IBatchedDatabaseServerMessenger.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Umbraco.Core.Sync
-{
- ///
- /// An implementation that works by storing messages in the database.
- ///
- public interface IBatchedDatabaseServerMessenger : IDatabaseServerMessenger
- {
- void FlushBatch();
- DatabaseServerMessengerCallbacks Callbacks { get; }
- void Startup();
- }
-}
diff --git a/src/Umbraco.Core/Sync/IDatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/IDatabaseServerMessenger.cs
deleted file mode 100644
index a49cfdd023..0000000000
--- a/src/Umbraco.Core/Sync/IDatabaseServerMessenger.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Umbraco.Core.Sync
-{
- public interface IDatabaseServerMessenger: IServerMessenger
- {
- void Sync();
- }
-}
diff --git a/src/Umbraco.Core/Sync/IServerMessenger.cs b/src/Umbraco.Core/Sync/IServerMessenger.cs
index b8300b2d6d..df2d665057 100644
--- a/src/Umbraco.Core/Sync/IServerMessenger.cs
+++ b/src/Umbraco.Core/Sync/IServerMessenger.cs
@@ -1,21 +1,30 @@
-using System;
-using System.Collections.Generic;
+using System;
using Umbraco.Core.Cache;
namespace Umbraco.Core.Sync
{
///
- /// Broadcasts distributed cache notifications to all servers of a load balanced environment.
+ /// Transmits distributed cache notifications for all servers of a load balanced environment.
///
/// Also ensures that the notification is processed on the local environment.
public interface IServerMessenger
{
+ ///
+ /// Called to synchronize a server with queued notifications
+ ///
+ void Sync();
+
+ ///
+ /// Called to send/commit the queued messages created with the Perform methods
+ ///
+ void SendMessages();
+
///
/// Notifies the distributed cache, for a specified .
///
/// The ICacheRefresher.
/// The notification content.
- void PerformRefresh(ICacheRefresher refresher, TPayload[] payload);
+ void QueueRefresh(ICacheRefresher refresher, TPayload[] payload);
///
/// Notifies the distributed cache of specified item invalidation, for a specified .
@@ -24,7 +33,7 @@ namespace Umbraco.Core.Sync
/// The ICacheRefresher.
/// A function returning the unique identifier of items.
/// The invalidated items.
- void PerformRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances);
+ void QueueRefresh(ICacheRefresher refresher, Func getNumericId, params T[] instances);
///
/// Notifies the distributed cache of specified item invalidation, for a specified .
@@ -33,7 +42,7 @@ namespace Umbraco.Core.Sync
/// The ICacheRefresher.
/// A function returning the unique identifier of items.
/// The invalidated items.
- void PerformRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances);
+ void QueueRefresh(ICacheRefresher refresher, Func getGuidId, params T[] instances);
///
/// Notifies all servers of specified items removal, for a specified .
@@ -42,33 +51,33 @@ namespace Umbraco.Core.Sync
/// The ICacheRefresher.
/// A function returning the unique identifier of items.
/// The removed items.
- void PerformRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances);
+ void QueueRemove(ICacheRefresher refresher, Func getNumericId, params T[] instances);
///
/// Notifies all servers of specified items removal, for a specified .
///
/// The ICacheRefresher.
/// The unique identifiers of the removed items.
- void PerformRemove(ICacheRefresher refresher, params int[] numericIds);
+ void QueueRemove(ICacheRefresher refresher, params int[] numericIds);
///
/// Notifies all servers of specified items invalidation, for a specified .
///
/// The ICacheRefresher.
/// The unique identifiers of the invalidated items.
- void PerformRefresh(ICacheRefresher refresher, params int[] numericIds);
+ void QueueRefresh(ICacheRefresher refresher, params int[] numericIds);
///
/// Notifies all servers of specified items invalidation, for a specified .
///
/// The ICacheRefresher.
/// The unique identifiers of the invalidated items.
- void PerformRefresh(ICacheRefresher refresher, params Guid[] guidIds);
+ void QueueRefresh(ICacheRefresher refresher, params Guid[] guidIds);
///
/// Notifies all servers of a global invalidation for a specified .
///
/// The ICacheRefresher.
- void PerformRefreshAll(ICacheRefresher refresher);
+ void QueueRefreshAll(ICacheRefresher refresher);
}
}
diff --git a/src/Umbraco.Core/Sync/IServerRegistrar.cs b/src/Umbraco.Core/Sync/IServerRegistrar.cs
deleted file mode 100644
index 780f865ad7..0000000000
--- a/src/Umbraco.Core/Sync/IServerRegistrar.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Collections.Generic;
-
-namespace Umbraco.Core.Sync
-{
- ///
- /// Provides server registrations to the distributed cache.
- ///
- public interface IServerRegistrar
- {
- ///
- /// Gets the server registrations.
- ///
- IEnumerable Registrations { get; }
-
- ///
- /// Gets the role of the current server in the application environment.
- ///
- ServerRole GetCurrentServerRole();
-
- }
-}
diff --git a/src/Umbraco.Core/Sync/IServerRoleAccessor.cs b/src/Umbraco.Core/Sync/IServerRoleAccessor.cs
new file mode 100644
index 0000000000..b23acbac7c
--- /dev/null
+++ b/src/Umbraco.Core/Sync/IServerRoleAccessor.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+
+namespace Umbraco.Core.Sync
+{
+ ///
+ /// Gets the current server's
+ ///
+ public interface IServerRoleAccessor
+ {
+ ///
+ /// Gets the role of the current server in the application environment.
+ ///
+ ServerRole CurrentServerRole { get; }
+ }
+}
diff --git a/src/Umbraco.Core/Sync/SingleServerRegistrar.cs b/src/Umbraco.Core/Sync/SingleServerRegistrar.cs
deleted file mode 100644
index fe03e195b2..0000000000
--- a/src/Umbraco.Core/Sync/SingleServerRegistrar.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Umbraco.Web;
-
-namespace Umbraco.Core.Sync
-{
- ///
- /// Can be used when Umbraco is definitely not operating in a Load Balanced scenario to micro-optimize some startup performance
- ///
- ///
- /// The micro optimization is specifically to avoid a DB query just after the app starts up to determine the
- /// which by default is done with master election by a database query. The master election process doesn't occur until just after startup
- /// so this micro optimization doesn't really affect the primary startup phase.
- ///
- public class SingleServerRegistrar : IServerRegistrar
- {
- private readonly IRequestAccessor _requestAccessor;
- private readonly Lazy _registrations;
-
- public IEnumerable Registrations => _registrations.Value;
-
- public SingleServerRegistrar(IRequestAccessor requestAccessor)
- {
- _requestAccessor = requestAccessor;
- _registrations = new Lazy(() => new IServerAddress[] { new ServerAddressImpl(_requestAccessor.GetApplicationUrl().ToString()) });
- }
-
- public ServerRole GetCurrentServerRole()
- {
- return ServerRole.Single;
- }
-
-
- private class ServerAddressImpl : IServerAddress
- {
- public ServerAddressImpl(string serverAddress)
- {
- ServerAddress = serverAddress;
- }
-
- public string ServerAddress { get; }
- }
- }
-}
diff --git a/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs b/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs
new file mode 100644
index 0000000000..65b9559522
--- /dev/null
+++ b/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using Umbraco.Web;
+
+namespace Umbraco.Core.Sync
+{
+ ///
+ /// Can be used when Umbraco is definitely not operating in a Load Balanced scenario to micro-optimize some startup performance
+ ///
+ ///
+ /// The micro optimization is specifically to avoid a DB query just after the app starts up to determine the
+ /// which by default is done with master election by a database query. The master election process doesn't occur until just after startup
+ /// so this micro optimization doesn't really affect the primary startup phase.
+ ///
+ public class SingleServerRoleAccessor : IServerRoleAccessor
+ {
+ public ServerRole CurrentServerRole => ServerRole.Single;
+ }
+}
diff --git a/src/Umbraco.Core/Trees/ISearchableTree.cs b/src/Umbraco.Core/Trees/ISearchableTree.cs
index 3d82d548c8..8f31c2c6ab 100644
--- a/src/Umbraco.Core/Trees/ISearchableTree.cs
+++ b/src/Umbraco.Core/Trees/ISearchableTree.cs
@@ -1,8 +1,8 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using Umbraco.Core.Composing;
using Umbraco.Web.Models.ContentEditing;
-namespace Umbraco.Web.Trees
+namespace Umbraco.Core.Trees
{
public interface ISearchableTree : IDiscoverable
{
diff --git a/src/Umbraco.Infrastructure/Search/SearchableApplicationTree.cs b/src/Umbraco.Core/Trees/SearchableApplicationTree.cs
similarity index 92%
rename from src/Umbraco.Infrastructure/Search/SearchableApplicationTree.cs
rename to src/Umbraco.Core/Trees/SearchableApplicationTree.cs
index 346f106b84..ad6fb7f43f 100644
--- a/src/Umbraco.Infrastructure/Search/SearchableApplicationTree.cs
+++ b/src/Umbraco.Core/Trees/SearchableApplicationTree.cs
@@ -1,6 +1,4 @@
-using Umbraco.Web.Trees;
-
-namespace Umbraco.Web.Search
+namespace Umbraco.Core.Trees
{
public class SearchableApplicationTree
{
diff --git a/src/Umbraco.Infrastructure/Search/SearchableTreeCollection.cs b/src/Umbraco.Core/Trees/SearchableTreeCollection.cs
similarity index 97%
rename from src/Umbraco.Infrastructure/Search/SearchableTreeCollection.cs
rename to src/Umbraco.Core/Trees/SearchableTreeCollection.cs
index 5c251a857d..e562b763d4 100644
--- a/src/Umbraco.Infrastructure/Search/SearchableTreeCollection.cs
+++ b/src/Umbraco.Core/Trees/SearchableTreeCollection.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
@@ -6,7 +6,7 @@ using Umbraco.Core.Composing;
using Umbraco.Web.Services;
using Umbraco.Web.Trees;
-namespace Umbraco.Web.Search
+namespace Umbraco.Core.Trees
{
public class SearchableTreeCollection : BuilderCollectionBase
{
diff --git a/src/Umbraco.Infrastructure/Search/SearchableTreeCollectionBuilder.cs b/src/Umbraco.Core/Trees/SearchableTreeCollectionBuilder.cs
similarity index 81%
rename from src/Umbraco.Infrastructure/Search/SearchableTreeCollectionBuilder.cs
rename to src/Umbraco.Core/Trees/SearchableTreeCollectionBuilder.cs
index a5e940b4a6..7922cf36ad 100644
--- a/src/Umbraco.Infrastructure/Search/SearchableTreeCollectionBuilder.cs
+++ b/src/Umbraco.Core/Trees/SearchableTreeCollectionBuilder.cs
@@ -1,8 +1,7 @@
-using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection;
using Umbraco.Core.Composing;
-using Umbraco.Web.Trees;
-namespace Umbraco.Web.Search
+namespace Umbraco.Core.Trees
{
public class SearchableTreeCollectionBuilder : LazyCollectionBuilderBase
{
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 24b2fae683..263621aed7 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -19,6 +19,7 @@
+
diff --git a/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs b/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs
index e2f2460d58..05315b05fe 100644
--- a/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs
+++ b/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs
@@ -1,5 +1,4 @@
using System.Runtime.InteropServices;
-using Umbraco.Core;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Composing;
diff --git a/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs
new file mode 100644
index 0000000000..5b4dd4f0ed
--- /dev/null
+++ b/src/Umbraco.Infrastructure/Cache/DatabaseServerMessengerNotificationHandler.cs
@@ -0,0 +1,96 @@
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using Umbraco.Core.Events;
+using Umbraco.Core.Persistence;
+using Umbraco.Core.Sync;
+using Umbraco.Web;
+using Umbraco.Web.Cache;
+using Umbraco.Web.Routing;
+
+namespace Umbraco.Infrastructure.Cache
+{
+ ///
+ /// Ensures that distributed cache events are setup and the is initialized
+ ///
+ public sealed class DatabaseServerMessengerNotificationHandler : INotificationHandler
+ {
+ private readonly IServerMessenger _messenger;
+ private readonly IRequestAccessor _requestAccessor;
+ private readonly IUmbracoDatabaseFactory _databaseFactory;
+ private readonly IDistributedCacheBinder _distributedCacheBinder;
+ private readonly ILogger _logger;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public DatabaseServerMessengerNotificationHandler(
+ IServerMessenger serverMessenger,
+ IRequestAccessor requestAccessor,
+ IUmbracoDatabaseFactory databaseFactory,
+ IDistributedCacheBinder distributedCacheBinder,
+ ILogger logger)
+ {
+ _requestAccessor = requestAccessor;
+ _databaseFactory = databaseFactory;
+ _distributedCacheBinder = distributedCacheBinder;
+ _logger = logger;
+ _messenger = serverMessenger;
+ }
+
+ ///
+ public Task HandleAsync(UmbracoApplicationStarting notification, CancellationToken cancellationToken)
+ {
+ // The scheduled tasks - TouchServerTask and InstructionProcessTask - run as .NET Core hosted services.
+ // The former (as well as other hosted services that run outside of an HTTP request context) depends on the application URL
+ // being available (via IRequestAccessor), which can only be retrieved within an HTTP request (unless it's explicitly configured).
+ // Hence we hook up a one-off task on an HTTP request to ensure this is retrieved, which caches the value and makes it available
+ // for the hosted services to use when the HTTP request is not available.
+ _requestAccessor.RouteAttempt += EnsureApplicationUrlOnce;
+ _requestAccessor.EndRequest += EndRequest;
+
+ Startup();
+
+ return Task.CompletedTask;
+ }
+
+ private void Startup()
+ {
+ if (_databaseFactory.CanConnect == false)
+ {
+ _logger.LogWarning("Cannot connect to the database, distributed calls will not be enabled for this server.");
+ }
+ else
+ {
+ _distributedCacheBinder.BindEvents();
+
+ // Sync on startup, this will run through the messenger's initialization sequence
+ _messenger?.Sync();
+ }
+ }
+
+ // TODO: I don't really know or think that the Application Url plays a role anymore with the DB dist cache,
+ // this might be really old stuff. I 'think' all this is doing is ensuring that the IRequestAccessor.GetApplicationUrl
+ // is definitely called during the first request. If that is still required, that logic doesn't belong here. That logic
+ // should be part of it's own service/middleware. There's also TODO notes within IRequestAccessor.GetApplicationUrl directly
+ // mentioning that the property doesn't belong on that service either. This should be investigated and resolved in a separate task.
+ private void EnsureApplicationUrlOnce(object sender, RoutableAttemptEventArgs e)
+ {
+ if (e.Outcome == EnsureRoutableOutcome.IsRoutable || e.Outcome == EnsureRoutableOutcome.NotDocumentRequest)
+ {
+ _requestAccessor.RouteAttempt -= EnsureApplicationUrlOnce;
+ EnsureApplicationUrl();
+ }
+ }
+
+ // By retrieving the application URL within the context of a request (as we are here in responding
+ // to the IRequestAccessor's RouteAttempt event), we'll get it from the HTTP context and save it for
+ // future requests that may not be within an HTTP request (e.g. from hosted services).
+ private void EnsureApplicationUrl() => _requestAccessor.GetApplicationUrl();
+
+ ///
+ /// Clear the batch on end request
+ ///
+ private void EndRequest(object sender, UmbracoRequestEventArgs e) => _messenger?.SendMessages();
+ }
+}
diff --git a/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs
deleted file mode 100644
index 7279eaf10c..0000000000
--- a/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Umbraco.Core;
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Composing;
-
-namespace Umbraco.Web.Cache
-{
- ///
- /// Installs listeners on service events in order to refresh our caches.
- ///
- [ComposeBefore(typeof(ICoreComposer))] // runs before every other IUmbracoCoreComponent!
- public sealed class DistributedCacheBinderComposer : ComponentComposer, ICoreComposer
- {
- public override void Compose(IUmbracoBuilder builder)
- {
- base.Compose(builder);
-
- builder.Services.AddUnique();
- }
- }
-}
diff --git a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs
deleted file mode 100644
index 8d2a2e19cc..0000000000
--- a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-using System;
-using Microsoft.Extensions.DependencyInjection;
-using Umbraco.Core;
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Composing;
-using Umbraco.Core.Services.Changes;
-using Umbraco.Core.Sync;
-using Umbraco.Web.Cache;
-using Umbraco.Web.PublishedCache;
-using Umbraco.Web.Routing;
-using Umbraco.Web.Search;
-
-namespace Umbraco.Web.Compose
-{
- ///
- /// Ensures that servers are automatically registered in the database, when using the database server registrar.
- ///
- ///
- /// At the moment servers are automatically registered upon first request and then on every
- /// request but not more than once per (configurable) period. This really is "for information & debug" purposes so
- /// we can look at the table and see what servers are registered - but the info is not used anywhere.
- /// Should we actually want to use this, we would need a better and more deterministic way of figuring
- /// out the "server address" ie the address to which server-to-server requests should be sent - because it
- /// probably is not the "current request address" - especially in multi-domains configurations.
- ///
- // during Initialize / Startup, we end up checking Examine, which needs to be initialized beforehand
- // TODO: should not be a strong dependency on "examine" but on an "indexing component"
- [ComposeAfter(typeof(ExamineComposer))]
-
- public sealed class DatabaseServerRegistrarAndMessengerComposer : ComponentComposer, ICoreComposer
- {
- public static DatabaseServerMessengerCallbacks GetCallbacks(IServiceProvider factory)
- {
- return new DatabaseServerMessengerCallbacks
- {
- //These callbacks will be executed if the server has not been synced
- // (i.e. it is a new server or the lastsynced.txt file has been removed)
- InitializingCallbacks = new Action[]
- {
- //rebuild the xml cache file if the server is not synced
- () =>
- {
- var publishedSnapshotService = factory.GetRequiredService();
-
- // rebuild the published snapshot caches entirely, if the server is not synced
- // this is equivalent to DistributedCache RefreshAll... but local only
- // (we really should have a way to reuse RefreshAll... locally)
- // note: refresh all content & media caches does refresh content types too
- publishedSnapshotService.Notify(new[] { new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll) });
- publishedSnapshotService.Notify(new[] { new ContentCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) }, out _, out _);
- publishedSnapshotService.Notify(new[] { new MediaCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) }, out _);
- },
-
- //rebuild indexes if the server is not synced
- // NOTE: This will rebuild ALL indexes including the members, if developers want to target specific
- // indexes then they can adjust this logic themselves.
- () =>
- {
- var indexRebuilder = factory.GetRequiredService();
- indexRebuilder.RebuildIndexes(false, 5000);
- }
- }
- };
- }
-
- public override void Compose(IUmbracoBuilder builder)
- {
- base.Compose(builder);
-
- builder.SetDatabaseServerMessengerCallbacks(GetCallbacks);
- builder.SetServerMessenger();
- }
- }
-
- public sealed class DatabaseServerRegistrarAndMessengerComponent : IComponent
- {
- private readonly IBatchedDatabaseServerMessenger _messenger;
- private readonly IRequestAccessor _requestAccessor;
-
- public DatabaseServerRegistrarAndMessengerComponent(
- IServerMessenger serverMessenger,
- IRequestAccessor requestAccessor)
- {
- _requestAccessor = requestAccessor;
- _messenger = serverMessenger as IBatchedDatabaseServerMessenger;
- }
-
- public void Initialize()
- {
- // The scheduled tasks - TouchServerTask and InstructionProcessTask - run as .NET Core hosted services.
- // The former (as well as other hosted services that run outside of an HTTP request context) depends on the application URL
- // being available (via IRequestAccessor), which can only be retrieved within an HTTP request (unless it's explicitly configured).
- // Hence we hook up a one-off task on an HTTP request to ensure this is retrieved, which caches the value and makes it available
- // for the hosted services to use when the HTTP request is not available.
- _requestAccessor.RouteAttempt += EnsureApplicationUrlOnce;
-
- // Must come last, as it references some _variables
- _messenger?.Startup();
- }
-
- public void Terminate()
- { }
-
- private void EnsureApplicationUrlOnce(object sender, RoutableAttemptEventArgs e)
- {
- if (e.Outcome == EnsureRoutableOutcome.IsRoutable || e.Outcome == EnsureRoutableOutcome.NotDocumentRequest)
- {
- _requestAccessor.RouteAttempt -= EnsureApplicationUrlOnce;
- EnsureApplicationUrl();
- }
- }
-
- private void EnsureApplicationUrl()
- {
- // By retrieving the application URL within the context of a request (as we are here in responding
- // to the IRequestAccessor's RouteAttempt event), we'll get it from the HTTP context and save it for
- // future requests that may not be within an HTTP request (e.g. from hosted services).
- _requestAccessor.GetApplicationUrl();
- }
- }
-}
diff --git a/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs b/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs
index 0fee815560..79066dedd7 100644
--- a/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs
+++ b/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs
@@ -1,5 +1,4 @@
-using Umbraco.Core;
-using Umbraco.Core.DependencyInjection;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Composing;
namespace Umbraco.Web.Compose
diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs
deleted file mode 100644
index 31b3133e4d..0000000000
--- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using Microsoft.Extensions.DependencyInjection;
-using Umbraco.Core;
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Composing;
-using Umbraco.Web.Install;
-using Umbraco.Web.Install.InstallSteps;
-using Umbraco.Web.Install.Models;
-
-namespace Umbraco.Web.Composing.CompositionExtensions
-{
- public static class Installer
- {
- public static IUmbracoBuilder ComposeInstaller(this IUmbracoBuilder builder)
- {
- // register the installer steps
-
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
-
- // TODO: Add these back once we have a compatible Starter kit
- // composition.Services.AddScoped();
- // composition.Services.AddScoped();
- // composition.Services.AddScoped