diff --git a/.gitignore b/.gitignore
index 8ff5a8ef25..5390da67dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -166,3 +166,4 @@ build/temp/
/src/ApiDocs/api/*
/src/Umbraco.Web.UI.NetCore/wwwroot/Media/*
/src/Umbraco.Web.UI.NetCore/wwwroot/is-cache/*
+/src/Umbraco.Tests.Integration/App_Data/*
diff --git a/src/Umbraco.Configuration/Models/ConnectionStrings.cs b/src/Umbraco.Configuration/Models/ConnectionStrings.cs
index 9fc546a88f..22a0bde571 100644
--- a/src/Umbraco.Configuration/Models/ConnectionStrings.cs
+++ b/src/Umbraco.Configuration/Models/ConnectionStrings.cs
@@ -1,12 +1,12 @@
using System;
-using System.Linq;
-using System.Text.Json.Serialization;
+using System.Data.Common;
using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration.Models
{
- internal class ConnectionStrings : IConnectionStrings
+ public class ConnectionStrings : IConnectionStrings
{
private readonly IConfiguration _configuration;
@@ -17,8 +17,43 @@ namespace Umbraco.Configuration.Models
public ConfigConnectionString this[string key]
{
- get => new ConfigConnectionString(_configuration.GetConnectionString(key), "System.Data.SqlClient", key);
+ get
+ {
+ var connectionString = _configuration.GetConnectionString(key);
+ var provider = ParseProvider(connectionString);
+ return new ConfigConnectionString(connectionString, provider, key);
+ }
set => throw new NotImplementedException();
}
+
+ private string ParseProvider(string connectionString)
+ {
+ if (string.IsNullOrEmpty(connectionString))
+ {
+ return null;
+ }
+
+ var builder = new DbConnectionStringBuilder();
+
+ builder.ConnectionString = connectionString;
+
+ if (builder.TryGetValue("Data Source", out var ds) && ds is string dataSource)
+ {
+ if (dataSource.EndsWith(".sdf"))
+ {
+ return Constants.DbProviderNames.SqlCe;
+ }
+ }
+
+ if (builder.TryGetValue("Server", out var s) && s is string server && builder.TryGetValue("Database", out var db) && db is string database)
+ {
+ if (!string.IsNullOrEmpty(server) && !string.IsNullOrEmpty(database))
+ {
+ return Constants.DbProviderNames.SqlServer;
+ }
+ }
+
+ throw new ArgumentException("Cannot determine provider name from connection string", nameof(connectionString));
+ }
}
}
diff --git a/src/Umbraco.Core/Composing/Composition.cs b/src/Umbraco.Core/Composing/Composition.cs
index 9a696c2dc0..05c7554eab 100644
--- a/src/Umbraco.Core/Composing/Composition.cs
+++ b/src/Umbraco.Core/Composing/Composition.cs
@@ -33,13 +33,13 @@ namespace Umbraco.Core.Composing
/// An IOHelper
public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, Configs configs, IIOHelper ioHelper, AppCaches appCaches)
{
- _register = register;
- TypeLoader = typeLoader;
- Logger = logger;
- RuntimeState = runtimeState;
- Configs = configs;
- IOHelper = ioHelper;
- AppCaches = appCaches;
+ _register = register ?? throw new ArgumentNullException(nameof(register));
+ TypeLoader = typeLoader ?? throw new ArgumentNullException(nameof(typeLoader));
+ Logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ RuntimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState));
+ Configs = configs ?? throw new ArgumentNullException(nameof(configs));
+ IOHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
+ AppCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches));
}
#region Services
diff --git a/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs
index 61d7cff240..f7c81d6d7e 100644
--- a/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs
+++ b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs
@@ -18,6 +18,7 @@ namespace Umbraco.Core.Composing
{
"Umbraco.Core",
"Umbraco.Web",
+ "Umbraco.Web.BackOffice",
"Umbraco.Infrastructure",
"Umbraco.PublishedCache.NuCache",
"Umbraco.ModelsBuilder.Embedded",
diff --git a/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs b/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs
new file mode 100644
index 0000000000..93441f1a47
--- /dev/null
+++ b/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs
@@ -0,0 +1,8 @@
+namespace Umbraco.Core.Hosting
+{
+ public interface IApplicationShutdownRegistry
+ {
+ void RegisterObject(IRegisteredObject registeredObject);
+ void UnregisterObject(IRegisteredObject registeredObject);
+ }
+}
diff --git a/src/Umbraco.Core/Hosting/IHostingEnvironment.cs b/src/Umbraco.Core/Hosting/IHostingEnvironment.cs
index 5b97d8e4f3..b12ffbc138 100644
--- a/src/Umbraco.Core/Hosting/IHostingEnvironment.cs
+++ b/src/Umbraco.Core/Hosting/IHostingEnvironment.cs
@@ -19,8 +19,5 @@ namespace Umbraco.Core.Hosting
Version IISVersion { get; }
string MapPath(string path);
string ToAbsolute(string virtualPath, string root);
-
- void RegisterObject(IRegisteredObject registeredObject);
- void UnregisterObject(IRegisteredObject registeredObject);
}
}
diff --git a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs
index 10d5b10955..3e5361a1c1 100644
--- a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs
+++ b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs
@@ -1,5 +1,6 @@
namespace Umbraco.Net
{
+ // TODO: This shouldn't be in this namespace?
public interface IUmbracoApplicationLifetime
{
///
diff --git a/src/Umbraco.Core/Runtime/IMainDom.cs b/src/Umbraco.Core/Runtime/IMainDom.cs
index 444fc1c7d0..93a560ff7d 100644
--- a/src/Umbraco.Core/Runtime/IMainDom.cs
+++ b/src/Umbraco.Core/Runtime/IMainDom.cs
@@ -1,4 +1,5 @@
using System;
+using Umbraco.Core.Hosting;
// TODO: Can't change namespace due to breaking changes, change in netcore
namespace Umbraco.Core
@@ -16,10 +17,17 @@ namespace Umbraco.Core
/// Gets a value indicating whether the current domain is the main domain.
///
///
- /// When the first call is made to this there will generally be some logic executed to acquire a distributed lock lease.
+ /// Acquire must be called first else this will always return false
///
bool IsMainDom { get; }
+ ///
+ /// Tries to acquire the MainDom, returns true if successful else false
+ ///
+ ///
+ ///
+ bool Acquire(IApplicationShutdownRegistry hostingEnvironment);
+
///
/// Registers a resource that requires the current AppDomain to be the main domain to function.
///
diff --git a/src/Umbraco.Core/Runtime/MainDom.cs b/src/Umbraco.Core/Runtime/MainDom.cs
index 2c56852095..81db1b700d 100644
--- a/src/Umbraco.Core/Runtime/MainDom.cs
+++ b/src/Umbraco.Core/Runtime/MainDom.cs
@@ -21,7 +21,7 @@ namespace Umbraco.Core.Runtime
#region Vars
private readonly ILogger _logger;
- private readonly IHostingEnvironment _hostingEnvironment;
+ private IApplicationShutdownRegistry _hostingEnvironment;
private readonly IMainDomLock _mainDomLock;
// our own lock for local consistency
@@ -42,17 +42,25 @@ namespace Umbraco.Core.Runtime
#region Ctor
// initializes a new instance of MainDom
- public MainDom(ILogger logger, IHostingEnvironment hostingEnvironment, IMainDomLock systemLock)
+ public MainDom(ILogger logger, IMainDomLock systemLock)
{
- hostingEnvironment.RegisterObject(this);
-
_logger = logger;
- _hostingEnvironment = hostingEnvironment;
_mainDomLock = systemLock;
}
#endregion
+ public bool Acquire(IApplicationShutdownRegistry hostingEnvironment)
+ {
+ _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
+
+ return LazyInitializer.EnsureInitialized(ref _isMainDom, ref _isInitialized, ref _locko, () =>
+ {
+ hostingEnvironment.RegisterObject(this);
+ return Acquire();
+ });
+ }
+
///
/// Registers a resource that requires the current AppDomain to be the main domain to function.
///
@@ -180,10 +188,9 @@ namespace Umbraco.Core.Runtime
/// Gets a value indicating whether the current domain is the main domain.
///
///
- /// The lazy initializer call will only call the Acquire callback when it's not been initialized, else it will just return
- /// the value from _isMainDom which means when we set _isMainDom to false again after being signaled, this will return false;
+ /// Acquire must be called first else this will always return false
///
- public bool IsMainDom => LazyInitializer.EnsureInitialized(ref _isMainDom, ref _isInitialized, ref _locko, () => Acquire());
+ public bool IsMainDom => _isMainDom;
// IRegisteredObject
void IRegisteredObject.Stop(bool immediate)
@@ -193,7 +200,7 @@ namespace Umbraco.Core.Runtime
// The web app is stopping, need to wind down
Dispose(true);
- _hostingEnvironment.UnregisterObject(this);
+ _hostingEnvironment?.UnregisterObject(this);
}
#region IDisposable Support
diff --git a/src/Umbraco.Core/Scheduling/KeepAlive.cs b/src/Umbraco.Core/Scheduling/KeepAlive.cs
index 515251b105..1c4ef075ae 100644
--- a/src/Umbraco.Core/Scheduling/KeepAlive.cs
+++ b/src/Umbraco.Core/Scheduling/KeepAlive.cs
@@ -11,18 +11,22 @@ namespace Umbraco.Web.Scheduling
{
public class KeepAlive : RecurringTaskBase
{
- private readonly IRuntimeState _runtime;
+ private readonly IRuntimeState _runtimeState;
+ private readonly IMainDom _mainDom;
private readonly IKeepAliveSettings _keepAliveSettings;
private readonly IProfilingLogger _logger;
+ private readonly IServerRegistrar _serverRegistrar;
private static HttpClient _httpClient;
public KeepAlive(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds,
- IRuntimeState runtime, IKeepAliveSettings keepAliveSettings, IProfilingLogger logger)
+ IRuntimeState runtimeState, IMainDom mainDom, IKeepAliveSettings keepAliveSettings, IProfilingLogger logger, IServerRegistrar serverRegistrar)
: base(runner, delayMilliseconds, periodMilliseconds)
{
- _runtime = runtime;
+ _runtimeState = runtimeState;
+ _mainDom = mainDom;
_keepAliveSettings = keepAliveSettings;
_logger = logger;
+ _serverRegistrar = serverRegistrar;
if (_httpClient == null)
_httpClient = new HttpClient();
}
@@ -30,7 +34,7 @@ namespace Umbraco.Web.Scheduling
public override async Task PerformRunAsync(CancellationToken token)
{
// not on replicas nor unknown role servers
- switch (_runtime.ServerRole)
+ switch (_serverRegistrar.GetCurrentServerRole())
{
case ServerRole.Replica:
_logger.Debug("Does not run on replica servers.");
@@ -41,7 +45,7 @@ namespace Umbraco.Web.Scheduling
}
// ensure we do not run if not main domain, but do NOT lock it
- if (_runtime.IsMainDom == false)
+ if (_mainDom.IsMainDom == false)
{
_logger.Debug("Does not run if not MainDom.");
return false; // do NOT repeat, going down
@@ -54,7 +58,7 @@ namespace Umbraco.Web.Scheduling
{
if (keepAlivePingUrl.Contains("{umbracoApplicationUrl}"))
{
- var umbracoAppUrl = _runtime.ApplicationUrl.ToString();
+ var umbracoAppUrl = _runtimeState.ApplicationUrl.ToString();
if (umbracoAppUrl.IsNullOrWhiteSpace())
{
_logger.Warn("No umbracoApplicationUrl for service (yet), skip.");
diff --git a/src/Umbraco.Core/Scheduling/TempFileCleanup.cs b/src/Umbraco.Core/Scheduling/TempFileCleanup.cs
index aefaf605db..90bf4ee9eb 100644
--- a/src/Umbraco.Core/Scheduling/TempFileCleanup.cs
+++ b/src/Umbraco.Core/Scheduling/TempFileCleanup.cs
@@ -14,26 +14,26 @@ namespace Umbraco.Web.Scheduling
{
private readonly DirectoryInfo[] _tempFolders;
private readonly TimeSpan _age;
- private readonly IRuntimeState _runtime;
+ private readonly IMainDom _mainDom;
private readonly IProfilingLogger _logger;
public TempFileCleanup(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds,
IEnumerable tempFolders, TimeSpan age,
- IRuntimeState runtime, IProfilingLogger logger)
+ IMainDom mainDom, IProfilingLogger logger)
: base(runner, delayMilliseconds, periodMilliseconds)
{
//SystemDirectories.TempFileUploads
_tempFolders = tempFolders.ToArray();
_age = age;
- _runtime = runtime;
+ _mainDom = mainDom;
_logger = logger;
}
public override bool PerformRun()
{
// ensure we do not run if not main domain
- if (_runtime.IsMainDom == false)
+ if (_mainDom.IsMainDom == false)
{
_logger.Debug("Does not run if not MainDom.");
return false; // do NOT repeat, going down
diff --git a/src/Umbraco.Core/Services/IRuntime.cs b/src/Umbraco.Core/Services/IRuntime.cs
index e846342dbc..4715068073 100644
--- a/src/Umbraco.Core/Services/IRuntime.cs
+++ b/src/Umbraco.Core/Services/IRuntime.cs
@@ -13,13 +13,15 @@ namespace Umbraco.Core
///
/// The application register.
/// The application factory.
- IFactory Boot(IRegister register);
+ IFactory Configure(IRegister register);
///
/// Gets the runtime state.
///
IRuntimeState State { get; }
+ void Start();
+
///
/// Terminates the runtime.
///
diff --git a/src/Umbraco.Core/Services/IRuntimeState.cs b/src/Umbraco.Core/Services/IRuntimeState.cs
index 38da246cc1..4b5e26651b 100644
--- a/src/Umbraco.Core/Services/IRuntimeState.cs
+++ b/src/Umbraco.Core/Services/IRuntimeState.cs
@@ -25,33 +25,12 @@ namespace Umbraco.Core
///
SemVersion SemanticVersion { get; }
- ///
- /// Gets a value indicating whether the application is running in debug mode.
- ///
- bool Debug { get; }
-
- ///
- /// Gets a value indicating whether the runtime is the current main domain.
- ///
- bool IsMainDom { get; }
-
- ///
- /// Get the server's current role.
- ///
- ServerRole ServerRole { get; }
-
///
/// Gets the Umbraco application url.
///
/// 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.
///
@@ -77,6 +56,5 @@ namespace Umbraco.Core
///
BootFailedException BootFailedException { get; }
- IMainDom MainDom { get; }
}
}
diff --git a/src/Umbraco.Core/SimpleMainDom.cs b/src/Umbraco.Core/SimpleMainDom.cs
index 87cc7bcff1..e6bdda67d7 100644
--- a/src/Umbraco.Core/SimpleMainDom.cs
+++ b/src/Umbraco.Core/SimpleMainDom.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Umbraco.Core.Hosting;
namespace Umbraco.Core
{
@@ -16,6 +17,9 @@ namespace Umbraco.Core
///
public bool IsMainDom { get; private set; } = true;
+ // always acquire
+ public bool Acquire(IApplicationShutdownRegistry hostingEnvironment) => true;
+
///
public bool Register(Action release, int weight = 100)
=> Register(null, release, weight);
diff --git a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs
index 78b9589a2e..70b79fbeb0 100644
--- a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs
+++ b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs
@@ -28,17 +28,18 @@ namespace Umbraco.Web
private readonly IRequestAccessor _requestAccessor;
public BatchedDatabaseServerMessenger(
- IRuntimeState runtime,
+ IMainDom mainDom,
IUmbracoDatabaseFactory databaseFactory,
IScopeProvider scopeProvider,
ISqlContext sqlContext,
IProfilingLogger proflog,
+ IServerRegistrar serverRegistrar,
DatabaseServerMessengerOptions options,
IHostingEnvironment hostingEnvironment,
CacheRefresherCollection cacheRefreshers,
IRequestCache requestCache,
IRequestAccessor requestAccessor)
- : base(runtime, scopeProvider, sqlContext, proflog, true, options, hostingEnvironment, cacheRefreshers)
+ : base(mainDom, scopeProvider, sqlContext, proflog, serverRegistrar, true, options, hostingEnvironment, cacheRefreshers)
{
_databaseFactory = databaseFactory;
_requestCache = requestCache;
diff --git a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs
index 2a24e6f318..6c745f3877 100644
--- a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs
+++ b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs
@@ -91,7 +91,6 @@ namespace Umbraco.Web.Compose
private readonly BackgroundTaskRunner _processTaskRunner;
private bool _started;
private IBackgroundTask[] _tasks;
- private IndexRebuilder _indexRebuilder;
private readonly IRequestAccessor _requestAccessor;
public DatabaseServerRegistrarAndMessengerComponent(
@@ -100,14 +99,12 @@ namespace Umbraco.Web.Compose
IServerMessenger serverMessenger,
IServerRegistrationService registrationService,
ILogger logger,
- IHostingEnvironment hostingEnvironment,
- IndexRebuilder indexRebuilder,
+ IApplicationShutdownRegistry hostingEnvironment,
IRequestAccessor requestAccessor)
{
_runtime = runtime;
_logger = logger;
_registrationService = registrationService;
- _indexRebuilder = indexRebuilder;
_requestAccessor = requestAccessor;
// create task runner for DatabaseServerRegistrar
diff --git a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs
index d4e22bbfde..a2ee650595 100644
--- a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs
+++ b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Compose
{
public sealed class ManifestWatcherComponent : IComponent
{
- private readonly IRuntimeState _runtimeState;
+ private readonly IHostingEnvironment _hosting;
private readonly ILogger _logger;
private readonly IIOHelper _ioHelper;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
@@ -19,9 +19,9 @@ namespace Umbraco.Core.Compose
// package.manifest chances and restarts the application on any change
private ManifestWatcher _mw;
- public ManifestWatcherComponent(IRuntimeState runtimeState, ILogger logger, IIOHelper ioHelper, IUmbracoApplicationLifetime umbracoApplicationLifetime)
+ public ManifestWatcherComponent(IHostingEnvironment hosting, ILogger logger, IIOHelper ioHelper, IUmbracoApplicationLifetime umbracoApplicationLifetime)
{
- _runtimeState = runtimeState;
+ _hosting = hosting;
_logger = logger;
_ioHelper = ioHelper;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Compose
public void Initialize()
{
- if (_runtimeState.Debug == false) return;
+ if (_hosting.IsDebugMode == false) return;
//if (ApplicationContext.Current.IsConfigured == false || GlobalSettings.DebugMode == false)
// return;
diff --git a/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs b/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs
index d5355c136f..2099778185 100644
--- a/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs
+++ b/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs
@@ -13,8 +13,9 @@ namespace Umbraco.Core.Composing
///
///
public static IHostBuilder UseUmbraco(this IHostBuilder builder)
- {
- return builder.UseServiceProviderFactory(new UmbracoServiceProviderFactory());
- }
+ => builder.UseUmbraco(new UmbracoServiceProviderFactory());
+
+ public static IHostBuilder UseUmbraco(this IHostBuilder builder, UmbracoServiceProviderFactory umbracoServiceProviderFactory)
+ => builder.UseServiceProviderFactory(umbracoServiceProviderFactory);
}
}
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/Intall/InstallHelper.cs b/src/Umbraco.Infrastructure/Intall/InstallHelper.cs
index a5b4f71d8e..cf4b174cde 100644
--- a/src/Umbraco.Infrastructure/Intall/InstallHelper.cs
+++ b/src/Umbraco.Infrastructure/Intall/InstallHelper.cs
@@ -9,10 +9,10 @@ using Umbraco.Core.Cookie;
using Umbraco.Core.Logging;
using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Models;
+using Umbraco.Net;
using Umbraco.Core.Persistence;
using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
-using Umbraco.Net;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install
diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs
index cc269408f4..4e14da30b7 100644
--- a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs
+++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs
@@ -2,8 +2,8 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
-using Umbraco.Core.Services;
using Umbraco.Net;
+using Umbraco.Core.Services;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install.InstallSteps
diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs
index 17192fd69b..8d5922028c 100644
--- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs
+++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs
@@ -46,7 +46,7 @@ namespace Umbraco.Core.Migrations.Install
IIOHelper ioHelper,
IUmbracoVersion umbracoVersion,
IDbProviderFactoryCreator dbProviderFactoryCreator,
- IConfigManipulator configManipulator)
+ IConfigManipulator configManipulator)
{
_scopeProvider = scopeProvider;
_globalSettings = globalSettings;
diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs
index 9318b223df..1bf954e4c1 100644
--- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs
+++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs
@@ -44,7 +44,7 @@ namespace Umbraco.Core.Runtime
public override void Compose(Composition composition)
{
base.Compose(composition);
-
+
// composers
composition
.ComposeRepositories()
@@ -120,10 +120,11 @@ namespace Umbraco.Core.Runtime
// project
composition.RegisterUnique(factory
=> new DatabaseServerMessenger(
- factory.GetInstance(),
+ factory.GetInstance(),
factory.GetInstance(),
factory.GetInstance(),
factory.GetInstance(),
+ factory.GetInstance(),
true, new DatabaseServerMessengerOptions(),
factory.GetInstance(),
factory.GetInstance()
@@ -176,6 +177,8 @@ namespace Umbraco.Core.Runtime
// Grid config is not a real config file as we know them
composition.RegisterUnique();
+ // Config manipulator
+ composition.RegisterUnique();
}
}
}
diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs
index 6c1a06ab6b..139e9e9b67 100644
--- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs
+++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
-using System.Reflection;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
@@ -12,7 +11,6 @@ using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Mappers;
-using Umbraco.Core.Sync;
namespace Umbraco.Core.Runtime
{
@@ -25,12 +23,11 @@ namespace Umbraco.Core.Runtime
{
private ComponentCollection _components;
private IFactory _factory;
- private RuntimeState _state;
+ private readonly RuntimeState _state;
private readonly IUmbracoBootPermissionChecker _umbracoBootPermissionChecker;
private readonly IGlobalSettings _globalSettings;
private readonly IConnectionStrings _connectionStrings;
-
public CoreRuntime(
Configs configs,
IUmbracoVersion umbracoVersion,
@@ -65,11 +62,7 @@ namespace Umbraco.Core.Runtime
// 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(() => mainDom),
- new Lazy(() => _factory.GetInstance()),
- UmbracoVersion,HostingEnvironment, BackOfficeInfo)
+ _state = new RuntimeState(Logger, Configs.Global(), UmbracoVersion, BackOfficeInfo)
{
Level = RuntimeLevel.Boot
};
@@ -81,13 +74,13 @@ namespace Umbraco.Core.Runtime
protected ILogger Logger { get; }
protected IBackOfficeInfo BackOfficeInfo { get; }
+
public IDbProviderFactoryCreator DbProviderFactoryCreator { get; }
- //public IBulkSqlInsertProvider BulkSqlInsertProvider { get; }
///
/// Gets the profiler.
///
- protected IProfiler Profiler { get; set; }
+ protected IProfiler Profiler { get; }
///
/// Gets the profiling logger.
@@ -110,11 +103,13 @@ namespace Umbraco.Core.Runtime
///
public IRuntimeState State => _state;
- public IMainDom MainDom { get; private set; }
+ public IMainDom MainDom { get; }
///
- public virtual IFactory Boot(IRegister register)
+ public virtual IFactory Configure(IRegister register)
{
+ if (register is null) throw new ArgumentNullException(nameof(register));
+
// create and register the essential services
// ie the bare minimum required to boot
@@ -139,25 +134,24 @@ namespace Umbraco.Core.Runtime
// application environment
ConfigureUnhandledException();
- ConfigureApplicationRootPath();
-
- Boot(register, timer);
+ return _factory = Configure(register, timer);
}
-
- return _factory;
}
///
- /// Boots the runtime within a timer.
+ /// Configure the runtime within a timer.
///
- protected virtual IFactory Boot(IRegister register, DisposableTimer timer)
+ private IFactory Configure(IRegister register, DisposableTimer timer)
{
+ if (register is null) throw new ArgumentNullException(nameof(register));
+ if (timer is null) throw new ArgumentNullException(nameof(timer));
+
Composition composition = null;
+ IFactory factory = null;
try
{
- // throws if not full-trust
- _umbracoBootPermissionChecker.ThrowIfNotPermissions();
+
// run handlers
RuntimeOptions.DoRuntimeBoot(ProfilingLogger);
@@ -171,31 +165,12 @@ 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);
-
- // register runtime-level services
- // there should be none, really - this is here "just in case"
- Compose(composition);
-
- // acquire the main domain - if this fails then anything that should be registered with MainDom will not operate
- AcquireMainDom(MainDom);
+ // register ourselves (TODO: Should we put this in RegisterEssentials?)
+ composition.Register(_ => this, Lifetime.Singleton);
// determine our runtime level
DetermineRuntimeLevel(databaseFactory, ProfilingLogger);
@@ -213,13 +188,7 @@ namespace Umbraco.Core.Runtime
composers.Compose();
// create the factory
- _factory = composition.CreateFactory();
-
- // create & initialize the components
- _components = _factory.GetInstance();
- _components.Initialize();
-
-
+ factory = composition.CreateFactory();
}
catch (Exception e)
{
@@ -236,11 +205,11 @@ namespace Umbraco.Core.Runtime
// if something goes wrong above, we may end up with no factory
// meaning nothing can get the runtime state, etc - so let's try
// to make sure we have a factory
- if (_factory == null)
+ if (factory == null)
{
try
{
- _factory = composition?.CreateFactory();
+ factory = composition?.CreateFactory();
}
catch { /* yea */ }
}
@@ -254,7 +223,29 @@ namespace Umbraco.Core.Runtime
// throw a BootFailedException for every requests.
}
- return _factory;
+ return factory;
+ }
+
+ public void Start()
+ {
+ // throws if not full-trust
+ _umbracoBootPermissionChecker.ThrowIfNotPermissions();
+
+ ConfigureApplicationRootPath();
+
+ // run handlers
+ RuntimeOptions.DoRuntimeEssentials(_factory);
+
+ var hostingEnvironmentLifetime = _factory.TryGetInstance();
+ if (hostingEnvironmentLifetime == null)
+ throw new InvalidOperationException($"An instance of {typeof(IApplicationShutdownRegistry)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(Start)}");
+
+ // acquire the main domain - if this fails then anything that should be registered with MainDom will not operate
+ AcquireMainDom(MainDom, _factory.GetInstance());
+
+ // create & initialize the components
+ _components = _factory.GetInstance();
+ _components.Initialize();
}
protected virtual void ConfigureUnhandledException()
@@ -281,13 +272,13 @@ namespace Umbraco.Core.Runtime
IOHelper.SetRootDirectory(path);
}
- private bool AcquireMainDom(IMainDom mainDom)
+ private bool AcquireMainDom(IMainDom mainDom, IApplicationShutdownRegistry applicationShutdownRegistry)
{
using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Acquired."))
{
try
{
- return mainDom.IsMainDom;
+ return mainDom.Acquire(applicationShutdownRegistry);
}
catch
{
@@ -346,12 +337,6 @@ namespace Umbraco.Core.Runtime
_components?.Terminate();
}
- ///
- /// Composes the runtime.
- ///
- public virtual void Compose(Composition composition)
- {
- }
#region Getters
@@ -392,5 +377,6 @@ namespace Umbraco.Core.Runtime
#endregion
+
}
}
diff --git a/src/Umbraco.Infrastructure/Runtime/WebRuntime.cs b/src/Umbraco.Infrastructure/Runtime/WebRuntime.cs
index 2f45a3e437..fc2a019023 100644
--- a/src/Umbraco.Infrastructure/Runtime/WebRuntime.cs
+++ b/src/Umbraco.Infrastructure/Runtime/WebRuntime.cs
@@ -40,7 +40,7 @@ namespace Umbraco.Web.Runtime
}
///
- public override IFactory Boot(IRegister register)
+ public override IFactory Configure(IRegister register)
{
var profilingLogger = new ProfilingLogger(Logger, Profiler);
@@ -57,7 +57,7 @@ namespace Umbraco.Web.Runtime
NetworkHelper.MachineName);
Logger.Debug("Runtime: {Runtime}", GetType().FullName);
- var factory = base.Boot(register);
+ var factory = base.Configure(register);
// now (and only now) is the time to switch over to perWebRequest scopes.
// up until that point we may not have a request, and scoped services would
diff --git a/src/Umbraco.Infrastructure/RuntimeOptions.cs b/src/Umbraco.Infrastructure/RuntimeOptions.cs
index 23abd474a4..562a7e3c5c 100644
--- a/src/Umbraco.Infrastructure/RuntimeOptions.cs
+++ b/src/Umbraco.Infrastructure/RuntimeOptions.cs
@@ -16,7 +16,7 @@ namespace Umbraco.Core
public static class RuntimeOptions
{
private static List> _onBoot;
- private static List> _onEssentials;
+ private static List> _onEssentials;
///
/// Executes the RuntimeBoot handlers.
@@ -33,13 +33,13 @@ namespace Umbraco.Core
///
/// Executes the RuntimeEssentials handlers.
///
- internal static void DoRuntimeEssentials(Composition composition, AppCaches appCaches, TypeLoader typeLoader, IUmbracoDatabaseFactory databaseFactory)
+ internal static void DoRuntimeEssentials(IFactory factory)
{
if (_onEssentials== null)
return;
foreach (var action in _onEssentials)
- action(composition, appCaches, typeLoader, databaseFactory);
+ action(factory);
}
///
@@ -64,10 +64,10 @@ namespace Umbraco.Core
/// essential things (AppCaches, a TypeLoader, and a database factory) but
/// before anything else.
///
- public static void OnRuntimeEssentials(Action action)
+ public static void OnRuntimeEssentials(Action action)
{
if (_onEssentials == null)
- _onEssentials = new List>();
+ _onEssentials = new List>();
_onEssentials.Add(action);
}
}
diff --git a/src/Umbraco.Infrastructure/RuntimeState.cs b/src/Umbraco.Infrastructure/RuntimeState.cs
index eadb9fed21..e0099c5e7e 100644
--- a/src/Umbraco.Infrastructure/RuntimeState.cs
+++ b/src/Umbraco.Infrastructure/RuntimeState.cs
@@ -22,46 +22,22 @@ namespace Umbraco.Core
private readonly ILogger _logger;
private readonly IGlobalSettings _globalSettings;
private readonly ConcurrentHashSet _applicationUrls = new ConcurrentHashSet();
- private readonly Lazy _mainDom;
- private readonly Lazy _serverRegistrar;
private readonly IUmbracoVersion _umbracoVersion;
- private readonly IHostingEnvironment _hostingEnvironment;
private readonly IBackOfficeInfo _backOfficeInfo;
///
/// Initializes a new instance of the class.
///
public RuntimeState(ILogger logger, IGlobalSettings globalSettings,
- Lazy mainDom, Lazy serverRegistrar, IUmbracoVersion umbracoVersion,
- IHostingEnvironment hostingEnvironment,
+ IUmbracoVersion umbracoVersion,
IBackOfficeInfo backOfficeInfo)
{
_logger = logger;
_globalSettings = globalSettings;
- _mainDom = mainDom;
- _serverRegistrar = serverRegistrar;
_umbracoVersion = umbracoVersion;
- _hostingEnvironment = hostingEnvironment;
_backOfficeInfo = backOfficeInfo;
-
- ApplicationVirtualPath = _hostingEnvironment.ApplicationVirtualPath;
}
- ///
- /// Gets the server registrar.
- ///
- ///
- /// This is NOT exposed in the interface.
- ///
- private IServerRegistrar ServerRegistrar => _serverRegistrar.Value;
-
- ///
- /// Gets the application MainDom.
- ///
- ///
- /// This is NOT exposed in the interface as MainDom is internal.
- ///
- public IMainDom MainDom => _mainDom.Value;
///
public Version Version => _umbracoVersion.Current;
@@ -72,26 +48,14 @@ namespace Umbraco.Core
///
public SemVersion SemanticVersion => _umbracoVersion.SemanticVersion;
- ///
- public bool Debug => _hostingEnvironment.IsDebugMode;
-
- ///
- public bool IsMainDom => MainDom.IsMainDom;
-
- ///
- public ServerRole ServerRole => ServerRegistrar.GetCurrentServerRole();
-
///
public Uri ApplicationUrl { get; private set; }
///
- public string ApplicationVirtualPath { get; }
+ public string CurrentMigrationState { get; private set; }
///
- public string CurrentMigrationState { get; internal set; }
-
- ///
- public string FinalMigrationState { get; internal set; }
+ public string FinalMigrationState { get; private set; }
///
public RuntimeLevel Level { get; internal set; } = RuntimeLevel.Unknown;
@@ -253,7 +217,7 @@ namespace Umbraco.Core
Reason = RuntimeLevelReason.UpgradeMigrations;
}
- protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger)
+ private bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger)
{
var upgrader = new Upgrader(new UmbracoPlan(_umbracoVersion, _globalSettings));
var stateValueKey = upgrader.StateValueKey;
diff --git a/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs b/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs
index 0b5b81319f..2cda289591 100644
--- a/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs
+++ b/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs
@@ -81,7 +81,7 @@ namespace Umbraco.Web.Scheduling
private readonly string _logPrefix;
private readonly BackgroundTaskRunnerOptions _options;
private readonly ILogger _logger;
- private readonly IHostingEnvironment _hostingEnvironment;
+ private readonly IApplicationShutdownRegistry _hostingEnvironment;
private readonly object _locker = new object();
private readonly BufferBlock _tasks = new BufferBlock(new DataflowBlockOptions());
@@ -105,7 +105,7 @@ namespace Umbraco.Web.Scheduling
/// A logger.
/// The hosting environment
/// An optional main domain hook.
- public BackgroundTaskRunner(ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
+ public BackgroundTaskRunner(ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null)
: this(typeof(T).FullName, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook)
{ }
@@ -116,7 +116,7 @@ namespace Umbraco.Web.Scheduling
/// A logger.
/// The hosting environment
/// An optional main domain hook.
- public BackgroundTaskRunner(string name, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
+ public BackgroundTaskRunner(string name, ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null)
: this(name, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook)
{ }
@@ -127,7 +127,7 @@ namespace Umbraco.Web.Scheduling
/// A logger.
/// The hosting environment
/// An optional main domain hook.
- public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
+ public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null)
: this(typeof(T).FullName, options, logger, hostingEnvironment, hook)
{ }
@@ -139,7 +139,7 @@ namespace Umbraco.Web.Scheduling
/// A logger.
/// The hosting environment
/// An optional main domain hook.
- public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null)
+ public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
diff --git a/src/Umbraco.Infrastructure/Scheduling/HealthCheckNotifier.cs b/src/Umbraco.Infrastructure/Scheduling/HealthCheckNotifier.cs
index 04c1571b3b..e7692b851a 100644
--- a/src/Umbraco.Infrastructure/Scheduling/HealthCheckNotifier.cs
+++ b/src/Umbraco.Infrastructure/Scheduling/HealthCheckNotifier.cs
@@ -11,22 +11,27 @@ namespace Umbraco.Web.Scheduling
{
public class HealthCheckNotifier : RecurringTaskBase
{
- private readonly IRuntimeState _runtimeState;
+ private readonly IMainDom _mainDom;
private readonly HealthCheckCollection _healthChecks;
private readonly HealthCheckNotificationMethodCollection _notifications;
private readonly IProfilingLogger _logger;
private readonly IHealthChecksSettings _healthChecksSettingsConfig;
+ private readonly IServerRegistrar _serverRegistrar;
+ private readonly IRuntimeState _runtimeState;
public HealthCheckNotifier(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds,
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
- IRuntimeState runtimeState, IProfilingLogger logger, IHealthChecksSettings healthChecksSettingsConfig)
+ IMainDom mainDom, IProfilingLogger logger, IHealthChecksSettings healthChecksSettingsConfig, IServerRegistrar serverRegistrar,
+ IRuntimeState runtimeState)
: base(runner, delayMilliseconds, periodMilliseconds)
{
_healthChecks = healthChecks;
_notifications = notifications;
- _runtimeState = runtimeState;
+ _mainDom = mainDom;
_logger = logger;
_healthChecksSettingsConfig = healthChecksSettingsConfig;
+ _serverRegistrar = serverRegistrar;
+ _runtimeState = runtimeState;
}
public override async Task PerformRunAsync(CancellationToken token)
@@ -34,7 +39,7 @@ namespace Umbraco.Web.Scheduling
if (_runtimeState.Level != RuntimeLevel.Run)
return true; // repeat...
- switch (_runtimeState.ServerRole)
+ switch (_serverRegistrar.GetCurrentServerRole())
{
case ServerRole.Replica:
_logger.Debug("Does not run on replica servers.");
@@ -45,7 +50,7 @@ namespace Umbraco.Web.Scheduling
}
// ensure we do not run if not main domain, but do NOT lock it
- if (_runtimeState.IsMainDom == false)
+ if (_mainDom.IsMainDom == false)
{
_logger.Debug("Does not run if not MainDom.");
return false; // do NOT repeat, going down
diff --git a/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs b/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs
index 563d79a193..aaf09dbe8f 100644
--- a/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs
+++ b/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs
@@ -11,17 +11,19 @@ namespace Umbraco.Web.Scheduling
public class LogScrubber : RecurringTaskBase
{
- private readonly IRuntimeState _runtime;
+ private readonly IMainDom _mainDom;
+ private readonly IServerRegistrar _serverRegistrar;
private readonly IAuditService _auditService;
private readonly ILoggingSettings _settings;
private readonly IProfilingLogger _logger;
private readonly IScopeProvider _scopeProvider;
public LogScrubber(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds,
- IRuntimeState runtime, IAuditService auditService, ILoggingSettings settings, IScopeProvider scopeProvider, IProfilingLogger logger)
+ IMainDom mainDom, IServerRegistrar serverRegistrar, IAuditService auditService, ILoggingSettings settings, IScopeProvider scopeProvider, IProfilingLogger logger)
: base(runner, delayMilliseconds, periodMilliseconds)
{
- _runtime = runtime;
+ _mainDom = mainDom;
+ _serverRegistrar = serverRegistrar;
_auditService = auditService;
_settings = settings;
_scopeProvider = scopeProvider;
@@ -53,7 +55,7 @@ namespace Umbraco.Web.Scheduling
public override bool PerformRun()
{
- switch (_runtime.ServerRole)
+ switch (_serverRegistrar.GetCurrentServerRole())
{
case ServerRole.Replica:
_logger.Debug("Does not run on replica servers.");
@@ -64,7 +66,7 @@ namespace Umbraco.Web.Scheduling
}
// ensure we do not run if not main domain, but do NOT lock it
- if (_runtime.IsMainDom == false)
+ if (_mainDom.IsMainDom == false)
{
_logger.Debug("Does not run if not MainDom.");
return false; // do NOT repeat, going down
diff --git a/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs b/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs
index b074704033..fea16999fd 100644
--- a/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs
+++ b/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs
@@ -10,16 +10,20 @@ namespace Umbraco.Web.Scheduling
public class ScheduledPublishing : RecurringTaskBase
{
private readonly IRuntimeState _runtime;
+ private readonly IMainDom _mainDom;
+ private readonly IServerRegistrar _serverRegistrar;
private readonly IContentService _contentService;
private readonly IUmbracoContextFactory _umbracoContextFactory;
private readonly ILogger _logger;
private readonly IServerMessenger _serverMessenger;
public ScheduledPublishing(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds,
- IRuntimeState runtime, IContentService contentService, IUmbracoContextFactory umbracoContextFactory, ILogger logger, IServerMessenger serverMessenger)
+ IRuntimeState runtime, IMainDom mainDom, IServerRegistrar serverRegistrar, IContentService contentService, IUmbracoContextFactory umbracoContextFactory, ILogger logger, IServerMessenger serverMessenger)
: base(runner, delayMilliseconds, periodMilliseconds)
{
_runtime = runtime;
+ _mainDom = mainDom;
+ _serverRegistrar = serverRegistrar;
_contentService = contentService;
_umbracoContextFactory = umbracoContextFactory;
_logger = logger;
@@ -31,7 +35,7 @@ namespace Umbraco.Web.Scheduling
if (Suspendable.ScheduledPublishing.CanRun == false)
return true; // repeat, later
- switch (_runtime.ServerRole)
+ switch (_serverRegistrar.GetCurrentServerRole())
{
case ServerRole.Replica:
_logger.Debug("Does not run on replica servers.");
@@ -42,7 +46,7 @@ namespace Umbraco.Web.Scheduling
}
// ensure we do not run if not main domain, but do NOT lock it
- if (_runtime.IsMainDom == false)
+ if (_mainDom.IsMainDom == false)
{
_logger.Debug("Does not run if not MainDom.");
return false; // do NOT repeat, going down
diff --git a/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs
index c8ff67579a..30d0bc7e4a 100644
--- a/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs
+++ b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs
@@ -26,10 +26,12 @@ namespace Umbraco.Web.Scheduling
private const int OneHourMilliseconds = 3600000;
private readonly IRuntimeState _runtime;
+ private readonly IMainDom _mainDom;
+ private readonly IServerRegistrar _serverRegistrar;
private readonly IContentService _contentService;
private readonly IAuditService _auditService;
private readonly IProfilingLogger _logger;
- private readonly IHostingEnvironment _hostingEnvironment;
+ private readonly IApplicationShutdownRegistry _hostingEnvironment;
private readonly IScopeProvider _scopeProvider;
private readonly HealthCheckCollection _healthChecks;
private readonly HealthCheckNotificationMethodCollection _notifications;
@@ -43,7 +45,6 @@ namespace Umbraco.Web.Scheduling
private BackgroundTaskRunner _keepAliveRunner;
private BackgroundTaskRunner _publishingRunner;
- private BackgroundTaskRunner _tasksRunner;
private BackgroundTaskRunner _scrubberRunner;
private BackgroundTaskRunner _fileCleanupRunner;
private BackgroundTaskRunner _healthCheckRunner;
@@ -52,15 +53,17 @@ namespace Umbraco.Web.Scheduling
private object _locker = new object();
private IBackgroundTask[] _tasks;
- public SchedulerComponent(IRuntimeState runtime,
+ public SchedulerComponent(IRuntimeState runtime, IMainDom mainDom, IServerRegistrar serverRegistrar,
IContentService contentService, IAuditService auditService,
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger,
- IHostingEnvironment hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig,
+ IApplicationShutdownRegistry hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig,
IIOHelper ioHelper, IServerMessenger serverMessenger, IRequestAccessor requestAccessor,
ILoggingSettings loggingSettings, IKeepAliveSettings keepAliveSettings)
{
_runtime = runtime;
+ _mainDom = mainDom;
+ _serverRegistrar = serverRegistrar;
_contentService = contentService;
_auditService = auditService;
_scopeProvider = scopeProvider;
@@ -83,7 +86,6 @@ namespace Umbraco.Web.Scheduling
// backgrounds runners are web aware, if the app domain dies, these tasks will wind down correctly
_keepAliveRunner = new BackgroundTaskRunner("KeepAlive", _logger, _hostingEnvironment);
_publishingRunner = new BackgroundTaskRunner("ScheduledPublishing", _logger, _hostingEnvironment);
- _tasksRunner = new BackgroundTaskRunner("ScheduledTasks", _logger, _hostingEnvironment);
_scrubberRunner = new BackgroundTaskRunner("LogScrubber", _logger, _hostingEnvironment);
_fileCleanupRunner = new BackgroundTaskRunner("TempFileCleanup", _logger, _hostingEnvironment);
_healthCheckRunner = new BackgroundTaskRunner("HealthCheckNotifier", _logger, _hostingEnvironment);
@@ -138,7 +140,7 @@ namespace Umbraco.Web.Scheduling
{
// ping/keepalive
// on all servers
- var task = new KeepAlive(_keepAliveRunner, DefaultDelayMilliseconds, FiveMinuteMilliseconds, _runtime, keepAliveSettings, _logger);
+ var task = new KeepAlive(_keepAliveRunner, DefaultDelayMilliseconds, FiveMinuteMilliseconds, _runtime, _mainDom, keepAliveSettings, _logger, _serverRegistrar);
_keepAliveRunner.TryAdd(task);
return task;
}
@@ -147,7 +149,7 @@ namespace Umbraco.Web.Scheduling
{
// scheduled publishing/unpublishing
// install on all, will only run on non-replica servers
- var task = new ScheduledPublishing(_publishingRunner, DefaultDelayMilliseconds, OneMinuteMilliseconds, _runtime, _contentService, _umbracoContextFactory, _logger, _serverMessenger);
+ var task = new ScheduledPublishing(_publishingRunner, DefaultDelayMilliseconds, OneMinuteMilliseconds, _runtime, _mainDom, _serverRegistrar, _contentService, _umbracoContextFactory, _logger, _serverMessenger);
_publishingRunner.TryAdd(task);
return task;
}
@@ -173,7 +175,7 @@ namespace Umbraco.Web.Scheduling
}
var periodInMilliseconds = healthCheckSettingsConfig.NotificationSettings.PeriodInHours * 60 * 60 * 1000;
- var task = new HealthCheckNotifier(_healthCheckRunner, delayInMilliseconds, periodInMilliseconds, healthChecks, notifications, _runtime, logger, _healthChecksSettingsConfig);
+ var task = new HealthCheckNotifier(_healthCheckRunner, delayInMilliseconds, periodInMilliseconds, healthChecks, notifications, _mainDom, logger, _healthChecksSettingsConfig, _serverRegistrar, _runtime);
_healthCheckRunner.TryAdd(task);
return task;
}
@@ -182,7 +184,7 @@ namespace Umbraco.Web.Scheduling
{
// log scrubbing
// install on all, will only run on non-replica servers
- var task = new LogScrubber(_scrubberRunner, DefaultDelayMilliseconds, LogScrubber.GetLogScrubbingInterval(), _runtime, _auditService, settings, _scopeProvider, _logger);
+ var task = new LogScrubber(_scrubberRunner, DefaultDelayMilliseconds, LogScrubber.GetLogScrubbingInterval(), _mainDom, _serverRegistrar, _auditService, settings, _scopeProvider, _logger);
_scrubberRunner.TryAdd(task);
return task;
}
@@ -194,7 +196,7 @@ namespace Umbraco.Web.Scheduling
var task = new TempFileCleanup(_fileCleanupRunner, DefaultDelayMilliseconds, OneHourMilliseconds,
new[] { new DirectoryInfo(_ioHelper.MapPath(Constants.SystemDirectories.TempFileUploads)) },
TimeSpan.FromDays(1), //files that are over a day old
- _runtime, _logger);
+ _mainDom, _logger);
_scrubberRunner.TryAdd(task);
return task;
}
diff --git a/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs b/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs
index 2c964a2723..1946e2041b 100644
--- a/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs
+++ b/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs
@@ -18,10 +18,10 @@ namespace Umbraco.Web.Search
private readonly IndexRebuilder _indexRebuilder;
private readonly IMainDom _mainDom;
private readonly IProfilingLogger _logger;
- private readonly IHostingEnvironment _hostingEnvironment;
+ private readonly IApplicationShutdownRegistry _hostingEnvironment;
private static BackgroundTaskRunner _rebuildOnStartupRunner;
- public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IHostingEnvironment hostingEnvironment, IndexRebuilder indexRebuilder)
+ public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IApplicationShutdownRegistry hostingEnvironment, IndexRebuilder indexRebuilder)
{
_mainDom = mainDom;
_logger = logger;
@@ -32,8 +32,6 @@ namespace Umbraco.Web.Search
///
/// Called to rebuild empty indexes on startup
///
- ///
- ///
///
///
public void RebuildIndexes(bool onlyEmptyIndexes, int waitMilliseconds = 0)
diff --git a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs
index 5a46a37d43..c915013162 100644
--- a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs
+++ b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs
@@ -28,10 +28,11 @@ namespace Umbraco.Core.Sync
//
public class DatabaseServerMessenger : ServerMessengerBase, IDatabaseServerMessenger
{
- private readonly IRuntimeState _runtime;
+ private readonly IMainDom _mainDom;
private readonly ManualResetEvent _syncIdle;
private readonly object _locko = new object();
private readonly IProfilingLogger _profilingLogger;
+ private readonly IServerRegistrar _serverRegistrar;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly CacheRefresherCollection _cacheRefreshers;
private readonly ISqlContext _sqlContext;
@@ -46,14 +47,15 @@ namespace Umbraco.Core.Sync
public DatabaseServerMessengerOptions Options { get; }
public DatabaseServerMessenger(
- IRuntimeState runtime, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog,
+ IMainDom mainDom, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, IServerRegistrar serverRegistrar,
bool distributedEnabled, DatabaseServerMessengerOptions options, IHostingEnvironment hostingEnvironment, CacheRefresherCollection cacheRefreshers)
: base(distributedEnabled)
{
ScopeProvider = scopeProvider ?? throw new ArgumentNullException(nameof(scopeProvider));
_sqlContext = sqlContext;
- _runtime = runtime;
+ _mainDom = mainDom;
_profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog));
+ _serverRegistrar = serverRegistrar;
_hostingEnvironment = hostingEnvironment;
_cacheRefreshers = cacheRefreshers;
Logger = proflog;
@@ -126,7 +128,7 @@ namespace Umbraco.Core.Sync
const int weight = 10;
- var registered = _runtime.MainDom.Register(
+ var registered = _mainDom.Register(
() =>
{
lock (_locko)
@@ -262,7 +264,7 @@ namespace Umbraco.Core.Sync
_lastPruned = _lastSync;
- switch (_runtime.ServerRole)
+ switch (_serverRegistrar.GetCurrentServerRole())
{
case ServerRole.Single:
case ServerRole.Master:
diff --git a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs
index 5db79de977..3cfefa77ce 100644
--- a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs
+++ b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs
@@ -42,7 +42,7 @@ namespace Umbraco.ModelsBuilder.Embedded
private static readonly string[] OurFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err" };
private readonly IModelsBuilderConfig _config;
- private readonly IHostingEnvironment _hostingEnvironment;
+ private readonly IApplicationShutdownRegistry _hostingLifetime;
private readonly IIOHelper _ioHelper;
private readonly ModelsGenerationError _errors;
@@ -51,12 +51,13 @@ namespace Umbraco.ModelsBuilder.Embedded
IProfilingLogger logger,
IModelsBuilderConfig config,
IHostingEnvironment hostingEnvironment,
+ IApplicationShutdownRegistry hostingLifetime,
IIOHelper ioHelper)
{
_umbracoServices = umbracoServices;
_logger = logger;
_config = config;
- _hostingEnvironment = hostingEnvironment;
+ _hostingLifetime = hostingLifetime;
_ioHelper = ioHelper;
_errors = new ModelsGenerationError(config, ioHelper);
_ver = 1; // zero is for when we had no version
@@ -64,7 +65,7 @@ namespace Umbraco.ModelsBuilder.Embedded
RazorBuildProvider.CodeGenerationStarted += RazorBuildProvider_CodeGenerationStarted;
- if (!_hostingEnvironment.IsHosted) return;
+ if (!hostingEnvironment.IsHosted) return;
var modelsDirectory = _config.ModelsDirectoryAbsolute(_ioHelper);
if (!Directory.Exists(modelsDirectory))
@@ -73,7 +74,7 @@ namespace Umbraco.ModelsBuilder.Embedded
// BEWARE! if the watcher is not properly released then for some reason the
// BuildManager will start confusing types - using a 'registered object' here
// though we should probably plug into Umbraco's MainDom - which is internal
- _hostingEnvironment.RegisterObject(this);
+ _hostingLifetime.RegisterObject(this);
_watcher = new FileSystemWatcher(modelsDirectory);
_watcher.Changed += WatcherOnChanged;
_watcher.EnableRaisingEvents = true;
@@ -677,7 +678,7 @@ namespace Umbraco.ModelsBuilder.Embedded
{
_watcher.EnableRaisingEvents = false;
_watcher.Dispose();
- _hostingEnvironment.UnregisterObject(this);
+ _hostingLifetime.UnregisterObject(this);
}
#endregion
diff --git a/src/Umbraco.Tests.Common/Builders/BuilderBase.cs b/src/Umbraco.Tests.Common/Builders/BuilderBase.cs
new file mode 100644
index 0000000000..d8fc048d1b
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/BuilderBase.cs
@@ -0,0 +1,7 @@
+namespace Umbraco.Tests.Common.Builders
+{
+ public abstract class BuilderBase
+ {
+ public abstract T Build();
+ }
+}
diff --git a/src/Umbraco.Tests.Common/Builders/ChildBuilderBase.cs b/src/Umbraco.Tests.Common/Builders/ChildBuilderBase.cs
new file mode 100644
index 0000000000..e1436ac1fe
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/ChildBuilderBase.cs
@@ -0,0 +1,19 @@
+namespace Umbraco.Tests.Common.Builders
+{
+ public abstract class ChildBuilderBase : BuilderBase
+ {
+ private readonly TParent _parentBuilder;
+
+ protected ChildBuilderBase(TParent parentBuilder)
+ {
+ _parentBuilder = parentBuilder;
+ }
+
+
+ public TParent Done()
+ {
+ return _parentBuilder;
+ }
+
+ }
+}
diff --git a/src/Umbraco.Tests.Common/Builders/ConfigurationEditorBuilder.cs b/src/Umbraco.Tests.Common/Builders/ConfigurationEditorBuilder.cs
new file mode 100644
index 0000000000..7789090d16
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/ConfigurationEditorBuilder.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using Umbraco.Core.PropertyEditors;
+
+namespace Umbraco.Tests.Common.Builders
+{
+ public class ConfigurationEditorBuilder : ChildBuilderBase
+ {
+ private IDictionary _defaultConfiguration;
+
+
+ public ConfigurationEditorBuilder(TParent parentBuilder) : base(parentBuilder)
+ {
+ }
+
+
+ public ConfigurationEditorBuilder WithDefaultConfiguration(IDictionary defaultConfiguration)
+ {
+ _defaultConfiguration = defaultConfiguration;
+ return this;
+ }
+
+ public override IConfigurationEditor Build()
+ {
+ var defaultConfiguration = _defaultConfiguration ?? new Dictionary();
+
+ return new ConfigurationEditor()
+ {
+ DefaultConfiguration = defaultConfiguration,
+ };
+ }
+
+ }
+}
diff --git a/src/Umbraco.Tests.Common/Builders/DataEditorBuilder.cs b/src/Umbraco.Tests.Common/Builders/DataEditorBuilder.cs
new file mode 100644
index 0000000000..b3c3ff1b7e
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/DataEditorBuilder.cs
@@ -0,0 +1,54 @@
+using System.Collections.Generic;
+using Moq;
+using Umbraco.Core.Logging;
+using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Services;
+using Umbraco.Core.Strings;
+
+namespace Umbraco.Tests.Common.Builders
+{
+ public class DataEditorBuilder : ChildBuilderBase
+ {
+ private readonly ConfigurationEditorBuilder> _explicitConfigurationEditorBuilder;
+ private readonly DataValueEditorBuilder> _explicitValueEditorBuilder;
+ private IDictionary _defaultConfiguration;
+
+ public DataEditorBuilder(TParent parentBuilder) : base(parentBuilder)
+ {
+ _explicitConfigurationEditorBuilder = new ConfigurationEditorBuilder>(this);
+ _explicitValueEditorBuilder = new DataValueEditorBuilder>(this);
+ }
+
+ public DataEditorBuilder WithDefaultConfiguration(IDictionary defaultConfiguration)
+ {
+ _defaultConfiguration = defaultConfiguration;
+ return this;
+ }
+
+ public ConfigurationEditorBuilder> AddExplicitConfigurationEditorBuilder() =>
+ _explicitConfigurationEditorBuilder;
+
+ public DataValueEditorBuilder> AddExplicitValueEditorBuilder() =>
+ _explicitValueEditorBuilder;
+
+ public override IDataEditor Build()
+ {
+ var defaultConfiguration = _defaultConfiguration ?? new Dictionary();
+ var explicitConfigurationEditor = _explicitConfigurationEditorBuilder.Build();
+ var explicitValueEditor = _explicitValueEditorBuilder.Build();
+
+ return new DataEditor(
+ Mock.Of(),
+ Mock.Of(),
+ Mock.Of(),
+ Mock.Of(),
+ Mock.Of()
+ )
+ {
+ DefaultConfiguration = defaultConfiguration,
+ ExplicitConfigurationEditor = explicitConfigurationEditor,
+ ExplicitValueEditor = explicitValueEditor
+ };
+ }
+ }
+}
diff --git a/src/Umbraco.Tests.Common/Builders/DataTypeBuilder.cs b/src/Umbraco.Tests.Common/Builders/DataTypeBuilder.cs
new file mode 100644
index 0000000000..20dc1bab81
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/DataTypeBuilder.cs
@@ -0,0 +1,160 @@
+using System;
+using Umbraco.Core.Models;
+using Umbraco.Tests.Common.Builders.Interfaces;
+
+namespace Umbraco.Tests.Common.Builders
+{
+ public class DataTypeBuilder
+ : BuilderBase,
+ IWithIdBuilder,
+ IWithKeyBuilder,
+ IWithCreateDateBuilder,
+ IWithUpdateDateBuilder,
+ IWithDeleteDateBuilder,
+ IWithNameBuilder
+ {
+ private readonly DataEditorBuilder _dataEditorBuilder;
+ private int? _id;
+ private int? _parentId;
+ private Guid? _key;
+ private DateTime? _createDate;
+ private DateTime? _updateDate;
+ private DateTime? _deleteDate;
+ private string _name;
+ private bool? _trashed;
+ // private object _configuration;
+ private int? _level;
+ private string _path;
+ private int? _creatorId;
+ private ValueStorageType? _databaseType;
+ private int? _sortOrder;
+
+ public DataTypeBuilder()
+ {
+ _dataEditorBuilder = new DataEditorBuilder(this);
+ }
+
+ public DataTypeBuilder WithParentId(int parentId)
+ {
+ _parentId = parentId;
+ return this;
+ }
+
+ public DataTypeBuilder WithTrashed(bool trashed)
+ {
+ _trashed = trashed;
+ return this;
+ }
+
+ // public DataTypeBuilder WithConfiguration(object configuration)
+ // {
+ // _configuration = configuration;
+ // return this;
+ // }
+
+ public DataTypeBuilder WithLevel(int level)
+ {
+ _level = level;
+ return this;
+ }
+
+ public DataTypeBuilder WithPath(string path)
+ {
+ _path = path;
+ return this;
+ }
+
+ public DataTypeBuilder WithCreatorId(int creatorId)
+ {
+ _creatorId = creatorId;
+ return this;
+ }
+
+ public DataTypeBuilder WithDatabaseType(ValueStorageType databaseType)
+ {
+ _databaseType = databaseType;
+ return this;
+ }
+
+ public DataTypeBuilder WithSortOrder(int sortOrder)
+ {
+ _sortOrder = sortOrder;
+ return this;
+ }
+
+ public DataEditorBuilder AddEditor()
+ {
+ return _dataEditorBuilder;
+ }
+
+ public override DataType Build()
+ {
+ var editor = _dataEditorBuilder.Build();
+ var parentId = _parentId ?? -1;
+ var id = _id ?? 1;
+ var key = _key ?? Guid.NewGuid();
+ var createDate = _createDate ?? DateTime.Now;
+ var updateDate = _updateDate ?? DateTime.Now;
+ var deleteDate = _deleteDate ?? null;
+ var name = _name ?? Guid.NewGuid().ToString();
+ // var configuration = _configuration ?? editor.GetConfigurationEditor().DefaultConfigurationObject;
+ var level = _level ?? 0;
+ var path = _path ?? string.Empty;
+ var creatorId = _creatorId ?? 1;
+ var databaseType = _databaseType ?? ValueStorageType.Ntext;
+ var sortOrder = _sortOrder ?? 0;
+
+ return new DataType(editor, parentId)
+ {
+ Id = id,
+ Key = key,
+ CreateDate = createDate,
+ UpdateDate = updateDate,
+ DeleteDate = deleteDate,
+ Name = name,
+ Trashed = _trashed ?? false,
+ Level = level,
+ Path = path,
+ CreatorId = creatorId,
+ DatabaseType = databaseType,
+ SortOrder = sortOrder,
+ };
+ }
+
+ int? IWithIdBuilder.Id
+ {
+ get => _id;
+ set => _id = value;
+ }
+
+ Guid? IWithKeyBuilder.Key
+ {
+ get => _key;
+ set => _key = value;
+ }
+
+ DateTime? IWithCreateDateBuilder.CreateDate
+ {
+ get => _createDate;
+ set => _createDate = value;
+ }
+
+ DateTime? IWithUpdateDateBuilder.UpdateDate
+ {
+ get => _updateDate;
+ set => _updateDate = value;
+ }
+
+ DateTime? IWithDeleteDateBuilder.DeleteDate
+ {
+ get => _deleteDate;
+ set => _deleteDate = value;
+ }
+
+ string IWithNameBuilder.Name
+ {
+ get => _name;
+ set => _name = value;
+ }
+ }
+}
diff --git a/src/Umbraco.Tests.Common/Builders/DataValueEditorBuilder.cs b/src/Umbraco.Tests.Common/Builders/DataValueEditorBuilder.cs
new file mode 100644
index 0000000000..3d0b518ee7
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/DataValueEditorBuilder.cs
@@ -0,0 +1,66 @@
+using System;
+using Moq;
+using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Services;
+using Umbraco.Core.Strings;
+
+namespace Umbraco.Tests.Common.Builders
+{
+ public class DataValueEditorBuilder : ChildBuilderBase
+ {
+ private string _configuration;
+ private string _view;
+ private bool? _hideLabel;
+ private string _valueType;
+
+
+ public DataValueEditorBuilder(TParent parentBuilder) : base(parentBuilder)
+ {
+ }
+
+ public DataValueEditorBuilder WithConfiguration(string configuration)
+ {
+ _configuration = configuration;
+ return this;
+ }
+
+ public DataValueEditorBuilder WithView(string view)
+ {
+ _view = view;
+ return this;
+ }
+
+ public DataValueEditorBuilder WithHideLabel(bool hideLabel)
+ {
+ _hideLabel = hideLabel;
+ return this;
+ }
+
+ public DataValueEditorBuilder WithValueType(string valueType)
+ {
+ _valueType = valueType;
+ return this;
+ }
+
+ public override IDataValueEditor Build()
+ {
+ var configuration = _configuration ?? null;
+ var view = _view ?? null;
+ var hideLabel = _hideLabel ?? false;
+ var valueType = _valueType ?? Guid.NewGuid().ToString();
+
+ return new DataValueEditor(
+ Mock.Of(),
+ Mock.Of(),
+ Mock.Of(),
+ Mock.Of()
+ )
+ {
+ Configuration = configuration,
+ View = view,
+ HideLabel = hideLabel,
+ ValueType = valueType,
+ };
+ }
+ }
+}
diff --git a/src/Umbraco.Tests.Common/Builders/DictionaryItemBuilder.cs b/src/Umbraco.Tests.Common/Builders/DictionaryItemBuilder.cs
new file mode 100644
index 0000000000..206bccba80
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/DictionaryItemBuilder.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Umbraco.Core.Models;
+using Umbraco.Tests.Common.Builders.Interfaces;
+
+namespace Umbraco.Tests.Common.Builders
+{
+ public class DictionaryItemBuilder
+ : BuilderBase,
+ IWithIdBuilder,
+ IWithCreateDateBuilder,
+ IWithUpdateDateBuilder,
+ IWithDeleteDateBuilder,
+ IWithKeyBuilder
+ {
+ private readonly List _translationBuilders =
+ new List();
+
+ private DateTime? _createDate;
+ private DateTime? _deleteDate;
+ private int? _id;
+ private string _itemKey;
+ private Guid? _key;
+ private Guid? _parentId;
+ private DateTime? _updateDate;
+
+ DateTime? IWithCreateDateBuilder.CreateDate
+ {
+ get => _createDate;
+ set => _createDate = value;
+ }
+
+ DateTime? IWithDeleteDateBuilder.DeleteDate
+ {
+ get => _deleteDate;
+ set => _deleteDate = value;
+ }
+
+ int? IWithIdBuilder.Id
+ {
+ get => _id;
+ set => _id = value;
+ }
+
+ Guid? IWithKeyBuilder.Key
+ {
+ get => _key;
+ set => _key = value;
+ }
+
+ DateTime? IWithUpdateDateBuilder.UpdateDate
+ {
+ get => _updateDate;
+ set => _updateDate = value;
+ }
+
+ public override DictionaryItem Build()
+ {
+ var createDate = _createDate ?? DateTime.Now;
+ var updateDate = _updateDate ?? DateTime.Now;
+ var deleteDate = _deleteDate ?? null;
+ var id = _id ?? 1;
+ var key = _key ?? Guid.NewGuid();
+ var parentId = _parentId ?? null;
+ var itemKey = _itemKey ?? Guid.NewGuid().ToString();
+
+ var result = new DictionaryItem(itemKey)
+ {
+ Translations = _translationBuilders.Select(x => x.Build()),
+ CreateDate = createDate,
+ UpdateDate = updateDate,
+ DeleteDate = deleteDate,
+ Id = id,
+ ParentId = parentId,
+ Key = key,
+ };
+ return result;
+ }
+
+ public DictionaryItemBuilder WithParentId(Guid parentId)
+ {
+ _parentId = parentId;
+ return this;
+ }
+
+ public DictionaryItemBuilder WithItemKey(string itemKey)
+ {
+ _itemKey = itemKey;
+ return this;
+ }
+
+ public DictionaryTranslationBuilder AddTranslation()
+ {
+ var builder = new DictionaryTranslationBuilder(this);
+
+ _translationBuilders.Add(builder);
+
+ return builder;
+ }
+
+ public DictionaryItemBuilder WithRandomTranslations(int count)
+ {
+ for (var i = 0; i < count; i++)
+ {
+ AddTranslation().Done();
+ }
+
+ return this;
+ }
+ }
+}
diff --git a/src/Umbraco.Tests.Common/Builders/DictionaryTranslationBuilder.cs b/src/Umbraco.Tests.Common/Builders/DictionaryTranslationBuilder.cs
new file mode 100644
index 0000000000..37fb7c5b07
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/DictionaryTranslationBuilder.cs
@@ -0,0 +1,90 @@
+using System;
+using Umbraco.Core.Models;
+using Umbraco.Tests.Common.Builders.Interfaces;
+
+namespace Umbraco.Tests.Common.Builders
+{
+ public class DictionaryTranslationBuilder
+ : ChildBuilderBase,
+ IWithIdBuilder,
+ IWithCreateDateBuilder,
+ IWithUpdateDateBuilder,
+ IWithDeleteDateBuilder,
+ IWithKeyBuilder
+ {
+ private readonly LanguageBuilder _languageBuilder;
+ private readonly Guid? _uniqueId = null;
+ private DateTime? _createDate;
+ private DateTime? _deleteDate;
+ private int? _id;
+ private Guid? _key;
+ private DateTime? _updateDate;
+ private string _value;
+
+
+ public DictionaryTranslationBuilder(DictionaryItemBuilder parentBuilder) : base(parentBuilder)
+ {
+ _languageBuilder = new LanguageBuilder(this);
+ }
+
+ DateTime? IWithCreateDateBuilder.CreateDate
+ {
+ get => _createDate;
+ set => _createDate = value;
+ }
+
+ DateTime? IWithDeleteDateBuilder.DeleteDate
+ {
+ get => _deleteDate;
+ set => _deleteDate = value;
+ }
+
+ int? IWithIdBuilder.Id
+ {
+ get => _id;
+ set => _id = value;
+ }
+
+ Guid? IWithKeyBuilder.Key
+ {
+ get => _key;
+ set => _key = value;
+ }
+
+ DateTime? IWithUpdateDateBuilder.UpdateDate
+ {
+ get => _updateDate;
+ set => _updateDate = value;
+ }
+
+ public override IDictionaryTranslation Build()
+ {
+ var createDate = _createDate ?? DateTime.Now;
+ var updateDate = _updateDate ?? DateTime.Now;
+ var deleteDate = _deleteDate ?? null;
+ var id = _id ?? 1;
+ var key = _key ?? Guid.NewGuid();
+
+ var result = new DictionaryTranslation(
+ _languageBuilder.Build(),
+ _value ?? Guid.NewGuid().ToString(),
+ _uniqueId ?? key)
+ {
+ CreateDate = createDate,
+ UpdateDate = updateDate,
+ DeleteDate = deleteDate,
+ Id = id
+ };
+
+ return result;
+ }
+
+ public LanguageBuilder AddLanguage() => _languageBuilder;
+
+ public DictionaryTranslationBuilder WithValue(string value)
+ {
+ _value = value;
+ return this;
+ }
+ }
+}
diff --git a/src/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs b/src/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs
new file mode 100644
index 0000000000..c8f3f80bf1
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs
@@ -0,0 +1,50 @@
+using System;
+using Umbraco.Tests.Common.Builders.Interfaces;
+
+namespace Umbraco.Tests.Common.Builders.Extensions
+{
+ public static class BuilderExtensions
+ {
+ public static T WithId(this T builder, int id)
+ where T : IWithIdBuilder
+ {
+ builder.Id = id;
+ return builder;
+ }
+
+ public static T WithCreateDate(this T builder, DateTime createDate)
+ where T : IWithCreateDateBuilder
+ {
+ builder.CreateDate = createDate;
+ return builder;
+ }
+
+ public static T WithUpdateDate(this T builder, DateTime updateDate)
+ where T : IWithUpdateDateBuilder
+ {
+ builder.UpdateDate = updateDate;
+ return builder;
+ }
+
+ public static T WithAlias(this T builder, string alias)
+ where T : IWithAliasBuilder
+ {
+ builder.Alias = alias;
+ return builder;
+ }
+
+ public static T WithName(this T builder, string name)
+ where T : IWithNameBuilder
+ {
+ builder.Name = name;
+ return builder;
+ }
+
+ public static T WithKey(this T builder, Guid key)
+ where T : IWithKeyBuilder
+ {
+ builder.Key = key;
+ return builder;
+ }
+ }
+}
diff --git a/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs b/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs
new file mode 100644
index 0000000000..56e242146c
--- /dev/null
+++ b/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs
@@ -0,0 +1,249 @@
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Tests.Common.Builders
+{
+ public class GlobalSettingsBuilder : GlobalSettingsBuilder
/// The default constructor will boot the cache, load data from file or database, /// wire events in order to manage changes, etc.
public XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache,
- IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IGlobalSettings globalSettings, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper)
- : this(contentTypeService, contentService, scopeProvider, routesCache, contentTypeCache, publishedSnapshotAccessor, mainDom, false, false, documentRepository, mediaRepository, memberRepository, globalSettings, entitySerializer, hostingEnvironment, shortStringHelper)
+ IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper)
+ : this(contentTypeService, contentService, scopeProvider, routesCache, contentTypeCache, publishedSnapshotAccessor, mainDom, false, false, documentRepository, mediaRepository, memberRepository, entitySerializer, hostingEnvironment, hostingLifetime, shortStringHelper)
{ }
// internal for unit tests
@@ -76,7 +74,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
// TODO: er, we DO have a DB?
internal XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache,
IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom,
- bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IGlobalSettings globalSettings, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper)
+ bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper)
{
if (testing == false)
EnsureConfigurationIsValid();
@@ -90,12 +88,11 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
_documentRepository = documentRepository;
_mediaRepository = mediaRepository;
_memberRepository = memberRepository;
- _globalSettings = globalSettings;
_entitySerializer = entitySerializer;
- _hostingEnvironment = hostingEnvironment;
+ _hostingLifetime = hostingLifetime;
_shortStringHelper = shortStringHelper;
- _xmlFileName = TestHelper.IOHelper.MapPath(SystemFiles.GetContentCacheXml(_hostingEnvironment));
+ _xmlFileName = TestHelper.IOHelper.MapPath(SystemFiles.GetContentCacheXml(hostingEnvironment));
if (testing)
{
@@ -150,7 +147,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
LongRunning = true,
KeepAlive = true,
Hosted = false // main domain will take care of stopping the runner (see below)
- }, logger, _hostingEnvironment);
+ }, logger, _hostingLifetime);
// create (and add to runner)
_persisterTask = new XmlStoreFilePersister(runner, this, logger);
@@ -207,7 +204,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
MediaTypeService.ScopedRefreshedEntity += OnMediaTypeRefreshedEntity;
MemberTypeService.ScopedRefreshedEntity += OnMemberTypeRefreshedEntity;
- _withRepositoryEvents = true;
}
private void ClearEvents()
@@ -226,7 +222,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
MediaTypeService.ScopedRefreshedEntity -= OnMediaTypeRefreshedEntity;
MemberTypeService.ScopedRefreshedEntity -= OnMemberTypeRefreshedEntity;
- _withRepositoryEvents = false;
}
private void LazyInitializeContent()
diff --git a/src/Umbraco.Tests/Models/DataTypeTests.cs b/src/Umbraco.Tests/Models/DataTypeTests.cs
deleted file mode 100644
index fe8a26e431..0000000000
--- a/src/Umbraco.Tests/Models/DataTypeTests.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using System;
-using System.Diagnostics;
-using Moq;
-using Newtonsoft.Json;
-using NUnit.Framework;
-using Umbraco.Core.Logging;
-using Umbraco.Core.Models;
-using Umbraco.Core.PropertyEditors;
-using Umbraco.Core.Serialization;
-using Umbraco.Core.Services;
-using Umbraco.Core.Strings;
-
-namespace Umbraco.Tests.Models
-{
- [TestFixture]
- public class DataTypeTests
- {
- [Test]
- public void Can_Deep_Clone()
- {
- var dtd = new DataType(new VoidEditor(Mock.Of(), Mock.Of(), Mock.Of(),Mock.Of(), Mock.Of()), 9)
- {
- CreateDate = DateTime.Now,
- CreatorId = 5,
- DatabaseType = ValueStorageType.Nvarchar,
- Id = 4,
- Key = Guid.NewGuid(),
- Level = 7,
- Name = "Test",
- ParentId = 9,
- Path = "-1,2",
- SortOrder = 8,
- Trashed = true,
- UpdateDate = DateTime.Now
- };
- var clone = (DataType) dtd.DeepClone();
-
- Assert.AreNotSame(clone, dtd);
- Assert.AreEqual(clone, dtd);
- Assert.AreEqual(clone.CreateDate, dtd.CreateDate);
- Assert.AreEqual(clone.CreatorId, dtd.CreatorId);
- Assert.AreEqual(clone.DatabaseType, dtd.DatabaseType);
- Assert.AreEqual(clone.Id, dtd.Id);
- Assert.AreEqual(clone.Key, dtd.Key);
- Assert.AreEqual(clone.Level, dtd.Level);
- Assert.AreEqual(clone.Name, dtd.Name);
- Assert.AreEqual(clone.ParentId, dtd.ParentId);
- Assert.AreEqual(clone.Path, dtd.Path);
- Assert.AreEqual(clone.SortOrder, dtd.SortOrder);
- Assert.AreEqual(clone.Trashed, dtd.Trashed);
- Assert.AreEqual(clone.UpdateDate, dtd.UpdateDate);
-
- //This double verifies by reflection
- var allProps = clone.GetType().GetProperties();
- foreach (var propertyInfo in allProps)
- {
- Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(dtd, null));
- }
- }
-
- [Test]
- public void Can_Serialize_Without_Error()
- {
- var dtd = new DataType(new VoidEditor(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(),Mock.Of()), 9)
- {
- CreateDate = DateTime.Now,
- CreatorId = 5,
- DatabaseType = ValueStorageType.Nvarchar,
- Id = 4,
- Key = Guid.NewGuid(),
- Level = 7,
- Name = "Test",
- ParentId = 9,
- Path = "-1,2",
- SortOrder = 8,
- Trashed = true,
- UpdateDate = DateTime.Now
- };
-
- var json = JsonConvert.SerializeObject(dtd);
- Debug.Print(json);
- }
-
- }
-}
diff --git a/src/Umbraco.Tests/Models/DictionaryItemTests.cs b/src/Umbraco.Tests/Models/DictionaryItemTests.cs
deleted file mode 100644
index 835cfd96f1..0000000000
--- a/src/Umbraco.Tests/Models/DictionaryItemTests.cs
+++ /dev/null
@@ -1,137 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Linq;
-using Newtonsoft.Json;
-using NUnit.Framework;
-using Umbraco.Core.Models;
-using Umbraco.Core.Serialization;
-using Umbraco.Tests.TestHelpers;
-
-namespace Umbraco.Tests.Models
-{
- [TestFixture]
- public class DictionaryItemTests
- {
- [Test]
- public void Can_Deep_Clone()
- {
- var item = new DictionaryItem("blah")
- {
- CreateDate = DateTime.Now,
- Id = 8,
- ItemKey = "blah",
- Key = Guid.NewGuid(),
- ParentId = Guid.NewGuid(),
- UpdateDate = DateTime.Now,
- Translations = new[]
- {
- new DictionaryTranslation(new Language(SettingsForTests.GenerateMockGlobalSettings(),"en-AU")
- {
- CreateDate = DateTime.Now,
- CultureName = "en",
- Id = 11,
- IsoCode = "AU",
- Key = Guid.NewGuid(),
- UpdateDate = DateTime.Now
- }, "colour")
- {
- CreateDate = DateTime.Now,
- Id = 88,
- Key = Guid.NewGuid(),
- UpdateDate = DateTime.Now
- },
- new DictionaryTranslation(new Language(SettingsForTests.GenerateMockGlobalSettings(),"en-US")
- {
- CreateDate = DateTime.Now,
- CultureName = "en",
- Id = 12,
- IsoCode = "US",
- Key = Guid.NewGuid(),
- UpdateDate = DateTime.Now
- }, "color")
- {
- CreateDate = DateTime.Now,
- Id = 89,
- Key = Guid.NewGuid(),
- UpdateDate = DateTime.Now
- },
- }
- };
-
- var clone = (DictionaryItem)item.DeepClone();
-
- Assert.AreNotSame(clone, item);
- Assert.AreEqual(clone, item);
- Assert.AreEqual(clone.CreateDate, item.CreateDate);
- Assert.AreEqual(clone.Id, item.Id);
- Assert.AreEqual(clone.ItemKey, item.ItemKey);
- Assert.AreEqual(clone.Key, item.Key);
- Assert.AreEqual(clone.ParentId, item.ParentId);
- Assert.AreEqual(clone.UpdateDate, item.UpdateDate);
- Assert.AreEqual(clone.Translations.Count(), item.Translations.Count());
- for (var i = 0; i < item.Translations.Count(); i++)
- {
- Assert.AreNotSame(clone.Translations.ElementAt(i), item.Translations.ElementAt(i));
- Assert.AreEqual(clone.Translations.ElementAt(i), item.Translations.ElementAt(i));
- }
-
- //This double verifies by reflection
- var allProps = clone.GetType().GetProperties();
- foreach (var propertyInfo in allProps)
- {
- Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null));
- }
- }
-
- [Test]
- public void Can_Serialize_Without_Error()
- {
- var item = new DictionaryItem("blah")
- {
- CreateDate = DateTime.Now,
- Id = 8,
- ItemKey = "blah",
- Key = Guid.NewGuid(),
- ParentId = Guid.NewGuid(),
- UpdateDate = DateTime.Now,
- Translations = new[]
- {
- new DictionaryTranslation(new Language(SettingsForTests.GenerateMockGlobalSettings(),"en-AU")
- {
- CreateDate = DateTime.Now,
- CultureName = "en",
- Id = 11,
- IsoCode = "AU",
- Key = Guid.NewGuid(),
- UpdateDate = DateTime.Now
- }, "colour")
- {
- CreateDate = DateTime.Now,
- Id = 88,
- Key = Guid.NewGuid(),
- UpdateDate = DateTime.Now
- },
- new DictionaryTranslation(new Language(SettingsForTests.GenerateMockGlobalSettings(),"en-US")
- {
- CreateDate = DateTime.Now,
- CultureName = "en",
- Id = 12,
- IsoCode = "US",
- Key = Guid.NewGuid(),
- UpdateDate = DateTime.Now
- }, "color")
- {
- CreateDate = DateTime.Now,
- Id = 89,
- Key = Guid.NewGuid(),
- UpdateDate = DateTime.Now
- },
- }
- };
-
-
- var json = JsonConvert.SerializeObject(item);
- Debug.Print(json);
- }
- }
-}
diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs
index 561a6d945e..f9de3579c2 100644
--- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs
+++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs
@@ -32,8 +32,7 @@ namespace Umbraco.Tests.Routing
//create the module
var logger = Mock.Of();
var globalSettings = TestObjects.GetGlobalSettings();
- var runtime = new RuntimeState(logger, globalSettings,
- new Lazy(), new Lazy(), UmbracoVersion, HostingEnvironment, BackOfficeInfo);
+ var runtime = new RuntimeState(logger, globalSettings, UmbracoVersion, BackOfficeInfo);
_module = new UmbracoInjectedModule
(
diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs
index 92ab825ee2..6ccb2c3b35 100644
--- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs
+++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs
@@ -104,11 +104,6 @@ namespace Umbraco.Tests.Runtimes
return configs;
}
- private static IProfiler GetProfiler()
- {
- return new TestProfiler();
- }
-
public IRuntime Runtime { get; private set; }
protected override IRuntime GetRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo)
@@ -136,50 +131,14 @@ namespace Umbraco.Tests.Runtimes
return mock.Object;
}
- // FIXME: so how the f* should we do it now?
- /*
- // pretend we have the proper migration
- // else BootFailedException because our mock IUmbracoDatabaseFactory does not provide databases
- protected override bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory)
+ public override IFactory Configure(IRegister container)
{
- return true;
- }
- */
+ container.Register(Lifetime.Singleton);
- // because we don't even have the core runtime component,
- // there are a few required stuff that we need to compose
- public override void Compose(Composition composition)
- {
- base.Compose(composition);
-
- var scopeProvider = Mock.Of();
- Mock.Get(scopeProvider)
- .Setup(x => x.CreateScope(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny()))
- .Returns(Mock.Of());
-
- composition.RegisterUnique(scopeProvider);
- }
-
- private IMainDom _mainDom;
-
- public override IFactory Boot(IRegister container)
- {
- var factory = base.Boot(container);
- _mainDom = factory.GetInstance();
+ var factory = base.Configure(container);
return factory;
}
- public override void Terminate()
- {
- base.Terminate();
- }
-
// runs with only one single component
// UmbracoCoreComponent will be force-added too
// and that's it
diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs
index 0cb3f3e2e1..f167aafb89 100644
--- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs
+++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs
@@ -72,7 +72,7 @@ namespace Umbraco.Tests.Runtimes
var mainDom = new SimpleMainDom();
var umbracoVersion = TestHelper.GetUmbracoVersion();
var backOfficeInfo = TestHelper.GetBackOfficeInfo();
- var runtimeState = new RuntimeState(logger, null, new Lazy(() => mainDom), new Lazy(() => factory.GetInstance()), umbracoVersion, hostingEnvironment, backOfficeInfo);
+ var runtimeState = new RuntimeState(logger, null, umbracoVersion, backOfficeInfo);
var configs = TestHelper.GetConfigs();
var variationContextAccessor = TestHelper.VariationContextAccessor;
@@ -80,11 +80,10 @@ 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);
- coreRuntime.Compose(composition);
// determine actual runtime level
runtimeState.DetermineRuntimeLevel(databaseFactory, logger);
@@ -275,11 +274,10 @@ 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);
- coreRuntime.Compose(composition);
// get the components
// all of them?
diff --git a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs
index f10b141916..2291584f66 100644
--- a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs
+++ b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs
@@ -19,13 +19,13 @@ namespace Umbraco.Tests.Scheduling
public class BackgroundTaskRunnerTests
{
private ILogger _logger;
- private IHostingEnvironment _hostingEnvironment;
+ private IApplicationShutdownRegistry _hostingEnvironment;
[OneTimeSetUp]
public void InitializeFixture()
{
_logger = new ConsoleLogger(new MessageTemplates());
- _hostingEnvironment = TestHelper.GetHostingEnvironment();
+ _hostingEnvironment = TestHelper.GetHostingEnvironmentLifetime();
}
[Test]
@@ -934,7 +934,7 @@ namespace Umbraco.Tests.Scheduling
[Test]
public void SourceTaskTest()
{
- var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, _logger, TestHelper.GetHostingEnvironment());
+ var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, _logger, TestHelper.GetHostingEnvironmentLifetime());
var task = new SourceTask();
runner.Add(task);
diff --git a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs
index c65c7e3efb..01169abce2 100644
--- a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs
+++ b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs
@@ -22,7 +22,7 @@ namespace Umbraco.Tests.Scheduling
public async Task ThreadResumeIssue()
{
var logger = new DebugDiagnosticsLogger(new MessageTemplates());
- var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironment());
+ var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironmentLifetime());
var work = new ThreadResumeIssueWorkItem();
runner.Add(work);
@@ -77,7 +77,7 @@ namespace Umbraco.Tests.Scheduling
public async Task DebuggerInterferenceIssue()
{
var logger = new DebugDiagnosticsLogger(new MessageTemplates());
- var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironment());
+ var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironmentLifetime());
var taskCompleted = false;
runner.TaskCompleted += (sender, args) =>
{
diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs
index 05d4de6e23..11393e3e6b 100644
--- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs
+++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs
@@ -21,12 +21,12 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.PublishedContent;
+using Umbraco.Net;
using Umbraco.Core.Persistence;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
-using Umbraco.Net;
using Umbraco.Tests.Common;
using Umbraco.Web;
using Umbraco.Web.Hosting;
@@ -40,7 +40,7 @@ namespace Umbraco.Tests.TestHelpers
///
public static class TestHelper
{
- private static TestHelperInternal _testHelperInternal = new TestHelperInternal();
+ private static readonly TestHelperInternal _testHelperInternal = new TestHelperInternal();
private class TestHelperInternal : TestHelperBase
{
public TestHelperInternal() : base(typeof(TestHelperInternal).Assembly)
@@ -62,6 +62,9 @@ namespace Umbraco.Tests.TestHelpers
public override IHostingEnvironment GetHostingEnvironment()
=> new AspNetHostingEnvironment(SettingsForTests.GetDefaultHostingSettings());
+ public override IApplicationShutdownRegistry GetHostingEnvironmentLifetime()
+ => new AspNetApplicationShutdownRegistry();
+
public override IIpResolver GetIpResolver()
=> new AspNetIpResolver();
}
@@ -320,6 +323,8 @@ namespace Umbraco.Tests.TestHelpers
public static IHostingEnvironment GetHostingEnvironment() => _testHelperInternal.GetHostingEnvironment();
+ public static IApplicationShutdownRegistry GetHostingEnvironmentLifetime() => _testHelperInternal.GetHostingEnvironmentLifetime();
+
public static IIpResolver GetIpResolver() => _testHelperInternal.GetIpResolver();
public static IRequestCache GetRequestCache() => _testHelperInternal.GetRequestCache();
diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs
index 5cf2c7b6bd..fbfada118a 100644
--- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs
+++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs
@@ -265,6 +265,7 @@ namespace Umbraco.Tests.TestHelpers
Logger,
Factory.GetInstance(),
HostingEnvironment,
+ HostingLifetime,
ShortStringHelper,
new SiteDomainHelper(),
Factory.GetInstance(),
diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
index ca36a6049e..0345aab2da 100644
--- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
+++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs
@@ -51,10 +51,10 @@ using Umbraco.Web.Templates;
using Umbraco.Web.PropertyEditors;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Models;
+using Umbraco.Net;
using Umbraco.Core.Request;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
-using Umbraco.Net;
using Umbraco.Tests.LegacyXmlPublishedCache;
using Umbraco.Web.AspNet;
using Umbraco.Web.Install;
@@ -140,6 +140,7 @@ namespace Umbraco.Tests.Testing
protected virtual IProfilingLogger ProfilingLogger => Factory.GetInstance();
protected IHostingEnvironment HostingEnvironment { get; } = new AspNetHostingEnvironment(TestHelpers.SettingsForTests.GetDefaultHostingSettings());
+ protected IApplicationShutdownRegistry HostingLifetime { get; } = new AspNetApplicationShutdownRegistry();
protected IIpResolver IpResolver => Factory.GetInstance();
protected IBackOfficeInfo BackOfficeInfo => Factory.GetInstance();
protected AppCaches AppCaches => Factory.GetInstance();
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index 12d3ae111c..1d6d26be16 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -295,17 +295,13 @@
-
-
-
-
diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs
index 5e5197a28a..c5e9556d05 100644
--- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs
+++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs
@@ -423,6 +423,7 @@ namespace Umbraco.Tests.Web.Mvc
new TestDefaultCultureAccessor(),
Current.Logger, TestObjects.GetGlobalSettings(),
TestHelper.GetHostingEnvironment(),
+ TestHelper.GetHostingEnvironmentLifetime(),
ShortStringHelper,
new SiteDomainHelper(),
Factory.GetInstance(),
diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs
new file mode 100644
index 0000000000..92af822836
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Concurrent;
+using System.Threading;
+using Microsoft.Extensions.Hosting;
+using Umbraco.Core;
+using Umbraco.Core.Hosting;
+
+namespace Umbraco.Web.BackOffice.AspNetCore
+{
+ public class AspNetCoreApplicationShutdownRegistry : IApplicationShutdownRegistry
+ {
+ private readonly IHostApplicationLifetime _hostApplicationLifetime;
+ private readonly ConcurrentDictionary _registeredObjects =
+ new ConcurrentDictionary();
+
+ public AspNetCoreApplicationShutdownRegistry(IHostApplicationLifetime hostApplicationLifetime)
+ {
+ _hostApplicationLifetime = hostApplicationLifetime;
+ }
+
+ public void RegisterObject(IRegisteredObject registeredObject)
+ {
+ var wrapped = new RegisteredObjectWrapper(registeredObject);
+ if (!_registeredObjects.TryAdd(registeredObject, wrapped))
+ {
+ throw new InvalidOperationException("Could not register object");
+ }
+
+ var cancellationTokenRegistration = _hostApplicationLifetime.ApplicationStopping.Register(() => wrapped.Stop(true));
+ wrapped.CancellationTokenRegistration = cancellationTokenRegistration;
+ }
+
+ public void UnregisterObject(IRegisteredObject registeredObject)
+ {
+ if (_registeredObjects.TryGetValue(registeredObject, out var wrapped))
+ {
+ wrapped.CancellationTokenRegistration.Unregister();
+ }
+ }
+
+
+ private class RegisteredObjectWrapper
+ {
+ private readonly IRegisteredObject _inner;
+
+ public RegisteredObjectWrapper(IRegisteredObject inner)
+ {
+ _inner = inner;
+ }
+
+ public CancellationTokenRegistration CancellationTokenRegistration { get; set; }
+
+ public void Stop(bool immediate)
+ {
+ _inner.Stop(immediate);
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs
new file mode 100644
index 0000000000..fc38e429a0
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs
@@ -0,0 +1,27 @@
+using Microsoft.AspNetCore.Http;
+using Umbraco.Core;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Hosting;
+using Umbraco.Net;
+using Umbraco.Core.Runtime;
+
+namespace Umbraco.Web.BackOffice.AspNetCore
+{
+ ///
+ /// Adds/replaces AspNetCore specific services
+ ///
+ [ComposeBefore(typeof(ICoreComposer))]
+ [ComposeAfter(typeof(CoreInitialComposer))]
+ public class AspNetCoreComposer : IComposer
+ {
+ public void Compose(Composition composition)
+ {
+ // AspNetCore specific services
+ composition.RegisterUnique();
+
+ // Our own netcore implementations
+ composition.RegisterUnique();
+ composition.RegisterUnique();
+ }
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironment.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironment.cs
index 00bc894b0d..6f1298918d 100644
--- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironment.cs
+++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironment.cs
@@ -1,11 +1,8 @@
using System;
-using System.Collections.Concurrent;
-using System.Diagnostics;
+using System.Globalization;
using System.IO;
-using System.Threading;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Hosting;
using Umbraco.Core;
using Umbraco.Core.Configuration;
@@ -13,30 +10,29 @@ namespace Umbraco.Web.BackOffice.AspNetCore
{
public class AspNetCoreHostingEnvironment : Umbraco.Core.Hosting.IHostingEnvironment
{
- private readonly ConcurrentDictionary _registeredObjects =
- new ConcurrentDictionary();
+
private readonly IHostingSettings _hostingSettings;
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly IHttpContextAccessor _httpContextAccessor;
- private readonly IHostApplicationLifetime _hostApplicationLifetime;
+
private string _localTempPath;
- public AspNetCoreHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor, IHostApplicationLifetime hostHostApplicationLifetime)
+ public AspNetCoreHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor)
{
_hostingSettings = hostingSettings ?? throw new ArgumentNullException(nameof(hostingSettings));
_webHostEnvironment = webHostEnvironment;
_httpContextAccessor = httpContextAccessor;
- _hostApplicationLifetime = hostHostApplicationLifetime;
SiteName = webHostEnvironment.ApplicationName;
ApplicationId = AppDomain.CurrentDomain.Id.ToString();
ApplicationPhysicalPath = webHostEnvironment.ContentRootPath;
ApplicationVirtualPath = "/"; //TODO how to find this, This is a server thing, not application thing.
- IISVersion = new Version(0, 0); // TODO not necessary IIS
+ IISVersion = new Version(0, 0); // TODO not necessary IIS
IsDebugMode = _hostingSettings.DebugMode;
}
+
public bool IsHosted { get; } = true;
public string SiteName { get; }
public string ApplicationId { get; }
@@ -56,7 +52,10 @@ namespace Umbraco.Web.BackOffice.AspNetCore
switch (_hostingSettings.LocalTempStorageLocation)
{
case LocalTempStorage.AspNetTemp:
- return _localTempPath = System.IO.Path.Combine(Path.GetTempPath(),ApplicationId, "UmbracoData");
+
+ // TODO: I don't think this is correct? but also we probably can remove AspNetTemp as an option entirely
+ // since this is legacy and we shouldn't use it
+ return _localTempPath = System.IO.Path.Combine(Path.GetTempPath(), ApplicationId, "UmbracoData");
case LocalTempStorage.EnvironmentTemp:
@@ -84,8 +83,11 @@ namespace Umbraco.Web.BackOffice.AspNetCore
}
}
- // TODO: This may need to take into account ~/ paths which means the ApplicationVirtualPath and is this the content root or web root?
- public string MapPath(string path) => Path.Combine(_webHostEnvironment.WebRootPath, path);
+ public string MapPath(string path)
+ {
+ var newPath = path.TrimStart('~', '/').Replace('/', Path.DirectorySeparatorChar);
+ return Path.Combine(_webHostEnvironment.WebRootPath, newPath);
+ }
// TODO: Need to take into account 'root' here
public string ToAbsolute(string virtualPath, string root)
@@ -101,43 +103,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
return applicationPath.Add(segment).Value;
}
- public void RegisterObject(IRegisteredObject registeredObject)
- {
- var wrapped = new RegisteredObjectWrapper(registeredObject);
- if (!_registeredObjects.TryAdd(registeredObject, wrapped))
- {
- throw new InvalidOperationException("Could not register object");
- }
-
- var cancellationTokenRegistration = _hostApplicationLifetime.ApplicationStopping.Register(() => wrapped.Stop(true));
- wrapped.CancellationTokenRegistration = cancellationTokenRegistration;
- }
-
- public void UnregisterObject(IRegisteredObject registeredObject)
- {
- if (_registeredObjects.TryGetValue(registeredObject, out var wrapped))
- {
- wrapped.CancellationTokenRegistration.Unregister();
- }
- }
-
-
- private class RegisteredObjectWrapper
- {
- private readonly IRegisteredObject _inner;
-
- public RegisteredObjectWrapper(IRegisteredObject inner)
- {
- _inner = inner;
- }
-
- public CancellationTokenRegistration CancellationTokenRegistration { get; set; }
-
- public void Stop(bool immediate)
- {
- _inner.Stop(immediate);
- }
- }
+
}
diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreMarchal.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreMarchal.cs
index 98e040d338..247666090e 100644
--- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreMarchal.cs
+++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreMarchal.cs
@@ -2,7 +2,7 @@ using System;
using System.Runtime.InteropServices;
using Umbraco.Core.Diagnostics;
-namespace Umbraco.Web.BackOffice
+namespace Umbraco.Web.BackOffice.AspNetCore
{
public class AspNetCoreMarchal : IMarchal
diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs
index 20cfef352d..0dca3edec8 100644
--- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs
+++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs
@@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Umbraco.Net;
-namespace Umbraco.Web.AspNet
+namespace Umbraco.Web.BackOffice.AspNetCore
{
public class AspNetCoreUmbracoApplicationLifetime : IUmbracoApplicationLifetime
{
diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs
index 1f06a818d6..770f4b883f 100644
--- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs
+++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs
@@ -1,5 +1,10 @@
using System;
using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Umbraco.Core;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Hosting;
namespace Umbraco.Web.BackOffice.AspNetCore
{
@@ -7,12 +12,57 @@ 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;
}
+
+ ///
+ /// Start Umbraco
+ ///
+ ///
+ ///
+ public static IApplicationBuilder UseUmbracoCore(this IApplicationBuilder app)
+ {
+ if (app == null) throw new ArgumentNullException(nameof(app));
+
+ // Register a listener for application shutdown in order to terminate the runtime
+ var hostLifetime = app.ApplicationServices.GetRequiredService();
+ var runtime = app.ApplicationServices.GetRequiredService();
+ var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime);
+ hostLifetime.RegisterObject(runtimeShutdown);
+
+ // Start the runtime!
+ runtime.Start();
+
+ return app;
+ }
+
+ ///
+ /// Ensures the runtime is shutdown when the application is shutting down
+ ///
+ private class CoreRuntimeShutdown : IRegisteredObject
+ {
+ public CoreRuntimeShutdown(IRuntime runtime, IApplicationShutdownRegistry hostLifetime)
+ {
+ _runtime = runtime;
+ _hostLifetime = hostLifetime;
+ }
+
+ private bool _completed = false;
+ private readonly IRuntime _runtime;
+ private readonly IApplicationShutdownRegistry _hostLifetime;
+
+ public void Stop(bool immediate)
+ {
+ if (!_completed)
+ {
+ _completed = true;
+ _runtime.Terminate();
+ _hostLifetime.UnregisterObject(this);
+ }
+
+ }
+ }
}
}
diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs
similarity index 55%
rename from src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs
rename to src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs
index 52d9c16f87..2e45ed0ea2 100644
--- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs
+++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs
@@ -23,17 +23,18 @@ using Umbraco.Core.Runtime;
namespace Umbraco.Web.BackOffice.AspNetCore
{
-
-
- public static class UmbracoBackOfficeServiceCollectionExtensions
+ // TODO: Move to Umbraco.Web.Common
+ public static class UmbracoCoreServiceCollectionExtensions
{
-
- public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services)
+ ///
+ /// Adds the Umbraco Configuration requirements
+ ///
+ ///
+ ///
+ ///
+ public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services, IConfiguration configuration)
{
- var serviceProvider = services.BuildServiceProvider();
- var configuration = serviceProvider.GetService();
- if (configuration == null)
- throw new InvalidOperationException($"Could not resolve {typeof(IConfiguration)} from the container");
+ if (configuration == null) throw new ArgumentNullException(nameof(configuration));
var configsFactory = new AspNetCoreConfigsFactory(configuration);
@@ -46,48 +47,61 @@ 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)
+ public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment)
{
if (!UmbracoServiceProviderFactory.IsActive)
throw new InvalidOperationException("Ensure to add UseUmbraco() in your Program.cs after ConfigureWebHostDefaults to enable Umbraco's service provider factory");
var umbContainer = UmbracoServiceProviderFactory.UmbracoContainer;
- services.AddUmbracoCore(umbContainer, Assembly.GetEntryAssembly());
+ services.AddUmbracoCore(webHostEnvironment, umbContainer, Assembly.GetEntryAssembly());
return services;
}
- public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IRegister umbContainer, Assembly entryAssembly)
+ ///
+ /// Adds the Umbraco Back Core requirements
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, IRegister umbContainer, Assembly entryAssembly)
{
+ if (services is null) throw new ArgumentNullException(nameof(services));
+ if (umbContainer is null) throw new ArgumentNullException(nameof(umbContainer));
+ if (entryAssembly is null) throw new ArgumentNullException(nameof(entryAssembly));
+
+ // Special case! The generic host adds a few default services but we need to manually add this one here NOW because
+ // we resolve it before the host finishes configuring in the call to CreateCompositionRoot
services.AddSingleton();
- // TODO: Get rid of this 'Current' requirement
- var globalSettings = Current.Configs.Global();
+ CreateCompositionRoot(services, webHostEnvironment, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler);
+
+ var globalSettings = configs.Global();
var umbracoVersion = new UmbracoVersion(globalSettings);
// TODO: Currently we are not passing in any TypeFinderConfig (with ITypeFinderSettings) which we should do, however
// this is not critical right now and would require loading in some config before boot time so just leaving this as-is for now.
- var typeFinder = new TypeFinder(Current.Logger, new DefaultUmbracoAssemblyProvider(entryAssembly));
+ var typeFinder = new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(entryAssembly));
var coreRuntime = GetCoreRuntime(
- Current.Configs,
+ configs,
umbracoVersion,
- Current.IOHelper,
- Current.Logger,
- Current.Profiler,
- Current.HostingEnvironment,
- Current.BackOfficeInfo,
+ ioHelper,
+ logger,
+ profiler,
+ hostingEnvironment,
+ backOfficeInfo,
typeFinder);
- var factory = coreRuntime.Boot(umbContainer);
+ var factory = coreRuntime.Configure(umbContainer);
return services;
}
@@ -109,7 +123,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
? (IMainDomLock)new SqlMainDomLock(logger, globalSettings, connStrings, dbProviderFactoryCreator)
: new MainDomSemaphoreLock(logger, hostingEnvironment);
- var mainDom = new MainDom(logger, hostingEnvironment, mainDomLock);
+ var mainDom = new MainDom(logger, mainDomLock);
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetCoreBootPermissionsChecker(),
hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom, typeFinder);
@@ -117,29 +131,33 @@ namespace Umbraco.Web.BackOffice.AspNetCore
return coreRuntime;
}
- public static IServiceCollection CreateCompositionRoot(
- this IServiceCollection services,
- IHttpContextAccessor httpContextAccessor,
- IWebHostEnvironment webHostEnvironment,
- IHostApplicationLifetime hostApplicationLifetime,
- Configs configs)
+ private static IServiceCollection CreateCompositionRoot(IServiceCollection services, IWebHostEnvironment webHostEnvironment,
+ out ILogger logger, out Configs configs, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment,
+ out IBackOfficeInfo backOfficeInfo, out IProfiler profiler)
{
+ // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured
+ var serviceProvider = services.BuildServiceProvider();
+
+ var httpContextAccessor = serviceProvider.GetRequiredService();
+
+ configs = serviceProvider.GetService();
+ if (configs == null)
+ throw new InvalidOperationException($"Could not resolve type {typeof(Configs)} from the container, ensure {nameof(AddUmbracoConfiguration)} is called before calling {nameof(AddUmbracoCore)}");
+
var hostingSettings = configs.Hosting();
var coreDebug = configs.CoreDebug();
var globalSettings = configs.Global();
- var hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor, hostApplicationLifetime);
- var ioHelper = new IOHelper(hostingEnvironment, globalSettings);
- var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment,
+ hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor);
+ ioHelper = new IOHelper(hostingEnvironment, globalSettings);
+ logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment,
new AspNetCoreSessionIdResolver(httpContextAccessor),
- // need to build a new service provider since the one already resolved above doesn't have the IRequestCache yet
+ // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured
() => services.BuildServiceProvider().GetService(), coreDebug, ioHelper,
new AspNetCoreMarchal());
- var backOfficeInfo = new AspNetCoreBackOfficeInfo(globalSettings);
- var profiler = new LogProfiler(logger);
-
- Current.Initialize(logger, configs, ioHelper, hostingEnvironment, backOfficeInfo, profiler);
+ backOfficeInfo = new AspNetCoreBackOfficeInfo(globalSettings);
+ profiler = new LogProfiler(logger);
return services;
}
@@ -159,5 +177,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
// nothing to check
}
}
+
+
}
}
diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs
index 76d92a82d6..2ae1e58a9d 100644
--- a/src/Umbraco.Web.UI.NetCore/Startup.cs
+++ b/src/Umbraco.Web.UI.NetCore/Startup.cs
@@ -16,21 +16,30 @@ namespace Umbraco.Web.UI.BackOffice
{
public class Startup
{
- private readonly IConfiguration _configuration;
+ private readonly IWebHostEnvironment _webHostEnvironment;
+ private readonly IConfiguration _config;
- public Startup(IConfiguration configuration)
+ ///
+ /// Constructor
+ ///
+ ///
+ ///
+ ///
+ /// Only a few services are possible to be injected here https://github.com/dotnet/aspnetcore/issues/9337
+ ///
+ public Startup(IWebHostEnvironment webHostEnvironment, IConfiguration config)
{
- _configuration = configuration;
+ _webHostEnvironment = webHostEnvironment ?? throw new ArgumentNullException(nameof(webHostEnvironment));
+ _config = config ?? throw new ArgumentNullException(nameof(config));
}
-
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
- services.AddUmbracoConfiguration();
- services.AddUmbracoRuntimeMinifier(_configuration);
- services.AddUmbracoCore();
+ services.AddUmbracoConfiguration(_config);
+ services.AddUmbracoRuntimeMinifier(_config);
+ services.AddUmbracoCore(_webHostEnvironment);
services.AddUmbracoWebsite();
}
diff --git a/src/Umbraco.Web.Website/AspNetCore/UmbracoWebsiteServiceCollectionExtensions.cs b/src/Umbraco.Web.Website/AspNetCore/UmbracoWebsiteServiceCollectionExtensions.cs
index f7a198bc3b..6d2ce5e7e4 100644
--- a/src/Umbraco.Web.Website/AspNetCore/UmbracoWebsiteServiceCollectionExtensions.cs
+++ b/src/Umbraco.Web.Website/AspNetCore/UmbracoWebsiteServiceCollectionExtensions.cs
@@ -19,6 +19,7 @@ namespace Umbraco.Web.Website.AspNetCore
{
public static IServiceCollection AddUmbracoWebsite(this IServiceCollection services)
{
+ // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured
var serviceProvider = services.BuildServiceProvider();
var configs = serviceProvider.GetService();
var imagingSettings = configs.Imaging();
diff --git a/src/Umbraco.Web/AspNet/AspNetApplicationShutdownRegistry.cs b/src/Umbraco.Web/AspNet/AspNetApplicationShutdownRegistry.cs
new file mode 100644
index 0000000000..dbd6e9e834
--- /dev/null
+++ b/src/Umbraco.Web/AspNet/AspNetApplicationShutdownRegistry.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Concurrent;
+using System.Web.Hosting;
+using Umbraco.Core.Hosting;
+using IRegisteredObject = Umbraco.Core.IRegisteredObject;
+
+namespace Umbraco.Web.Hosting
+{
+ public class AspNetApplicationShutdownRegistry : IApplicationShutdownRegistry
+ {
+ private readonly ConcurrentDictionary _registeredObjects =
+ new ConcurrentDictionary();
+
+ public void RegisterObject(IRegisteredObject registeredObject)
+ {
+ var wrapped = new RegisteredObjectWrapper(registeredObject);
+ if (!_registeredObjects.TryAdd(registeredObject, wrapped))
+ {
+ throw new InvalidOperationException("Could not register object");
+ }
+ HostingEnvironment.RegisterObject(wrapped);
+ }
+
+ public void UnregisterObject(IRegisteredObject registeredObject)
+ {
+ if (_registeredObjects.TryGetValue(registeredObject, out var wrapped))
+ {
+ HostingEnvironment.UnregisterObject(wrapped);
+ }
+ }
+
+ private class RegisteredObjectWrapper : System.Web.Hosting.IRegisteredObject
+ {
+ private readonly IRegisteredObject _inner;
+
+ public RegisteredObjectWrapper(IRegisteredObject inner)
+ {
+ _inner = inner;
+ }
+
+ public void Stop(bool immediate)
+ {
+ _inner.Stop(immediate);
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs b/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs
index aa07894aa9..a61ad356d5 100644
--- a/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs
+++ b/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs
@@ -1,21 +1,15 @@
using System;
-using System.Collections;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
using System.Web;
using System.Web.Hosting;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
-using Umbraco.Core.IO;
-using IRegisteredObject = Umbraco.Core.IRegisteredObject;
namespace Umbraco.Web.Hosting
{
public class AspNetHostingEnvironment : IHostingEnvironment
{
- private readonly ConcurrentDictionary _registeredObjects =
- new ConcurrentDictionary();
+
private readonly IHostingSettings _hostingSettings;
private string _localTempPath;
@@ -46,23 +40,7 @@ namespace Umbraco.Web.Hosting
}
public string ToAbsolute(string virtualPath, string root) => VirtualPathUtility.ToAbsolute(virtualPath, root);
- public void RegisterObject(IRegisteredObject registeredObject)
- {
- var wrapped = new RegisteredObjectWrapper(registeredObject);
- if (!_registeredObjects.TryAdd(registeredObject, wrapped))
- {
- throw new InvalidOperationException("Could not register object");
- }
- HostingEnvironment.RegisterObject(wrapped);
- }
-
- public void UnregisterObject(IRegisteredObject registeredObject)
- {
- if (_registeredObjects.TryGetValue(registeredObject, out var wrapped))
- {
- HostingEnvironment.UnregisterObject(wrapped);
- }
- }
+
public string LocalTempPath
{
@@ -101,20 +79,7 @@ namespace Umbraco.Web.Hosting
}
}
}
- private class RegisteredObjectWrapper : System.Web.Hosting.IRegisteredObject
- {
- private readonly IRegisteredObject _inner;
-
- public RegisteredObjectWrapper(IRegisteredObject inner)
- {
- _inner = inner;
- }
-
- public void Stop(bool immediate)
- {
- _inner.Stop(immediate);
- }
- }
+
}
diff --git a/src/Umbraco.Web/AspNet/AspNetSessionManager.cs b/src/Umbraco.Web/AspNet/AspNetSessionManager.cs
index bf7b1c05c3..f81daadb0a 100644
--- a/src/Umbraco.Web/AspNet/AspNetSessionManager.cs
+++ b/src/Umbraco.Web/AspNet/AspNetSessionManager.cs
@@ -1,6 +1,6 @@
using System.Web;
-using Umbraco.Core.Session;
using Umbraco.Net;
+using Umbraco.Core.Session;
namespace Umbraco.Web.AspNet
{
diff --git a/src/Umbraco.Web/Compose/AuditEventsComponent.cs b/src/Umbraco.Web/Compose/AuditEventsComponent.cs
index fba6e754c8..bd2520aa90 100644
--- a/src/Umbraco.Web/Compose/AuditEventsComponent.cs
+++ b/src/Umbraco.Web/Compose/AuditEventsComponent.cs
@@ -7,10 +7,10 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
+using Umbraco.Net;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
-using Umbraco.Net;
using Umbraco.Web.Security;
namespace Umbraco.Core.Compose
diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs
index 0509cfbcc4..751d441a68 100644
--- a/src/Umbraco.Web/Composing/Current.cs
+++ b/src/Umbraco.Web/Composing/Current.cs
@@ -11,6 +11,7 @@ using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Core.Mapping;
+using Umbraco.Net;
using Umbraco.Core.PackageActions;
using Umbraco.Core.Packaging;
using Umbraco.Core.PropertyEditors;
@@ -19,7 +20,6 @@ using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Core.Sync;
-using Umbraco.Net;
using Umbraco.Web.Actions;
using Umbraco.Web.Cache;
using Umbraco.Web.Editors;
diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs
index add80d4a2e..9c4264cbb8 100644
--- a/src/Umbraco.Web/Editors/PackageInstallController.cs
+++ b/src/Umbraco.Web/Editors/PackageInstallController.cs
@@ -14,12 +14,14 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models.Editors;
using Umbraco.Core.Models.Packaging;
+using Umbraco.Net;
using Umbraco.Core.Packaging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Runtime;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Net;
+using Umbraco.Web.JavaScript;
using Umbraco.Web.Models;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Mvc;
diff --git a/src/Umbraco.Web/Profiling/WebProfilingController.cs b/src/Umbraco.Web/Profiling/WebProfilingController.cs
index b37a7eefb8..d8f71b5c85 100644
--- a/src/Umbraco.Web/Profiling/WebProfilingController.cs
+++ b/src/Umbraco.Web/Profiling/WebProfilingController.cs
@@ -1,6 +1,7 @@
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
+using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Core.Mapping;
using Umbraco.Core.Persistence;
@@ -18,7 +19,7 @@ namespace Umbraco.Web.Profiling
[UmbracoApplicationAuthorize(Core.Constants.Applications.Settings)]
public class WebProfilingController : UmbracoAuthorizedJsonController
{
- private readonly IRuntimeState _runtimeState;
+ private readonly IHostingEnvironment _hosting;
public WebProfilingController(
IGlobalSettings globalSettings,
@@ -30,17 +31,18 @@ namespace Umbraco.Web.Profiling
IRuntimeState runtimeState,
IShortStringHelper shortStringHelper,
UmbracoMapper umbracoMapper,
- IPublishedUrlProvider publishedUrlProvider)
+ IPublishedUrlProvider publishedUrlProvider,
+ IHostingEnvironment hosting)
: base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, shortStringHelper, umbracoMapper, publishedUrlProvider)
{
- _runtimeState = runtimeState;
+ _hosting = hosting;
}
public object GetStatus()
{
return new
{
- Enabled = _runtimeState.Debug
+ Enabled = _hosting.IsDebugMode
};
}
}}
diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
index b81cafdb40..2a746ffe4c 100644
--- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs
+++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs
@@ -18,7 +18,6 @@ using Umbraco.Core.Runtime;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
-using Umbraco.Net;
using Umbraco.Web.Actions;
using Umbraco.Web.Cache;
using Umbraco.Web.Composing.CompositionExtensions;
@@ -46,6 +45,7 @@ using Umbraco.Web.WebApi;
using Umbraco.Web.PropertyEditors;
using Umbraco.Examine;
using Umbraco.Core.Models;
+using Umbraco.Net;
using Umbraco.Core.Request;
using Umbraco.Core.Session;
using Umbraco.Web.AspNet;
@@ -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/Security/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/AppBuilderExtensions.cs
index 8fab9f4ea8..b3f950433c 100644
--- a/src/Umbraco.Web/Security/AppBuilderExtensions.cs
+++ b/src/Umbraco.Web/Security/AppBuilderExtensions.cs
@@ -17,9 +17,9 @@ using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models.Identity;
+using Umbraco.Net;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
-using Umbraco.Net;
using Umbraco.Web.Composing;
using Umbraco.Web.Models.Identity;
using Constants = Umbraco.Core.Constants;
diff --git a/src/Umbraco.Web/Security/BackOfficeUserManager.cs b/src/Umbraco.Web/Security/BackOfficeUserManager.cs
index 354b9c2dde..7de7ba37e5 100644
--- a/src/Umbraco.Web/Security/BackOfficeUserManager.cs
+++ b/src/Umbraco.Web/Security/BackOfficeUserManager.cs
@@ -9,9 +9,9 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models.Identity;
+using Umbraco.Net;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
-using Umbraco.Net;
using Umbraco.Web.Models.Identity;
using IPasswordHasher = Microsoft.AspNet.Identity.IPasswordHasher;
diff --git a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs
index d2eeebaeaf..b099110911 100644
--- a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs
+++ b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs
@@ -10,10 +10,10 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Membership;
+using Umbraco.Net;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
-using Umbraco.Net;
using Umbraco.Web.Composing;
namespace Umbraco.Web.Security.Providers
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index bb11625b21..efc13d9dd7 100755
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -138,6 +138,7 @@
+
@@ -594,4 +595,4 @@
-
+
\ No newline at end of file
diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs
index 9f24da95e3..30d3fe5041 100644
--- a/src/Umbraco.Web/UmbracoApplication.cs
+++ b/src/Umbraco.Web/UmbracoApplication.cs
@@ -32,7 +32,7 @@ namespace Umbraco.Web
? (IMainDomLock)new SqlMainDomLock(logger, globalSettings, connectionStrings, dbProviderFactoryCreator)
: new MainDomSemaphoreLock(logger, hostingEnvironment);
- var mainDom = new MainDom(logger, hostingEnvironment, mainDomLock);
+ var mainDom = new MainDom(logger, mainDomLock);
var requestCache = new HttpRequestAppCache(() => HttpContext.Current?.Items);
var umbracoBootPermissionChecker = new AspNetUmbracoBootPermissionChecker();
diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs
index ce5f1304cd..0963ad3c07 100644
--- a/src/Umbraco.Web/UmbracoApplicationBase.cs
+++ b/src/Umbraco.Web/UmbracoApplicationBase.cs
@@ -152,7 +152,9 @@ namespace Umbraco.Web
Umbraco.Composing.Current.Profiler,
Umbraco.Composing.Current.HostingEnvironment,
Umbraco.Composing.Current.BackOfficeInfo);
- _factory = Current.Factory = _runtime.Boot(register);
+ _factory = Current.Factory = _runtime.Configure(register);
+
+ _runtime.Start();
}
// called by ASP.NET (auto event wireup) once per app domain
diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs
index 6f5fc26f90..9cc651f359 100644
--- a/src/Umbraco.Web/UmbracoContext.cs
+++ b/src/Umbraco.Web/UmbracoContext.cs
@@ -150,7 +150,7 @@ namespace Umbraco.Web
{
var request = GetRequestFromContext();
//NOTE: the request can be null during app startup!
- return Current.RuntimeState.Debug
+ return Current.HostingEnvironment.IsDebugMode
&& request != null
&& (string.IsNullOrEmpty(request["umbdebugshowtrace"]) == false
|| string.IsNullOrEmpty(request["umbdebug"]) == false
diff --git a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs
index a69e6c6f8d..a0b7cdd225 100644
--- a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs
+++ b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs
@@ -7,8 +7,8 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Mapping;
-using Umbraco.Core.Services;
using Umbraco.Net;
+using Umbraco.Core.Services;
using Umbraco.Web;
using Umbraco.Web.Composing;
using Umbraco.Web.Security;
diff --git a/src/Umbraco.Web/UrlHelperExtensions.cs b/src/Umbraco.Web/UrlHelperExtensions.cs
index 32f47ccd12..79731ebc54 100644
--- a/src/Umbraco.Web/UrlHelperExtensions.cs
+++ b/src/Umbraco.Web/UrlHelperExtensions.cs
@@ -140,12 +140,12 @@ namespace Umbraco.Web
//in case the user bypasses the installer and just bumps the web.config or client dependency config
//if in debug mode, always burst the cache
- if (Current.RuntimeState.Debug)
+ if (Current.HostingEnvironment.IsDebugMode)
{
return DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture).GenerateHash();
}
-
- var version = Current.RuntimeState.SemanticVersion.ToSemanticString();
+
+ var version = Current.UmbracoVersion.SemanticVersion.ToSemanticString();
return $"{version}.{Current.RuntimeMinifier.GetHashValue}".GenerateHash();
}
}
diff --git a/src/umbraco.sln b/src/umbraco.sln
index ca5d4d5188..09423ec00e 100644
--- a/src/umbraco.sln
+++ b/src/umbraco.sln
@@ -125,6 +125,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Tests.Integration",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Tests.Common", "Umbraco.Tests.Common\Umbraco.Tests.Common.csproj", "{A499779C-1B3B-48A8-B551-458E582E6E96}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Tests.UnitTests", "Umbraco.Tests.UnitTests\Umbraco.Tests.UnitTests.csproj", "{9102ABDF-E537-4E46-B525-C9ED4833EED0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -165,6 +167,10 @@ Global
{FBE7C065-DAC0-4025-A78B-63B24D3AB00B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FBE7C065-DAC0-4025-A78B-63B24D3AB00B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FBE7C065-DAC0-4025-A78B-63B24D3AB00B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9102ABDF-E537-4E46-B525-C9ED4833EED0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9102ABDF-E537-4E46-B525-C9ED4833EED0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9102ABDF-E537-4E46-B525-C9ED4833EED0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9102ABDF-E537-4E46-B525-C9ED4833EED0}.Release|Any CPU.Build.0 = Release|Any CPU
{33085570-9BF2-4065-A9B0-A29D920D13BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{33085570-9BF2-4065-A9B0-A29D920D13BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{33085570-9BF2-4065-A9B0-A29D920D13BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -213,6 +219,7 @@ Global
{53594E5B-64A2-4545-8367-E3627D266AE8} = {FD962632-184C-4005-A5F3-E705D92FC645}
{3A33ADC9-C6C0-4DB1-A613-A9AF0210DF3D} = {B5BD12C1-A454-435E-8A46-FF4A364C0382}
{C7311C00-2184-409B-B506-52A5FAEA8736} = {FD962632-184C-4005-A5F3-E705D92FC645}
+ {9102ABDF-E537-4E46-B525-C9ED4833EED0} = {B5BD12C1-A454-435E-8A46-FF4A364C0382}
{FB5676ED-7A69-492C-B802-E7B24144C0FC} = {B5BD12C1-A454-435E-8A46-FF4A364C0382}
{D6319409-777A-4BD0-93ED-B2DFD805B32C} = {B5BD12C1-A454-435E-8A46-FF4A364C0382}
{A499779C-1B3B-48A8-B551-458E582E6E96} = {B5BD12C1-A454-435E-8A46-FF4A364C0382}