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.Tests.Integration/ComponentRuntimeTests.cs b/src/Umbraco.Tests.Integration/ComponentRuntimeTests.cs
new file mode 100644
index 0000000000..ba6c6473fa
--- /dev/null
+++ b/src/Umbraco.Tests.Integration/ComponentRuntimeTests.cs
@@ -0,0 +1,76 @@
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using NUnit.Framework;
+using Umbraco.Core;
+using Umbraco.Core.Cache;
+using Umbraco.Core.Composing;
+using Umbraco.Core.DependencyInjection;
+using Umbraco.Extensions;
+using Umbraco.Infrastructure.PublishedCache.DependencyInjection;
+using Umbraco.Tests.Integration.Extensions;
+using Umbraco.Tests.Integration.Implementations;
+using Umbraco.Tests.Integration.Testing;
+using Umbraco.Tests.Testing;
+using Umbraco.Web.Common.DependencyInjection;
+
+namespace Umbraco.Tests.Integration
+{
+
+ [TestFixture]
+ [UmbracoTest(Boot = true)]
+ public class ComponentRuntimeTests : UmbracoIntegrationTest
+ {
+ // ensure composers are added
+ protected override void CustomTestSetup(IUmbracoBuilder builder) => builder.AddComposers();
+
+ ///
+ /// This will boot up umbraco with components enabled to show they initialize and shutdown
+ ///
+ [Test]
+ public async Task Start_And_Stop_Umbraco_With_Components_Enabled()
+ {
+ IRuntime runtime = Services.GetRequiredService();
+ IRuntimeState runtimeState = Services.GetRequiredService();
+ IMainDom mainDom = Services.GetRequiredService();
+ ComponentCollection components = Services.GetRequiredService();
+
+ MyComponent myComponent = components.OfType().First();
+
+ Assert.IsTrue(mainDom.IsMainDom);
+ Assert.IsNull(runtimeState.BootFailedException);
+ Assert.IsTrue(myComponent.IsInit, "The component was not initialized");
+
+ // force stop now
+ await runtime.StopAsync(CancellationToken.None);
+ Assert.IsTrue(myComponent.IsTerminated, "The component was not terminated");
+ }
+
+ public class MyComposer : IUserComposer
+ {
+ public void Compose(IUmbracoBuilder builder) => builder.Components().Append();
+ }
+
+ public class MyComponent : IComponent
+ {
+ public bool IsInit { get; private set; }
+
+ public bool IsTerminated { get; private set; }
+
+ private readonly ILogger _logger;
+
+ public MyComponent(ILogger logger) => _logger = logger;
+
+ public void Initialize() => IsInit = true;
+
+ public void Terminate() => IsTerminated = true;
+
+ }
+ }
+}
diff --git a/src/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs
index 88e0e9f502..c1bdf19069 100644
--- a/src/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs
+++ b/src/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs
@@ -34,9 +34,9 @@ namespace Umbraco.Tests.Integration.DependencyInjection
///
/// Uses/Replaces services with testing services
///
- public static IUmbracoBuilder AddTestServices(this IUmbracoBuilder builder, TestHelper testHelper)
+ public static IUmbracoBuilder AddTestServices(this IUmbracoBuilder builder, TestHelper testHelper, AppCaches appCaches = null)
{
- builder.Services.AddUnique(AppCaches.NoCache);
+ builder.Services.AddUnique(appCaches ?? AppCaches.NoCache);
builder.Services.AddUnique(Mock.Of());
builder.Services.AddUnique(testHelper.MainDom);
diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs
deleted file mode 100644
index 502936a04a..0000000000
--- a/src/Umbraco.Tests.Integration/RuntimeTests.cs
+++ /dev/null
@@ -1,132 +0,0 @@
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using NUnit.Framework;
-using Umbraco.Core;
-using Umbraco.Core.Cache;
-using Umbraco.Core.Composing;
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Extensions;
-using Umbraco.Infrastructure.PublishedCache.DependencyInjection;
-using Umbraco.Tests.Integration.Extensions;
-using Umbraco.Tests.Integration.Implementations;
-using Umbraco.Web.Common.DependencyInjection;
-
-namespace Umbraco.Tests.Integration
-{
-
- [TestFixture]
- public class RuntimeTests
- {
- [TearDown]
- public void TearDown()
- {
- MyComponent.Reset();
- MyComposer.Reset();
- }
-
- [SetUp]
- public void Setup()
- {
- MyComponent.Reset();
- MyComposer.Reset();
- }
-
- ///
- /// This will boot up umbraco with components enabled to show they initialize and shutdown
- ///
- [Test]
- public async Task Start_And_Stop_Umbraco_With_Components_Enabled()
- {
- var testHelper = new TestHelper();
-
- IHostBuilder hostBuilder = new HostBuilder()
- .ConfigureServices((hostContext, services) =>
- {
- IWebHostEnvironment webHostEnvironment = testHelper.GetWebHostEnvironment();
- services.AddSingleton(testHelper.DbProviderFactoryCreator);
- services.AddRequiredNetCoreServices(testHelper, webHostEnvironment);
-
- // Add it!
- TypeLoader typeLoader = services.AddTypeLoader(
- GetType().Assembly,
- webHostEnvironment,
- testHelper.GetHostingEnvironment(),
- testHelper.ConsoleLoggerFactory,
- AppCaches.NoCache,
- hostContext.Configuration,
- testHelper.Profiler);
-
- var builder = new UmbracoBuilder(
- services,
- hostContext.Configuration,
- typeLoader,
- testHelper.ConsoleLoggerFactory);
-
- builder.Services.AddUnique(AppCaches.NoCache);
- builder.AddConfiguration()
- .AddUmbracoCore()
- .AddWebComponents()
- .AddComposers()
- .Build();
-
- services.AddRouting(); // LinkGenerator
- });
-
- IHost host = await hostBuilder.StartAsync();
- var app = new ApplicationBuilder(host.Services);
-
- app.UseUmbracoCore();
-
- // assert results
- IRuntimeState runtimeState = app.ApplicationServices.GetRequiredService();
- IMainDom mainDom = app.ApplicationServices.GetRequiredService();
-
- Assert.IsTrue(mainDom.IsMainDom);
- Assert.IsNull(runtimeState.BootFailedException);
- Assert.IsTrue(MyComponent.IsInit);
-
- await host.StopAsync();
-
- Assert.IsTrue(MyComponent.IsTerminated);
- }
-
- public class MyComposer : IUserComposer
- {
- public void Compose(IUmbracoBuilder builder)
- {
- builder.Components().Append();
- IsComposed = true;
- }
-
- public static void Reset() => IsComposed = false;
-
- public static bool IsComposed { get; private set; }
- }
-
- public class MyComponent : IComponent
- {
- public static bool IsInit { get; private set; }
-
- public static bool IsTerminated { get; private set; }
-
- private readonly ILogger _logger;
-
- public MyComponent(ILogger logger) => _logger = logger;
-
- public void Initialize() => IsInit = true;
-
- public void Terminate() => IsTerminated = true;
-
- public static void Reset()
- {
- IsTerminated = false;
- IsInit = false;
- }
- }
- }
-}
diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs
index 33c1c28e48..27209182fe 100644
--- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs
+++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs
@@ -139,6 +139,7 @@ namespace Umbraco.Tests.Integration.TestServerTest
.AddUmbracoCore()
.AddWebComponents()
.AddRuntimeMinifier()
+ .AddBackOfficeCore()
.AddBackOfficeAuthentication()
.AddBackOfficeIdentity()
.AddBackOfficeAuthorizationPolicies(TestAuthHandler.TestAuthenticationScheme)
diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs
index 21c3cf8304..17778f986c 100644
--- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs
+++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs
@@ -217,25 +217,20 @@ namespace Umbraco.Tests.Integration.Testing
builder.Services.AddLogger(TestHelper.GetHostingEnvironment(), TestHelper.GetLoggingConfiguration(), Configuration);
builder.AddConfiguration()
- .AddUmbracoCore();
-
- builder.Services.AddUnique(GetAppCaches());
- builder.Services.AddUnique(Mock.Of());
- builder.Services.AddUnique(TestHelper.MainDom);
-
- //.AddTestServices(TestHelper)
- builder.AddWebComponents()
+ .AddUmbracoCore()
+ .AddWebComponents()
.AddRuntimeMinifier()
.AddBackOfficeAuthentication()
- .AddBackOfficeIdentity();
+ .AddBackOfficeIdentity()
+ .AddTestServices(TestHelper, GetAppCaches());
//.AddComposers();
services.AddSignalR();
services.AddMvc();
- builder.Build();
-
CustomTestSetup(builder);
+
+ builder.Build();
}
protected virtual AppCaches GetAppCaches()
diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs
index 30e6bdcbc7..fb2cbfb607 100644
--- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs
+++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs
@@ -1,11 +1,21 @@
using System;
+using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
using Umbraco.Core.DependencyInjection;
+using Umbraco.Core.Hosting;
+using Umbraco.Core.IO;
+using Umbraco.Core.Services;
+using Umbraco.Extensions;
using Umbraco.Infrastructure.DependencyInjection;
-using Umbraco.Infrastructure.PublishedCache.DependencyInjection;
using Umbraco.Web.BackOffice.Authorization;
+using Umbraco.Web.BackOffice.Controllers;
+using Umbraco.Web.BackOffice.Filters;
+using Umbraco.Web.BackOffice.Middleware;
+using Umbraco.Web.BackOffice.Routing;
using Umbraco.Web.BackOffice.Security;
+using Umbraco.Web.BackOffice.Services;
using Umbraco.Web.BackOffice.Trees;
using Umbraco.Web.Common.Authorization;
using Umbraco.Web.Common.DependencyInjection;
@@ -25,6 +35,7 @@ namespace Umbraco.Web.BackOffice.DependencyInjection
.AddUmbracoCore()
.AddWebComponents()
.AddRuntimeMinifier()
+ .AddBackOfficeCore()
.AddBackOfficeAuthentication()
.AddBackOfficeIdentity()
.AddBackOfficeAuthorizationPolicies()
@@ -64,6 +75,11 @@ namespace Umbraco.Web.BackOffice.DependencyInjection
});
builder.Services.ConfigureOptions();
+
+ builder.Services.AddUnique();
+ builder.Services.AddUnique();
+ builder.Services.AddUnique();
+
return builder;
}
@@ -117,5 +133,41 @@ namespace Umbraco.Web.BackOffice.DependencyInjection
///
public static TreeCollectionBuilder Trees(this IUmbracoBuilder builder)
=> builder.WithCollectionBuilder();
+
+ public static IUmbracoBuilder AddBackOfficeCore(this IUmbracoBuilder builder)
+ {
+ builder.Services.AddUnique();
+ builder.Services.AddUnique();
+ builder.Services.AddUnique();
+ builder.Services.AddScoped();
+ builder.Services.AddScoped();
+
+ // register back office trees
+ // the collection builder only accepts types inheriting from TreeControllerBase
+ // and will filter out those that are not attributed with TreeAttribute
+ var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList();
+ builder.Trees()
+ .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x)));
+
+ builder.ComposeWebMappingProfiles();
+
+ builder.Services.AddUnique(factory =>
+ {
+ var path = "~/";
+ var hostingEnvironment = factory.GetRequiredService();
+ return new PhysicalFileSystem(
+ factory.GetRequiredService(),
+ hostingEnvironment,
+ factory.GetRequiredService>(),
+ hostingEnvironment.MapPathContentRoot(path),
+ hostingEnvironment.ToAbsolute(path)
+ );
+ });
+
+ builder.Services.AddUnique();
+ builder.Services.AddUnique();
+
+ return builder;
+ }
}
}
diff --git a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs
deleted file mode 100644
index d933d00d68..0000000000
--- a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using System.Linq;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using Umbraco.Core.Composing;
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Hosting;
-using Umbraco.Core.IO;
-using Umbraco.Core.Services;
-using Umbraco.Extensions;
-using Umbraco.Web.BackOffice.Controllers;
-using Umbraco.Web.BackOffice.DependencyInjection;
-using Umbraco.Web.BackOffice.Filters;
-using Umbraco.Web.BackOffice.Middleware;
-using Umbraco.Web.BackOffice.Routing;
-using Umbraco.Web.BackOffice.Security;
-using Umbraco.Web.BackOffice.Services;
-using Umbraco.Web.BackOffice.Trees;
-using Umbraco.Web.Common.Runtime;
-
-namespace Umbraco.Web.BackOffice.Runtime
-{
- [ComposeBefore(typeof(ICoreComposer))]
- [ComposeAfter(typeof(AspNetCoreComposer))]
- public class BackOfficeComposer : IComposer
- {
- public void Compose(IUmbracoBuilder builder)
- {
- builder.Services.AddUnique();
- builder.Services.AddUnique();
- builder.Services.AddUnique();
- builder.Services.AddScoped();
- builder.Services.AddScoped();
-
- builder.Services.AddUnique();
- builder.Services.AddUnique();
- builder.Services.AddUnique();
-
- // register back office trees
- // the collection builder only accepts types inheriting from TreeControllerBase
- // and will filter out those that are not attributed with TreeAttribute
- var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList();
- builder.Trees()
- .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x)));
-
- builder.ComposeWebMappingProfiles();
-
- builder.Services.AddUnique(factory =>
- {
- var path = "~/";
- var hostingEnvironment = factory.GetRequiredService();
- return new PhysicalFileSystem(
- factory.GetRequiredService(),
- hostingEnvironment,
- factory.GetRequiredService>(),
- hostingEnvironment.MapPathContentRoot(path),
- hostingEnvironment.ToAbsolute(path)
- );
- });
-
- builder.Services.AddUnique();
- builder.Services.AddUnique();
- }
- }
-}
diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs
index 34a8b7583a..1eda1cc23a 100644
--- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs
+++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs
@@ -1,31 +1,4 @@
-using System.Linq;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.DependencyInjection;
-using Umbraco.Core;
-using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Composing;
-using Umbraco.Core.Diagnostics;
-using Umbraco.Core.Hosting;
-using Umbraco.Core.Logging;
-using Umbraco.Core.Security;
-using Umbraco.Extensions;
-using Umbraco.Net;
-using Umbraco.Web.Common.AspNetCore;
-using Umbraco.Web.Common.Controllers;
-using Umbraco.Web.Common.Install;
-using Umbraco.Web.Common.Lifetime;
-using Umbraco.Web.Common.Macros;
-using Umbraco.Web.Common.Middleware;
-using Umbraco.Web.Common.Profiler;
-using Umbraco.Web.Common.Routing;
-using Umbraco.Web.Common.Security;
-using Umbraco.Web.Common.Templates;
-using Umbraco.Web.Macros;
-using Umbraco.Web.Security;
-using Umbraco.Web.Templates;
-using Umbraco.Web.Common.ModelBinders;
-using Umbraco.Infrastructure.DependencyInjection;
-
namespace Umbraco.Web.Common.Runtime
{
diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs
index 75212e3077..a09b850d98 100644
--- a/src/Umbraco.Web.UI.NetCore/Startup.cs
+++ b/src/Umbraco.Web.UI.NetCore/Startup.cs
@@ -46,6 +46,7 @@ namespace Umbraco.Web.UI.NetCore
services.AddUmbraco(_env, _config)
.AddBackOffice()
.AddWebsite()
+ .AddComposers()
.Build();
#pragma warning restore IDE0022 // Use expression body for methods
diff --git a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs
index 5762a5fb69..52f6d5df11 100644
--- a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs
+++ b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs
@@ -2,8 +2,10 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Core.DependencyInjection;
+using Umbraco.Extensions;
using Umbraco.Infrastructure.DependencyInjection;
using Umbraco.Infrastructure.PublishedCache.DependencyInjection;
+using Umbraco.Web.Website.Collections;
using Umbraco.Web.Website.Controllers;
using Umbraco.Web.Website.Routing;
using Umbraco.Web.Website.ViewEngines;
@@ -20,6 +22,11 @@ namespace Umbraco.Web.Website.DependencyInjection
///
public static IUmbracoBuilder AddWebsite(this IUmbracoBuilder builder)
{
+ builder.Services.AddUnique();
+
+ builder.WithCollectionBuilder()
+ .Add(builder.TypeLoader.GetSurfaceControllers());
+
// Set the render & plugin view engines (Super complicated, but this allows us to use the IServiceCollection
// to inject dependencies into the viewEngines)
builder.Services.AddTransient, RenderMvcViewOptionsSetup>();
diff --git a/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs b/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs
deleted file mode 100644
index 2a4b85a0df..0000000000
--- a/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using Umbraco.Core.DependencyInjection;
-using Umbraco.Core.Composing;
-using Umbraco.Extensions;
-using Umbraco.Web.Website.Routing;
-using Umbraco.Web.Common.Runtime;
-using Umbraco.Web.Website.Collections;
-
-namespace Umbraco.Web.Website.Runtime
-{
- // web's initial composer composes after core's, and before all core composers
- [ComposeBefore(typeof(ICoreComposer))]
- [ComposeAfter(typeof(AspNetCoreComposer))]
- public class WebsiteComposer : IComposer
- {
- public void Compose(IUmbracoBuilder builder)
- {
- builder.Services.AddUnique();
-
- builder.WithCollectionBuilder()
- .Add(builder.TypeLoader.GetSurfaceControllers());
- }
- }
-}
-