diff --git a/src/Umbraco.Core/Services/IRuntimeState.cs b/src/Umbraco.Core/Services/IRuntimeState.cs
index 38da246cc1..565b2563e6 100644
--- a/src/Umbraco.Core/Services/IRuntimeState.cs
+++ b/src/Umbraco.Core/Services/IRuntimeState.cs
@@ -46,12 +46,6 @@ namespace Umbraco.Core
/// This is eg "http://www.example.com".
Uri ApplicationUrl { get; }
- ///
- /// Gets the Umbraco application virtual path.
- ///
- /// This is either "/" or eg "/virtual".
- string ApplicationVirtualPath { get; }
-
///
/// Gets the runtime level of execution.
///
diff --git a/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs b/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs
index eb74d37590..02e5a6f5ee 100644
--- a/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs
+++ b/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs
@@ -1,6 +1,7 @@
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
+using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
@@ -15,6 +16,9 @@ namespace Umbraco.Core
///
/// Registers essential services.
///
+ ///
+ /// These services are all either created by the runtime or used to construct the runtime
+ ///
public static void RegisterEssentials(this Composition composition,
ILogger logger, IProfiler profiler, IProfilingLogger profilingLogger,
IMainDom mainDom,
@@ -25,8 +29,10 @@ namespace Umbraco.Core
ITypeFinder typeFinder,
IIOHelper ioHelper,
IUmbracoVersion umbracoVersion,
- IDbProviderFactoryCreator dbProviderFactoryCreator)
- {
+ IDbProviderFactoryCreator dbProviderFactoryCreator,
+ IHostingEnvironment hostingEnvironment,
+ IBackOfficeInfo backOfficeInfo)
+ {
composition.RegisterUnique(logger);
composition.RegisterUnique(profiler);
composition.RegisterUnique(profilingLogger);
@@ -42,6 +48,8 @@ namespace Umbraco.Core
composition.RegisterUnique(umbracoVersion);
composition.RegisterUnique(dbProviderFactoryCreator);
composition.RegisterUnique(factory => factory.GetInstance().BulkSqlInsertProvider);
+ composition.RegisterUnique(hostingEnvironment);
+ composition.RegisterUnique(backOfficeInfo);
}
}
}
diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs
index 4a9441e535..5cd51a174a 100644
--- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs
+++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs
@@ -69,7 +69,7 @@ namespace Umbraco.Core.Runtime
Configs.Global(),
new Lazy(() => mainDom),
new Lazy(() => _factory.GetInstance()),
- UmbracoVersion,HostingEnvironment, BackOfficeInfo)
+ UmbracoVersion, HostingEnvironment, BackOfficeInfo)
{
Level = RuntimeLevel.Boot
};
@@ -82,7 +82,6 @@ namespace Umbraco.Core.Runtime
protected IBackOfficeInfo BackOfficeInfo { get; }
public IDbProviderFactoryCreator DbProviderFactoryCreator { get; }
- //public IBulkSqlInsertProvider BulkSqlInsertProvider { get; }
///
/// Gets the profiler.
@@ -176,21 +175,9 @@ namespace Umbraco.Core.Runtime
// type finder/loader
var typeLoader = new TypeLoader(IOHelper, TypeFinder, appCaches.RuntimeCache, new DirectoryInfo(HostingEnvironment.LocalTempPath), ProfilingLogger);
- // runtime state
- // beware! must use '() => _factory.GetInstance()' and NOT '_factory.GetInstance'
- // as the second one captures the current value (null) and therefore fails
- _state = new RuntimeState(Logger,
- Configs.Global(),
- new Lazy(() => _factory.GetInstance()),
- new Lazy(() => _factory.GetInstance()),
- UmbracoVersion, HostingEnvironment, BackOfficeInfo)
- {
- Level = RuntimeLevel.Boot
- };
-
// create the composition
composition = new Composition(register, typeLoader, ProfilingLogger, _state, Configs, IOHelper, appCaches);
- composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, MainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion, DbProviderFactoryCreator);
+ composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, MainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion, DbProviderFactoryCreator, HostingEnvironment, BackOfficeInfo);
// run handlers
RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory);
diff --git a/src/Umbraco.Infrastructure/RuntimeState.cs b/src/Umbraco.Infrastructure/RuntimeState.cs
index eadb9fed21..420fba7ffc 100644
--- a/src/Umbraco.Infrastructure/RuntimeState.cs
+++ b/src/Umbraco.Infrastructure/RuntimeState.cs
@@ -43,8 +43,6 @@ namespace Umbraco.Core
_umbracoVersion = umbracoVersion;
_hostingEnvironment = hostingEnvironment;
_backOfficeInfo = backOfficeInfo;
-
- ApplicationVirtualPath = _hostingEnvironment.ApplicationVirtualPath;
}
///
@@ -84,9 +82,6 @@ namespace Umbraco.Core
///
public Uri ApplicationUrl { get; private set; }
- ///
- public string ApplicationVirtualPath { get; }
-
///
public string CurrentMigrationState { get; internal set; }
diff --git a/src/Umbraco.Tests.Integration/ContainerTests.cs b/src/Umbraco.Tests.Integration/ContainerTests.cs
index d190d1165d..f440944ab7 100644
--- a/src/Umbraco.Tests.Integration/ContainerTests.cs
+++ b/src/Umbraco.Tests.Integration/ContainerTests.cs
@@ -37,7 +37,7 @@ namespace Umbraco.Tests.Integration
var testHelper = new TestHelper();
var runtimeState = Mock.Of();
var umbracoDatabaseFactory = Mock.Of();
- var dbProviderFactoryCreator = Mock.Of();
+ var dbProviderFactoryCreator = Mock.Of();
var typeLoader = testHelper.GetMockedTypeLoader();
// Register in the container
@@ -45,7 +45,8 @@ namespace Umbraco.Tests.Integration
testHelper.Logger, runtimeState, testHelper.GetConfigs(), testHelper.IOHelper, testHelper.AppCaches);
composition.RegisterEssentials(testHelper.Logger, testHelper.Profiler, testHelper.Logger, testHelper.MainDom,
testHelper.AppCaches, umbracoDatabaseFactory, typeLoader, runtimeState, testHelper.GetTypeFinder(),
- testHelper.IOHelper, testHelper.GetUmbracoVersion(), dbProviderFactoryCreator);
+ testHelper.IOHelper, testHelper.GetUmbracoVersion(), dbProviderFactoryCreator,
+ testHelper.GetHostingEnvironment(), testHelper.GetBackOfficeInfo());
// Cross wire - this would be called by the Host Builder at the very end of ConfigureServices
var lightInjectServiceProvider = serviceProviderFactory.CreateServiceProvider(umbracoContainer.Container);
diff --git a/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs b/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs
deleted file mode 100644
index 9df7270350..0000000000
--- a/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using Microsoft.Extensions.Hosting;
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Umbraco.Tests.Integration
-{
- ///
- /// Executes arbitrary code on start/end
- ///
- public class DelegateHostedService : IHostedService
- {
- private readonly Action _start;
- private readonly Action _end;
-
- public static DelegateHostedService Create(Action start, Action end) => new DelegateHostedService(start, end);
-
- private DelegateHostedService(Action start, Action end)
- {
- _start = start;
- _end = end;
- }
-
- public Task StartAsync(CancellationToken cancellationToken)
- {
- _start();
- return Task.CompletedTask;
- }
-
- public Task StopAsync(CancellationToken cancellationToken)
- {
- _end?.Invoke();
- return Task.CompletedTask;
- }
- }
-
-
-}
diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs
index fb7f6b427e..dae4d0cbb8 100644
--- a/src/Umbraco.Tests.Integration/RuntimeTests.cs
+++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs
@@ -9,6 +9,7 @@ using Moq;
using NUnit.Framework;
using System.Collections.Generic;
using System.IO;
+using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing.LightInject;
@@ -28,6 +29,13 @@ namespace Umbraco.Tests.Integration
[TestFixture]
public class RuntimeTests
{
+ [TearDown]
+ public void TearDown()
+ {
+ MyComponent.Reset();
+ MyComposer.Reset();
+ }
+
[OneTimeTearDown]
public void FixtureTearDown()
{
@@ -73,12 +81,11 @@ namespace Umbraco.Tests.Integration
/// Calling AddUmbracoCore to configure the container and boot the core runtime within a generic host
///
[Test]
- public void AddUmbracoCore()
+ public async Task AddUmbracoCore()
{
var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory);
- var host = Host.CreateDefaultBuilder()
- .UseTestLifetime()
+ var hostBuilder = new HostBuilder()
.UseUmbraco(serviceProviderFactory)
.ConfigureServices((hostContext, services) =>
{
@@ -89,38 +96,61 @@ namespace Umbraco.Tests.Integration
// Add it!
services.AddUmbracoConfiguration();
services.AddUmbracoCore(umbracoContainer, GetType().Assembly);
+ });
- // Run tests
- services.AddHostedService(x => DelegateHostedService.Create(() =>
- {
- // assert results
- var runtimeState = umbracoContainer.GetInstance();
- var mainDom = umbracoContainer.GetInstance();
+ var host = await hostBuilder.StartAsync();
- Assert.IsTrue(mainDom.IsMainDom);
- Assert.IsNull(runtimeState.BootFailedException);
- Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
- Assert.IsTrue(MyComposer.IsComposed);
+ // assert results
+ var runtimeState = umbracoContainer.GetInstance();
+ var mainDom = umbracoContainer.GetInstance();
- }, null));
- })
- .Build();
+ Assert.IsTrue(mainDom.IsMainDom);
+ Assert.IsNull(runtimeState.BootFailedException);
+ Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
+ Assert.IsTrue(MyComponent.IsInit);
+ Assert.IsFalse(MyComponent.IsTerminated);
- // NOTE: host.Run() could be used but that requires more work by manually calling IHostApplicationLifetime.StopApplication(). In these cases we don't need to wind down.
- host.Start();
+ await host.StopAsync();
+
+ Assert.IsTrue(MyComponent.IsTerminated);
}
+ [Ignore("This test just shows that resolving services from the container before the host is done resolves 2 different instances")]
[Test]
- public void UseUmbracoCore()
+ public async Task BuildServiceProvider()
+ {
+ var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory);
+
+ IHostApplicationLifetime lifetime1 = null;
+
+ var hostBuilder = new HostBuilder()
+ .UseUmbraco(serviceProviderFactory)
+ .ConfigureServices((hostContext, services) =>
+ {
+ lifetime1 = services.BuildServiceProvider().GetRequiredService();
+ });
+
+ var host = await hostBuilder.StartAsync();
+
+ var lifetime2 = host.Services.GetRequiredService();
+
+ lifetime1.StopApplication();
+ Assert.IsTrue(lifetime1.ApplicationStopping.IsCancellationRequested);
+ Assert.AreEqual(lifetime1.ApplicationStopping.IsCancellationRequested, lifetime2.ApplicationStopping.IsCancellationRequested);
+
+ }
+
+ [Test]
+ public async Task UseUmbracoCore()
{
var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory);
var testHelper = new TestHelper();
- var host = Host.CreateDefaultBuilder()
+ var hostBuilder = new HostBuilder()
//TODO: Need to have a configured umb version for the runtime state
.UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb"))
- .UseTestLifetime()
+ //.UseTestLifetime()
.UseUmbraco(serviceProviderFactory)
.ConfigureServices((hostContext, services) =>
{
@@ -129,33 +159,26 @@ namespace Umbraco.Tests.Integration
// Add it!
services.AddUmbracoConfiguration();
services.AddUmbracoCore(umbracoContainer, GetType().Assembly);
+ });
- // Run tests
- services.AddHostedService(x => DelegateHostedService.Create(() =>
- {
- var runtimeState = (RuntimeState)umbracoContainer.GetInstance();
- Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
+ var host = await hostBuilder.StartAsync();
- var dbBuilder = umbracoContainer.GetInstance();
- Assert.IsNotNull(dbBuilder);
+ var runtimeState = (RuntimeState)umbracoContainer.GetInstance();
+ Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level);
- var canConnect = dbBuilder.CanConnectToDatabase;
- Assert.IsTrue(canConnect);
+ var dbBuilder = umbracoContainer.GetInstance();
+ Assert.IsNotNull(dbBuilder);
- var dbResult = dbBuilder.CreateSchemaAndData();
- Assert.IsTrue(dbResult.Success);
+ var canConnect = dbBuilder.CanConnectToDatabase;
+ Assert.IsTrue(canConnect);
- var dbFactory = umbracoContainer.GetInstance();
- var profilingLogger = umbracoContainer.GetInstance();
- runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger);
- Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level);
+ var dbResult = dbBuilder.CreateSchemaAndData();
+ Assert.IsTrue(dbResult.Success);
- }, null));
- })
- .Build();
-
- // NOTE: host.Run() could be used but that requires more work by manually calling IHostApplicationLifetime.StopApplication(). In these cases we don't need to wind down.
- host.Start();
+ var dbFactory = umbracoContainer.GetInstance();
+ var profilingLogger = umbracoContainer.GetInstance();
+ runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger);
+ Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level);
}
private LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory)
@@ -181,6 +204,11 @@ namespace Umbraco.Tests.Integration
IsComposed = true;
}
+ public static void Reset()
+ {
+ IsComposed = false;
+ }
+
public static bool IsComposed { get; private set; }
}
@@ -205,6 +233,12 @@ namespace Umbraco.Tests.Integration
{
IsTerminated = true;
}
+
+ public static void Reset()
+ {
+ IsTerminated = false;
+ IsInit = false;
+ }
}
}
diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs
index 0cb3f3e2e1..99a5352a17 100644
--- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs
+++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs
@@ -80,7 +80,7 @@ namespace Umbraco.Tests.Runtimes
// create the register and the composition
var register = TestHelper.GetRegister();
var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs, ioHelper, appCaches);
- composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator);
+ composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo);
// create the core runtime and have it compose itself
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder);
@@ -275,7 +275,7 @@ namespace Umbraco.Tests.Runtimes
var register = TestHelper.GetRegister();
var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs, ioHelper, appCaches);
var umbracoVersion = TestHelper.GetUmbracoVersion();
- composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator);
+ composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo);
// create the core runtime and have it compose itself
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder);
diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs
index 1f06a818d6..a79838bd3e 100644
--- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs
+++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs
@@ -1,5 +1,7 @@
using System;
using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
namespace Umbraco.Web.BackOffice.AspNetCore
{
@@ -7,12 +9,10 @@ namespace Umbraco.Web.BackOffice.AspNetCore
{
public static IApplicationBuilder UseUmbracoBackOffice(this IApplicationBuilder app)
{
- if (app == null)
- {
- throw new ArgumentNullException(nameof(app));
- }
+ if (app == null) throw new ArgumentNullException(nameof(app));
return app;
}
+
}
}
diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs
similarity index 82%
rename from src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs
rename to src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs
index 44fb9bc14f..6c3cecad28 100644
--- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs
+++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs
@@ -6,14 +6,11 @@ using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-using Umbraco.Composing;
using Umbraco.Configuration;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
-using Umbraco.Core.Configuration.UmbracoSettings;
-using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Logging.Serilog;
@@ -24,9 +21,13 @@ namespace Umbraco.Web.BackOffice.AspNetCore
{
- public static class UmbracoBackOfficeServiceCollectionExtensions
+ public static class UmbracoCoreServiceCollectionExtensions
{
-
+ ///
+ /// Adds the Umbraco Configuration requirements
+ ///
+ ///
+ ///
public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services)
{
var serviceProvider = services.BuildServiceProvider();
@@ -45,13 +46,10 @@ namespace Umbraco.Web.BackOffice.AspNetCore
///
- /// Adds the Umbraco Back Core requirements
+ /// Adds the Umbraco Back Core requirements
///
///
///
- ///
- /// Must be called after all services are added to the application because we are cross-wiring the container (currently)
- ///
public static IServiceCollection AddUmbracoCore(this IServiceCollection services)
{
if (!UmbracoServiceProviderFactory.IsActive)
@@ -62,6 +60,13 @@ namespace Umbraco.Web.BackOffice.AspNetCore
return services.AddUmbracoCore(umbContainer, Assembly.GetEntryAssembly());
}
+ ///
+ /// Adds the Umbraco Back Core requirements
+ ///
+ ///
+ ///
+ ///
+ ///
public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IRegister umbContainer, Assembly entryAssembly)
{
if (services is null) throw new ArgumentNullException(nameof(services));
@@ -90,6 +95,8 @@ namespace Umbraco.Web.BackOffice.AspNetCore
backOfficeInfo,
typeFinder);
+ hostingEnvironment.RegisterObject(new CoreRuntimeShutdown(coreRuntime));
+
var factory = coreRuntime.Boot(umbContainer);
return services;
@@ -124,8 +131,8 @@ namespace Umbraco.Web.BackOffice.AspNetCore
out ILogger logger, out Configs configs, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment,
out IBackOfficeInfo backOfficeInfo, out IProfiler profiler)
{
- // TODO: This isn't the best to have to resolve the services now but to avoid this will
- // require quite a lot of re-work.
+ // TODO: Resolving services before the Host is done configuring this way means that the services resolved
+ // are not going to be the same instances that are going to be used within the application!
var serviceProvider = services.BuildServiceProvider();
var httpContextAccessor = serviceProvider.GetRequiredService();
@@ -162,5 +169,29 @@ namespace Umbraco.Web.BackOffice.AspNetCore
// nothing to check
}
}
+
+ ///
+ /// Ensures the runtime is shutdown when the application is shutting down
+ ///
+ private class CoreRuntimeShutdown : IRegisteredObject
+ {
+ public CoreRuntimeShutdown(IRuntime runtime)
+ {
+ _runtime = runtime;
+ }
+
+ private bool _completed = false;
+ private readonly IRuntime _runtime;
+
+ public void Stop(bool immediate)
+ {
+ if (!_completed)
+ {
+ _completed = true;
+ _runtime.Terminate();
+ }
+
+ }
+ }
}
}
diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
index b81cafdb40..81aac30d2c 100644
--- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs
+++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
@@ -72,8 +72,6 @@ namespace Umbraco.Web.Runtime
composition.Register(Lifetime.Singleton);
- composition.Register();
- composition.Register();
composition.Register(Lifetime.Singleton);
composition.Register();
composition.Register(Lifetime.Singleton);
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index e8aaecdf4d..5eb60cb629 100755
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -585,4 +585,4 @@
-
+
\ No newline at end of file