From 919d418920e0aabfbafe23a1baa70279dcb8198f Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 24 Mar 2020 11:53:56 +1100 Subject: [PATCH 01/16] Gets the DB installing in integration tests, changes integratino tests to use Generic Host builder --- src/Umbraco.Core/Composing/Composition.cs | 14 +- .../Composing/HostBuilderExtensions.cs | 7 +- .../Migrations/Install/DatabaseBuilder.cs | 2 +- .../Runtime/CoreInitialComposer.cs | 2 + .../Runtime/CoreRuntime.cs | 5 + .../Implementations/DelegateHostedService.cs | 38 +++++ .../Implementations/HostBuilderExtensions.cs | 55 +++++++ .../TestDbProviderFactoryCreator.cs | 34 ----- .../Implementations/TestHelper.cs | 3 +- .../Implementations/TestLifetime.cs | 18 +++ src/Umbraco.Tests.Integration/RuntimeTests.cs | 138 ++++++++++++++---- .../Testing/TestLocalDb.cs | 49 +++++++ .../Umbraco.Tests.Integration.csproj | 1 + ...coBackOfficeServiceCollectionExtensions.cs | 44 +++--- 14 files changed, 319 insertions(+), 91 deletions(-) create mode 100644 src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs create mode 100644 src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs delete mode 100644 src/Umbraco.Tests.Integration/Implementations/TestDbProviderFactoryCreator.cs create mode 100644 src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs create mode 100644 src/Umbraco.Tests.Integration/Testing/TestLocalDb.cs 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.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/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..67cfcded92 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs @@ -176,6 +176,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..4a9441e535 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -115,6 +115,8 @@ namespace Umbraco.Core.Runtime /// public virtual IFactory Boot(IRegister register) { + if (register is null) throw new ArgumentNullException(nameof(register)); + // create and register the essential services // ie the bare minimum required to boot @@ -152,6 +154,9 @@ namespace Umbraco.Core.Runtime /// protected virtual IFactory Boot(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; try diff --git a/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs b/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs new file mode 100644 index 0000000000..9df7270350 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.Hosting; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Umbraco.Tests.Integration +{ + /// + /// Executes arbitrary code on start/end + /// + public class DelegateHostedService : IHostedService + { + private readonly Action _start; + private readonly Action _end; + + public static DelegateHostedService Create(Action start, Action end) => new DelegateHostedService(start, end); + + private DelegateHostedService(Action start, Action end) + { + _start = start; + _end = end; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + _start(); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + _end?.Invoke(); + return Task.CompletedTask; + } + } + + +} diff --git a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs new file mode 100644 index 0000000000..2d86122770 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs @@ -0,0 +1,55 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Data.SqlClient; +using System.IO; +using Umbraco.Core.Persistence; +using Umbraco.Tests.Integration.Testing; + +namespace Umbraco.Tests.Integration +{ + public static class HostBuilderExtensions + { + + + /// + /// Ensures the lifetime of the host ends as soon as code executes + /// + /// + /// + public static IHostBuilder UseTestLifetime(this IHostBuilder hostBuilder) + { + hostBuilder.ConfigureServices((context, collection) => collection.AddSingleton()); + return hostBuilder; + } + + public static IHostBuilder UseLocalDb(this IHostBuilder hostBuilder, string dbFilePath) + { + // Need to register SqlClient manually + // TODO: Move this to someplace central + DbProviderFactories.RegisterFactory("System.Data.SqlClient", SqlClientFactory.Instance); + + hostBuilder.ConfigureAppConfiguration(x => + { + if (!Directory.Exists(dbFilePath)) + Directory.CreateDirectory(dbFilePath); + + var dbName = Guid.NewGuid().ToString("N"); + var instance = TestLocalDb.EnsureLocalDbInstanceAndDatabase(dbName, dbFilePath); + + x.AddInMemoryCollection(new[] + { + new KeyValuePair("ConnectionStrings:umbracoDbDSN", instance.GetConnectionString(dbName)) + }); + }); + return hostBuilder; + } + + + } + + +} diff --git a/src/Umbraco.Tests.Integration/Implementations/TestDbProviderFactoryCreator.cs b/src/Umbraco.Tests.Integration/Implementations/TestDbProviderFactoryCreator.cs deleted file mode 100644 index 9081c4ccb4..0000000000 --- a/src/Umbraco.Tests.Integration/Implementations/TestDbProviderFactoryCreator.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Data.Common; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.SqlSyntax; - -namespace Umbraco.Tests.Integration.Implementations -{ - public class TestDbProviderFactoryCreator : IDbProviderFactoryCreator - { - public IBulkSqlInsertProvider CreateBulkSqlInsertProvider(string providerName) - { - throw new System.NotImplementedException(); - } - - public void CreateDatabase() - { - throw new System.NotImplementedException(); - } - - public DbProviderFactory CreateFactory() - { - throw new System.NotImplementedException(); - } - - public DbProviderFactory CreateFactory(string providerName) - { - throw new System.NotImplementedException(); - } - - public ISqlSyntaxProvider GetSqlSyntaxProvider(string providerName) - { - throw new System.NotImplementedException(); - } - } -} diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index 5254892b23..4c37903b0c 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; using Moq; +using System.Data.Common; using System.Net; using Umbraco.Core; using Umbraco.Core.Cache; @@ -60,7 +61,7 @@ namespace Umbraco.Tests.Integration.Implementations public IWebHostEnvironment GetWebHostEnvironment() => _hostEnvironment; - public override IDbProviderFactoryCreator DbProviderFactoryCreator => new TestDbProviderFactoryCreator(); + public override IDbProviderFactoryCreator DbProviderFactoryCreator => new SqlServerDbProviderFactoryCreator("System.Data.SqlClient", DbProviderFactories.GetFactory); public override IBulkSqlInsertProvider BulkSqlInsertProvider => new SqlServerBulkSqlInsertProvider(); diff --git a/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs b/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs new file mode 100644 index 0000000000..063644490b --- /dev/null +++ b/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.Hosting; +using System.Threading; +using System.Threading.Tasks; + +namespace Umbraco.Tests.Integration +{ + /// + /// Ensures the host lifetime ends as soon as code execution is done + /// + public class TestLifetime : IHostLifetime + { + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + + public Task WaitForStartAsync(CancellationToken cancellationToken) => Task.CompletedTask; + } + + +} diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index 4b5cb30544..198fd4831c 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -7,19 +7,36 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Moq; using NUnit.Framework; +using System.Collections.Generic; +using System.IO; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Logging; +using Umbraco.Core.Migrations.Install; +using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; using Umbraco.Tests.Common; using Umbraco.Tests.Integration.Implementations; +using Umbraco.Tests.Integration.Testing; using Umbraco.Web.BackOffice.AspNetCore; +using static Umbraco.Core.Migrations.Install.DatabaseBuilder; namespace Umbraco.Tests.Integration { + [TestFixture] public class RuntimeTests { + [OneTimeTearDown] + public void FixtureTearDown() + { + TestLocalDb.Cleanup(); + } + + /// + /// Manually configure the containers/dependencies and call Boot on Core runtime + /// [Test] public void BootCoreRuntime() { @@ -52,40 +69,107 @@ namespace Umbraco.Tests.Integration Assert.IsTrue(MyComponent.IsTerminated); } + /// + /// Calling AddUmbracoCore to configure the container and boot the core runtime within a generic host + /// [Test] public void AddUmbracoCore() { + var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); + + var host = Host.CreateDefaultBuilder() + .UseTestLifetime() + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + var testHelper = new TestHelper(); + + AddRequiredNetCoreServices(services, testHelper); + + // Add it! + services.AddUmbracoConfiguration(); + services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + + // Run tests + services.AddHostedService(x => DelegateHostedService.Create(() => + { + // assert results + var runtimeState = umbracoContainer.GetInstance(); + var mainDom = umbracoContainer.GetInstance(); + + Assert.IsTrue(mainDom.IsMainDom); + Assert.IsNull(runtimeState.BootFailedException); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + Assert.IsTrue(MyComposer.IsComposed); + + }, null)); + }) + .Build(); + + // NOTE: host.Run() could be used but that requires more work by manually calling IHostApplicationLifetime.StopApplication(). In these cases we don't need to wind down. + host.Start(); + } + + + [Test] + public void UseUmbracoCore() + { + var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); var testHelper = new TestHelper(); - // MSDI - var services = new ServiceCollection(); - // These services are required + var host = Host.CreateDefaultBuilder() + //TODO: Need to have a configured umb version for the runtime state + .UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb")) + .UseTestLifetime() + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + AddRequiredNetCoreServices(services, testHelper); + + // Add it! + services.AddUmbracoConfiguration(); + services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + + // Run tests + services.AddHostedService(x => DelegateHostedService.Create(() => + { + var runtimeState = (RuntimeState)umbracoContainer.GetInstance(); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + + var dbBuilder = umbracoContainer.GetInstance(); + Assert.IsNotNull(dbBuilder); + + var canConnect = dbBuilder.CanConnectToDatabase; + Assert.IsTrue(canConnect); + + var dbResult = dbBuilder.CreateSchemaAndData(); + Assert.IsTrue(dbResult.Success); + + var dbFactory = umbracoContainer.GetInstance(); + var profilingLogger = umbracoContainer.GetInstance(); + runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger); + Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); + + }, null)); + }) + .Build(); + + // NOTE: host.Run() could be used but that requires more work by manually calling IHostApplicationLifetime.StopApplication(). In these cases we don't need to wind down. + host.Start(); + } + + private LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory) + { + var container = new ServiceContainer(ContainerOptions.Default.Clone().WithMicrosoftSettings().WithAspNetCoreSettings()); + serviceProviderFactory = new UmbracoServiceProviderFactory(container); + var umbracoContainer = serviceProviderFactory.GetContainer(); + return umbracoContainer; + } + + private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper) + { services.AddSingleton(x => testHelper.GetHttpContextAccessor()); services.AddSingleton(x => testHelper.GetWebHostEnvironment()); - services.AddSingleton(x => Mock.Of()); - - // LightInject / Umbraco - var container = new ServiceContainer(ContainerOptions.Default.Clone().WithMicrosoftSettings().WithAspNetCoreSettings()); - var serviceProviderFactory = new UmbracoServiceProviderFactory(container); - var umbracoContainer = serviceProviderFactory.GetContainer(); - - // Some IConfiguration must exist in the container first - var configurationBuilder = new ConfigurationBuilder(); - configurationBuilder.AddEnvironmentVariables(); - services.AddSingleton(x => configurationBuilder.Build()); - - // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); - - // assert results - var runtimeState = umbracoContainer.GetInstance(); - var mainDom = umbracoContainer.GetInstance(); - - Assert.IsTrue(mainDom.IsMainDom); - Assert.IsNull(runtimeState.BootFailedException); - Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); - Assert.IsTrue(MyComposer.IsComposed); } [RuntimeLevel(MinLevel = RuntimeLevel.Install)] diff --git a/src/Umbraco.Tests.Integration/Testing/TestLocalDb.cs b/src/Umbraco.Tests.Integration/Testing/TestLocalDb.cs new file mode 100644 index 0000000000..8ee326783b --- /dev/null +++ b/src/Umbraco.Tests.Integration/Testing/TestLocalDb.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Umbraco.Core.Persistence; + +namespace Umbraco.Tests.Integration.Testing +{ + public static class TestLocalDb + { + private const string LocalDbInstanceName = "UmbTests"; + + private static LocalDb LocalDb { get; } = new LocalDb(); + + // TODO: We need to borrow logic from this old branch, this is the latest commit at the old branch where we had LocalDb + // working for tests. There's a lot of hoops to jump through to make it work 'fast'. Turns out it didn't actually run as + // fast as SqlCe due to the dropping/creating of DB instances since that is faster in SqlCe but this code was all heavily + // optimized to go as fast as possible. + // see https://github.com/umbraco/Umbraco-CMS/blob/3a8716ac7b1c48b51258724337086cd0712625a1/src/Umbraco.Tests/TestHelpers/LocalDbTestDatabase.cs + internal static LocalDb.Instance EnsureLocalDbInstanceAndDatabase(string dbName, string dbFilePath) + { + if (!LocalDb.InstanceExists(LocalDbInstanceName) && !LocalDb.CreateInstance(LocalDbInstanceName)) + { + throw new InvalidOperationException( + $"Failed to create LocalDb instance {LocalDbInstanceName}, assuming LocalDb is not really available."); + } + + var instance = LocalDb.GetInstance(LocalDbInstanceName); + + if (instance == null) + { + throw new InvalidOperationException( + $"Failed to get LocalDb instance {LocalDbInstanceName}, assuming LocalDb is not really available."); + } + + instance.CreateDatabase(dbName, dbFilePath); + + return instance; + } + + public static void Cleanup() + { + var instance = LocalDb.GetInstance(LocalDbInstanceName); + if (instance != null) + { + instance.DropDatabases(); + } + } + } +} diff --git a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj index 55b3e8cdca..320db33568 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj +++ b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj @@ -15,6 +15,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs index 697e8b7dc4..d668b8c1bc 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; @@ -63,26 +64,30 @@ namespace Umbraco.Web.BackOffice.AspNetCore public static IServiceCollection AddUmbracoCore(this IServiceCollection services, 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)); + services.AddSingleton(); - CreateCompositionRoot(services); + CreateCompositionRoot(services, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler); // TODO: Get rid of this 'Current' requirement - var globalSettings = Current.Configs.Global(); + 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); @@ -115,7 +120,9 @@ namespace Umbraco.Web.BackOffice.AspNetCore return coreRuntime; } - private static void CreateCompositionRoot(IServiceCollection services) + private static void CreateCompositionRoot(IServiceCollection services, + out ILogger logger, out Configs configs, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment, + out IBackOfficeInfo backOfficeInfo, out IProfiler profiler) { // TODO: This isn't the best to have to resolve the services now but to avoid this will // require quite a lot of re-work. @@ -123,9 +130,12 @@ namespace Umbraco.Web.BackOffice.AspNetCore var httpContextAccessor = serviceProvider.GetRequiredService(); var webHostEnvironment = serviceProvider.GetRequiredService(); + // TODO: I'm unsure about this, by doing this it means we are resolving a "Different" instance to the one + // that controls the whole app because the instances comes from a different service provider. This + // could cause some issues with shutdowns, etc... we need to investigate. var hostApplicationLifetime = serviceProvider.GetRequiredService(); - var configs = serviceProvider.GetService(); + 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)}"); @@ -133,17 +143,15 @@ namespace Umbraco.Web.BackOffice.AspNetCore 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, hostApplicationLifetime); + ioHelper = new IOHelper(hostingEnvironment, globalSettings); + logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, new AspNetCoreSessionIdResolver(httpContextAccessor), () => serviceProvider.GetService(), coreDebug, ioHelper, new AspNetCoreMarchal()); - var backOfficeInfo = new AspNetCoreBackOfficeInfo(configs.Global()); - var profiler = new LogProfiler(logger); - - Current.Initialize(logger, configs, ioHelper, hostingEnvironment, backOfficeInfo, profiler); + backOfficeInfo = new AspNetCoreBackOfficeInfo(configs.Global()); + profiler = new LogProfiler(logger); } private class AspNetCoreBootPermissionsChecker : IUmbracoBootPermissionChecker From d0a204b984134e826dd78f68d6413cda9230dca6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 24 Mar 2020 14:48:32 +1100 Subject: [PATCH 02/16] Cleans up some unused code, fixes a merge issue causing duplicate runtimes to be created, register essential does what it's supposed to do, don't mix things with the webruntime. --- src/Umbraco.Core/Services/IRuntimeState.cs | 6 - .../CompositionExtensions_Essentials.cs | 12 +- .../Runtime/CoreRuntime.cs | 17 +-- src/Umbraco.Infrastructure/RuntimeState.cs | 5 - .../ContainerTests.cs | 5 +- .../Implementations/DelegateHostedService.cs | 38 ------ src/Umbraco.Tests.Integration/RuntimeTests.cs | 118 +++++++++++------- src/Umbraco.Tests/Runtimes/StandaloneTests.cs | 4 +- ...oBackOfficeApplicationBuilderExtensions.cs | 8 +- ...UmbracoCoreServiceCollectionExtensions.cs} | 53 ++++++-- src/Umbraco.Web/Runtime/WebInitialComposer.cs | 2 - src/Umbraco.Web/Umbraco.Web.csproj | 2 +- 12 files changed, 140 insertions(+), 130 deletions(-) delete mode 100644 src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs rename src/Umbraco.Web.BackOffice/AspNetCore/{UmbracoBackOfficeServiceCollectionExtensions.cs => UmbracoCoreServiceCollectionExtensions.cs} (82%) diff --git a/src/Umbraco.Core/Services/IRuntimeState.cs b/src/Umbraco.Core/Services/IRuntimeState.cs index 38da246cc1..565b2563e6 100644 --- a/src/Umbraco.Core/Services/IRuntimeState.cs +++ b/src/Umbraco.Core/Services/IRuntimeState.cs @@ -46,12 +46,6 @@ namespace Umbraco.Core /// This is eg "http://www.example.com". Uri ApplicationUrl { get; } - /// - /// Gets the Umbraco application virtual path. - /// - /// This is either "/" or eg "/virtual". - string ApplicationVirtualPath { get; } - /// /// Gets the runtime level of execution. /// diff --git a/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs b/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs index eb74d37590..02e5a6f5ee 100644 --- a/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs +++ b/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs @@ -1,6 +1,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -15,6 +16,9 @@ namespace Umbraco.Core /// /// Registers essential services. /// + /// + /// These services are all either created by the runtime or used to construct the runtime + /// public static void RegisterEssentials(this Composition composition, ILogger logger, IProfiler profiler, IProfilingLogger profilingLogger, IMainDom mainDom, @@ -25,8 +29,10 @@ namespace Umbraco.Core ITypeFinder typeFinder, IIOHelper ioHelper, IUmbracoVersion umbracoVersion, - IDbProviderFactoryCreator dbProviderFactoryCreator) - { + IDbProviderFactoryCreator dbProviderFactoryCreator, + IHostingEnvironment hostingEnvironment, + IBackOfficeInfo backOfficeInfo) + { composition.RegisterUnique(logger); composition.RegisterUnique(profiler); composition.RegisterUnique(profilingLogger); @@ -42,6 +48,8 @@ namespace Umbraco.Core composition.RegisterUnique(umbracoVersion); composition.RegisterUnique(dbProviderFactoryCreator); composition.RegisterUnique(factory => factory.GetInstance().BulkSqlInsertProvider); + composition.RegisterUnique(hostingEnvironment); + composition.RegisterUnique(backOfficeInfo); } } } diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index 4a9441e535..5cd51a174a 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -69,7 +69,7 @@ namespace Umbraco.Core.Runtime Configs.Global(), new Lazy(() => mainDom), new Lazy(() => _factory.GetInstance()), - UmbracoVersion,HostingEnvironment, BackOfficeInfo) + UmbracoVersion, HostingEnvironment, BackOfficeInfo) { Level = RuntimeLevel.Boot }; @@ -82,7 +82,6 @@ namespace Umbraco.Core.Runtime protected IBackOfficeInfo BackOfficeInfo { get; } public IDbProviderFactoryCreator DbProviderFactoryCreator { get; } - //public IBulkSqlInsertProvider BulkSqlInsertProvider { get; } /// /// Gets the profiler. @@ -176,21 +175,9 @@ namespace Umbraco.Core.Runtime // type finder/loader var typeLoader = new TypeLoader(IOHelper, TypeFinder, appCaches.RuntimeCache, new DirectoryInfo(HostingEnvironment.LocalTempPath), ProfilingLogger); - // runtime state - // beware! must use '() => _factory.GetInstance()' and NOT '_factory.GetInstance' - // as the second one captures the current value (null) and therefore fails - _state = new RuntimeState(Logger, - Configs.Global(), - new Lazy(() => _factory.GetInstance()), - new Lazy(() => _factory.GetInstance()), - UmbracoVersion, HostingEnvironment, BackOfficeInfo) - { - Level = RuntimeLevel.Boot - }; - // create the composition composition = new Composition(register, typeLoader, ProfilingLogger, _state, Configs, IOHelper, appCaches); - composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, MainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion, DbProviderFactoryCreator); + composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, MainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion, DbProviderFactoryCreator, HostingEnvironment, BackOfficeInfo); // run handlers RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory); diff --git a/src/Umbraco.Infrastructure/RuntimeState.cs b/src/Umbraco.Infrastructure/RuntimeState.cs index eadb9fed21..420fba7ffc 100644 --- a/src/Umbraco.Infrastructure/RuntimeState.cs +++ b/src/Umbraco.Infrastructure/RuntimeState.cs @@ -43,8 +43,6 @@ namespace Umbraco.Core _umbracoVersion = umbracoVersion; _hostingEnvironment = hostingEnvironment; _backOfficeInfo = backOfficeInfo; - - ApplicationVirtualPath = _hostingEnvironment.ApplicationVirtualPath; } /// @@ -84,9 +82,6 @@ namespace Umbraco.Core /// public Uri ApplicationUrl { get; private set; } - /// - public string ApplicationVirtualPath { get; } - /// public string CurrentMigrationState { get; internal set; } diff --git a/src/Umbraco.Tests.Integration/ContainerTests.cs b/src/Umbraco.Tests.Integration/ContainerTests.cs index d190d1165d..f440944ab7 100644 --- a/src/Umbraco.Tests.Integration/ContainerTests.cs +++ b/src/Umbraco.Tests.Integration/ContainerTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Integration var testHelper = new TestHelper(); var runtimeState = Mock.Of(); var umbracoDatabaseFactory = Mock.Of(); - var dbProviderFactoryCreator = Mock.Of(); + var dbProviderFactoryCreator = Mock.Of(); var typeLoader = testHelper.GetMockedTypeLoader(); // Register in the container @@ -45,7 +45,8 @@ namespace Umbraco.Tests.Integration testHelper.Logger, runtimeState, testHelper.GetConfigs(), testHelper.IOHelper, testHelper.AppCaches); composition.RegisterEssentials(testHelper.Logger, testHelper.Profiler, testHelper.Logger, testHelper.MainDom, testHelper.AppCaches, umbracoDatabaseFactory, typeLoader, runtimeState, testHelper.GetTypeFinder(), - testHelper.IOHelper, testHelper.GetUmbracoVersion(), dbProviderFactoryCreator); + testHelper.IOHelper, testHelper.GetUmbracoVersion(), dbProviderFactoryCreator, + testHelper.GetHostingEnvironment(), testHelper.GetBackOfficeInfo()); // Cross wire - this would be called by the Host Builder at the very end of ConfigureServices var lightInjectServiceProvider = serviceProviderFactory.CreateServiceProvider(umbracoContainer.Container); diff --git a/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs b/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs deleted file mode 100644 index 9df7270350..0000000000 --- a/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Microsoft.Extensions.Hosting; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace Umbraco.Tests.Integration -{ - /// - /// Executes arbitrary code on start/end - /// - public class DelegateHostedService : IHostedService - { - private readonly Action _start; - private readonly Action _end; - - public static DelegateHostedService Create(Action start, Action end) => new DelegateHostedService(start, end); - - private DelegateHostedService(Action start, Action end) - { - _start = start; - _end = end; - } - - public Task StartAsync(CancellationToken cancellationToken) - { - _start(); - return Task.CompletedTask; - } - - public Task StopAsync(CancellationToken cancellationToken) - { - _end?.Invoke(); - return Task.CompletedTask; - } - } - - -} diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index fb7f6b427e..dae4d0cbb8 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -9,6 +9,7 @@ using Moq; using NUnit.Framework; using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Composing.LightInject; @@ -28,6 +29,13 @@ namespace Umbraco.Tests.Integration [TestFixture] public class RuntimeTests { + [TearDown] + public void TearDown() + { + MyComponent.Reset(); + MyComposer.Reset(); + } + [OneTimeTearDown] public void FixtureTearDown() { @@ -73,12 +81,11 @@ namespace Umbraco.Tests.Integration /// Calling AddUmbracoCore to configure the container and boot the core runtime within a generic host /// [Test] - public void AddUmbracoCore() + public async Task AddUmbracoCore() { var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); - var host = Host.CreateDefaultBuilder() - .UseTestLifetime() + var hostBuilder = new HostBuilder() .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { @@ -89,38 +96,61 @@ namespace Umbraco.Tests.Integration // Add it! services.AddUmbracoConfiguration(); services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + }); - // Run tests - services.AddHostedService(x => DelegateHostedService.Create(() => - { - // assert results - var runtimeState = umbracoContainer.GetInstance(); - var mainDom = umbracoContainer.GetInstance(); + var host = await hostBuilder.StartAsync(); - Assert.IsTrue(mainDom.IsMainDom); - Assert.IsNull(runtimeState.BootFailedException); - Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); - Assert.IsTrue(MyComposer.IsComposed); + // assert results + var runtimeState = umbracoContainer.GetInstance(); + var mainDom = umbracoContainer.GetInstance(); - }, null)); - }) - .Build(); + Assert.IsTrue(mainDom.IsMainDom); + Assert.IsNull(runtimeState.BootFailedException); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + Assert.IsTrue(MyComponent.IsInit); + Assert.IsFalse(MyComponent.IsTerminated); - // NOTE: host.Run() could be used but that requires more work by manually calling IHostApplicationLifetime.StopApplication(). In these cases we don't need to wind down. - host.Start(); + await host.StopAsync(); + + Assert.IsTrue(MyComponent.IsTerminated); } + [Ignore("This test just shows that resolving services from the container before the host is done resolves 2 different instances")] [Test] - public void UseUmbracoCore() + public async Task BuildServiceProvider() + { + var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); + + IHostApplicationLifetime lifetime1 = null; + + var hostBuilder = new HostBuilder() + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + lifetime1 = services.BuildServiceProvider().GetRequiredService(); + }); + + var host = await hostBuilder.StartAsync(); + + var lifetime2 = host.Services.GetRequiredService(); + + lifetime1.StopApplication(); + Assert.IsTrue(lifetime1.ApplicationStopping.IsCancellationRequested); + Assert.AreEqual(lifetime1.ApplicationStopping.IsCancellationRequested, lifetime2.ApplicationStopping.IsCancellationRequested); + + } + + [Test] + public async Task UseUmbracoCore() { var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); var testHelper = new TestHelper(); - var host = Host.CreateDefaultBuilder() + var hostBuilder = new HostBuilder() //TODO: Need to have a configured umb version for the runtime state .UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb")) - .UseTestLifetime() + //.UseTestLifetime() .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { @@ -129,33 +159,26 @@ namespace Umbraco.Tests.Integration // Add it! services.AddUmbracoConfiguration(); services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + }); - // Run tests - services.AddHostedService(x => DelegateHostedService.Create(() => - { - var runtimeState = (RuntimeState)umbracoContainer.GetInstance(); - Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + var host = await hostBuilder.StartAsync(); - var dbBuilder = umbracoContainer.GetInstance(); - Assert.IsNotNull(dbBuilder); + var runtimeState = (RuntimeState)umbracoContainer.GetInstance(); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); - var canConnect = dbBuilder.CanConnectToDatabase; - Assert.IsTrue(canConnect); + var dbBuilder = umbracoContainer.GetInstance(); + Assert.IsNotNull(dbBuilder); - var dbResult = dbBuilder.CreateSchemaAndData(); - Assert.IsTrue(dbResult.Success); + var canConnect = dbBuilder.CanConnectToDatabase; + Assert.IsTrue(canConnect); - var dbFactory = umbracoContainer.GetInstance(); - var profilingLogger = umbracoContainer.GetInstance(); - runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger); - Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); + var dbResult = dbBuilder.CreateSchemaAndData(); + Assert.IsTrue(dbResult.Success); - }, null)); - }) - .Build(); - - // NOTE: host.Run() could be used but that requires more work by manually calling IHostApplicationLifetime.StopApplication(). In these cases we don't need to wind down. - host.Start(); + var dbFactory = umbracoContainer.GetInstance(); + var profilingLogger = umbracoContainer.GetInstance(); + runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger); + Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); } private LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory) @@ -181,6 +204,11 @@ namespace Umbraco.Tests.Integration IsComposed = true; } + public static void Reset() + { + IsComposed = false; + } + public static bool IsComposed { get; private set; } } @@ -205,6 +233,12 @@ namespace Umbraco.Tests.Integration { IsTerminated = true; } + + public static void Reset() + { + IsTerminated = false; + IsInit = false; + } } } diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index 0cb3f3e2e1..99a5352a17 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -80,7 +80,7 @@ namespace Umbraco.Tests.Runtimes // create the register and the composition var register = TestHelper.GetRegister(); var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs, ioHelper, appCaches); - composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator); + composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo); // create the core runtime and have it compose itself var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder); @@ -275,7 +275,7 @@ namespace Umbraco.Tests.Runtimes var register = TestHelper.GetRegister(); var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs, ioHelper, appCaches); var umbracoVersion = TestHelper.GetUmbracoVersion(); - composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator); + composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo); // create the core runtime and have it compose itself var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder); diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs index 1f06a818d6..a79838bd3e 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs @@ -1,5 +1,7 @@ using System; using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; namespace Umbraco.Web.BackOffice.AspNetCore { @@ -7,12 +9,10 @@ namespace Umbraco.Web.BackOffice.AspNetCore { public static IApplicationBuilder UseUmbracoBackOffice(this IApplicationBuilder app) { - if (app == null) - { - throw new ArgumentNullException(nameof(app)); - } + if (app == null) throw new ArgumentNullException(nameof(app)); return app; } + } } diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs similarity index 82% rename from src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs rename to src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs index 44fb9bc14f..6c3cecad28 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs @@ -6,14 +6,11 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Umbraco.Composing; using Umbraco.Configuration; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; @@ -24,9 +21,13 @@ namespace Umbraco.Web.BackOffice.AspNetCore { - public static class UmbracoBackOfficeServiceCollectionExtensions + public static class UmbracoCoreServiceCollectionExtensions { - + /// + /// Adds the Umbraco Configuration requirements + /// + /// + /// public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services) { var serviceProvider = services.BuildServiceProvider(); @@ -45,13 +46,10 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// - /// Adds the Umbraco Back Core requirements + /// Adds the Umbraco Back Core requirements /// /// /// - /// - /// Must be called after all services are added to the application because we are cross-wiring the container (currently) - /// public static IServiceCollection AddUmbracoCore(this IServiceCollection services) { if (!UmbracoServiceProviderFactory.IsActive) @@ -62,6 +60,13 @@ namespace Umbraco.Web.BackOffice.AspNetCore return services.AddUmbracoCore(umbContainer, Assembly.GetEntryAssembly()); } + /// + /// Adds the Umbraco Back Core requirements + /// + /// + /// + /// + /// public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IRegister umbContainer, Assembly entryAssembly) { if (services is null) throw new ArgumentNullException(nameof(services)); @@ -90,6 +95,8 @@ namespace Umbraco.Web.BackOffice.AspNetCore backOfficeInfo, typeFinder); + hostingEnvironment.RegisterObject(new CoreRuntimeShutdown(coreRuntime)); + var factory = coreRuntime.Boot(umbContainer); return services; @@ -124,8 +131,8 @@ namespace Umbraco.Web.BackOffice.AspNetCore out ILogger logger, out Configs configs, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment, out IBackOfficeInfo backOfficeInfo, out IProfiler profiler) { - // TODO: This isn't the best to have to resolve the services now but to avoid this will - // require quite a lot of re-work. + // TODO: Resolving services before the Host is done configuring this way means that the services resolved + // are not going to be the same instances that are going to be used within the application! var serviceProvider = services.BuildServiceProvider(); var httpContextAccessor = serviceProvider.GetRequiredService(); @@ -162,5 +169,29 @@ namespace Umbraco.Web.BackOffice.AspNetCore // nothing to check } } + + /// + /// Ensures the runtime is shutdown when the application is shutting down + /// + private class CoreRuntimeShutdown : IRegisteredObject + { + public CoreRuntimeShutdown(IRuntime runtime) + { + _runtime = runtime; + } + + private bool _completed = false; + private readonly IRuntime _runtime; + + public void Stop(bool immediate) + { + if (!_completed) + { + _completed = true; + _runtime.Terminate(); + } + + } + } } } diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index b81cafdb40..81aac30d2c 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -72,8 +72,6 @@ namespace Umbraco.Web.Runtime composition.Register(Lifetime.Singleton); - composition.Register(); - composition.Register(); composition.Register(Lifetime.Singleton); composition.Register(); composition.Register(Lifetime.Singleton); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index e8aaecdf4d..5eb60cb629 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -585,4 +585,4 @@ - + \ No newline at end of file From 900505704c264bbf561187a5128ba234ef2ed5be Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 14:54:45 +1100 Subject: [PATCH 03/16] Committing a namespaces change --- .gitignore | 1 + src/Umbraco.Core/Manifest/ManifestWatcher.cs | 2 +- src/Umbraco.Core/Net/IIpResolver.cs | 2 +- src/Umbraco.Core/Net/ISessionIdResolver.cs | 2 +- src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs | 2 +- src/Umbraco.Core/Net/IUserAgentProvider.cs | 2 +- src/Umbraco.Infrastructure/Intall/InstallHelper.cs | 2 +- .../Intall/InstallSteps/StarterKitDownloadStep.cs | 2 +- .../Intall/InstallSteps/StarterKitInstallStep.cs | 2 +- .../Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs | 2 +- .../Logging/Serilog/LoggerConfigExtensions.cs | 2 +- src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs | 2 +- src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs | 2 +- src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreMarchal.cs | 2 +- .../AspNetCore/AspNetCoreSessionIdResolver.cs | 2 +- .../AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs | 4 ++-- .../AspNetCore/AspNetCoreUserAgentProvider.cs | 2 +- src/Umbraco.Web/AspNet/AspNetIpResolver.cs | 2 +- src/Umbraco.Web/AspNet/AspNetSessionManager.cs | 2 +- src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs | 2 +- src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs | 2 +- src/Umbraco.Web/Compose/AuditEventsComponent.cs | 2 +- src/Umbraco.Web/Composing/Current.cs | 2 +- src/Umbraco.Web/Editors/PackageInstallController.cs | 2 +- src/Umbraco.Web/Runtime/WebInitialComposer.cs | 2 +- src/Umbraco.Web/Security/AppBuilderExtensions.cs | 2 +- src/Umbraco.Web/Security/BackOfficeUserManager.cs | 2 +- .../Security/Providers/MembersMembershipProvider.cs | 2 +- .../Security/Providers/UmbracoMembershipProvider.cs | 2 +- src/Umbraco.Web/UmbracoDefaultOwinStartup.cs | 2 +- 30 files changed, 31 insertions(+), 30 deletions(-) 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.Core/Manifest/ManifestWatcher.cs b/src/Umbraco.Core/Manifest/ManifestWatcher.cs index 23caac3a1b..adf2be466b 100644 --- a/src/Umbraco.Core/Manifest/ManifestWatcher.cs +++ b/src/Umbraco.Core/Manifest/ManifestWatcher.cs @@ -4,7 +4,7 @@ using System.IO; using System.Linq; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Core.Manifest { diff --git a/src/Umbraco.Core/Net/IIpResolver.cs b/src/Umbraco.Core/Net/IIpResolver.cs index 7fb6b8a793..8a7d670723 100644 --- a/src/Umbraco.Core/Net/IIpResolver.cs +++ b/src/Umbraco.Core/Net/IIpResolver.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Net +namespace Umbraco.Core.Net { public interface IIpResolver { diff --git a/src/Umbraco.Core/Net/ISessionIdResolver.cs b/src/Umbraco.Core/Net/ISessionIdResolver.cs index 745be5a435..94cdfb454a 100644 --- a/src/Umbraco.Core/Net/ISessionIdResolver.cs +++ b/src/Umbraco.Core/Net/ISessionIdResolver.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Net +namespace Umbraco.Core.Net { public interface ISessionIdResolver { diff --git a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs index 10d5b10955..eb38c67e2e 100644 --- a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Net +namespace Umbraco.Core.Net { public interface IUmbracoApplicationLifetime { diff --git a/src/Umbraco.Core/Net/IUserAgentProvider.cs b/src/Umbraco.Core/Net/IUserAgentProvider.cs index 14246ea99e..d3f997c607 100644 --- a/src/Umbraco.Core/Net/IUserAgentProvider.cs +++ b/src/Umbraco.Core/Net/IUserAgentProvider.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Net +namespace Umbraco.Core.Net { public interface IUserAgentProvider { diff --git a/src/Umbraco.Infrastructure/Intall/InstallHelper.cs b/src/Umbraco.Infrastructure/Intall/InstallHelper.cs index a5b4f71d8e..7aca4af09f 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.Core.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/StarterKitDownloadStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs index d8986cacb7..a20637584f 100644 --- a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Umbraco.Core.Services; using Umbraco.Core.Configuration; using Umbraco.Core.Models.Packaging; -using Umbraco.Net; +using Umbraco.Core.Net; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs index cc269408f4..0a6e67c829 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.Net; using Umbraco.Core.Services; -using Umbraco.Net; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs index 1558cdcf21..052775d918 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs @@ -1,7 +1,7 @@ using Serilog.Core; using Serilog.Events; using System; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Core.Logging.Serilog.Enrichers { diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs index f4e8f85281..59e0b8854f 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Hosting; using Umbraco.Core.Logging.Serilog.Enrichers; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Core.Logging.Serilog { diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs index bb77869e28..55b89d7996 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Diagnostics; using Umbraco.Core.Hosting; using Umbraco.Core.IO; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Core.Logging.Serilog { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs index cee43757d8..520fe6b8aa 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Http; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.BackOffice.AspNetCore { 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/AspNetCoreSessionIdResolver.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs index cafb02d367..a27e378909 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs index 20cfef352d..e7aba5e2de 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs @@ -1,9 +1,9 @@ using System.Threading; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; -using Umbraco.Net; +using Umbraco.Core.Net; -namespace Umbraco.Web.AspNet +namespace Umbraco.Web.BackOffice.AspNetCore { public class AspNetCoreUmbracoApplicationLifetime : IUmbracoApplicationLifetime { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs index f9c9884704..a85970afaf 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Http; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web/AspNet/AspNetIpResolver.cs b/src/Umbraco.Web/AspNet/AspNetIpResolver.cs index 7eaca54663..026fb7ff12 100644 --- a/src/Umbraco.Web/AspNet/AspNetIpResolver.cs +++ b/src/Umbraco.Web/AspNet/AspNetIpResolver.cs @@ -1,6 +1,6 @@ using System.Web; using Umbraco.Core; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web { diff --git a/src/Umbraco.Web/AspNet/AspNetSessionManager.cs b/src/Umbraco.Web/AspNet/AspNetSessionManager.cs index bf7b1c05c3..9196cb137f 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.Net; using Umbraco.Core.Session; -using Umbraco.Net; namespace Umbraco.Web.AspNet { diff --git a/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs b/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs index 245e8ea374..64988a20d9 100644 --- a/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs @@ -1,6 +1,6 @@ using System.Threading; using System.Web; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.AspNet { diff --git a/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs b/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs index bd37b62531..4ba73292bb 100644 --- a/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs +++ b/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs @@ -1,4 +1,4 @@ -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.AspNet { diff --git a/src/Umbraco.Web/Compose/AuditEventsComponent.cs b/src/Umbraco.Web/Compose/AuditEventsComponent.cs index fba6e754c8..d03f33d7ac 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.Core.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 eec3dcd1e3..4424de6771 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.Core.Net; using Umbraco.Core.PackageActions; using Umbraco.Core.Packaging; using Umbraco.Core.PropertyEditors; @@ -18,7 +19,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 672b47f1eb..178a5c96d9 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -14,11 +14,11 @@ using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Editors; using Umbraco.Core.Models.Packaging; +using Umbraco.Core.Net; using Umbraco.Core.Packaging; using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Core.Strings; -using Umbraco.Net; using Umbraco.Web.JavaScript; using Umbraco.Web.Models; using Umbraco.Web.Models.ContentEditing; diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 81aac30d2c..1d7fc8fd6e 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.Core.Net; using Umbraco.Core.Request; using Umbraco.Core.Session; using Umbraco.Web.AspNet; diff --git a/src/Umbraco.Web/Security/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/AppBuilderExtensions.cs index 8fab9f4ea8..5416683eab 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.Core.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..64b7054723 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.Core.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/MembersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs index d393078cc6..ffa9a1c967 100644 --- a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Services; using Umbraco.Core.Models.Membership; using Umbraco.Web.Composing; using System; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.Security.Providers { diff --git a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs index d2eeebaeaf..9466dd6732 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.Core.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/UmbracoDefaultOwinStartup.cs b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs index a69e6c6f8d..8fcdc2c542 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.Net; using Umbraco.Core.Services; -using Umbraco.Net; using Umbraco.Web; using Umbraco.Web.Composing; using Umbraco.Web.Security; From 612a47b16b9aebb63bfbe26f482e7e578cbcb178 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 15:06:22 +1100 Subject: [PATCH 04/16] Splits interfaces into separate ones, removes overlap between interfaces, injects the necessary bits, and much more --- .../DefaultUmbracoAssemblyProvider.cs | 1 + .../Hosting/IHostingEnvironment.cs | 3 - .../Hosting/IHostingEnvironmentLifetime.cs | 8 + src/Umbraco.Core/Runtime/IMainDom.cs | 10 +- src/Umbraco.Core/Runtime/MainDom.cs | 22 ++- src/Umbraco.Core/Scheduling/KeepAlive.cs | 16 +- .../Scheduling/TempFileCleanup.cs | 8 +- src/Umbraco.Core/Services/IRuntime.cs | 4 +- src/Umbraco.Core/Services/IRuntimeState.cs | 16 -- src/Umbraco.Core/SimpleMainDom.cs | 4 + .../BatchedDatabaseServerMessenger.cs | 5 +- ...aseServerRegistrarAndMessengerComponent.cs | 5 +- .../Compose/ManifestWatcherComponent.cs | 10 +- .../Runtime/CoreInitialComposer.cs | 5 +- .../Runtime/CoreRuntime.cs | 103 ++++++------ .../Runtime/WebRuntime.cs | 4 +- src/Umbraco.Infrastructure/RuntimeOptions.cs | 10 +- src/Umbraco.Infrastructure/RuntimeState.cs | 39 +---- .../Scheduling/BackgroundTaskRunner.cs | 10 +- .../Scheduling/HealthCheckNotifier.cs | 15 +- .../Scheduling/LogScrubber.cs | 12 +- .../Scheduling/ScheduledPublishing.cs | 10 +- .../Scheduling/SchedulerComponent.cs | 22 +-- .../Search/BackgroundIndexRebuilder.cs | 6 +- .../Sync/DatabaseServerMessenger.cs | 12 +- .../PureLiveModelFactory.cs | 11 +- src/Umbraco.Tests.Common/TestHelperBase.cs | 11 +- .../Implementations/HostBuilderExtensions.cs | 22 +-- .../Implementations/TestHelper.cs | 14 +- .../Implementations/TestHostingEnvironment.cs | 23 +++ .../Implementations/TestLifetime.cs | 6 +- src/Umbraco.Tests.Integration/RuntimeTests.cs | 158 ++++++++++++------ .../XmlPublishedSnapshotService.cs | 8 +- .../LegacyXmlPublishedCache/XmlStore.cs | 19 +-- .../Routing/UmbracoModuleTests.cs | 3 +- .../Runtimes/CoreRuntimeTests.cs | 38 ++--- src/Umbraco.Tests/Runtimes/StandaloneTests.cs | 4 +- .../Scheduling/BackgroundTaskRunnerTests.cs | 6 +- .../Scheduling/BackgroundTaskRunnerTests2.cs | 4 +- src/Umbraco.Tests/TestHelpers/TestHelper.cs | 9 +- .../TestHelpers/TestWithDatabaseBase.cs | 1 + src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 3 +- .../Web/Mvc/UmbracoViewPageTests.cs | 1 + .../AspNetCore/AspNetCoreComposer.cs | 27 +++ .../AspNetCoreHostingEnvironment.cs | 66 ++------ .../AspNetCoreHostingEnvironmentShutdown.cs | 59 +++++++ ...oBackOfficeApplicationBuilderExtensions.cs | 50 ++++++ .../UmbracoCoreServiceCollectionExtensions.cs | 42 +---- .../AspNet/AspNetHostingEnvironment.cs | 41 +---- .../AspNet/AspNetHostingLifetime.cs | 47 ++++++ .../Profiling/WebProfilingController.cs | 10 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 + src/Umbraco.Web/UmbracoApplication.cs | 2 +- src/Umbraco.Web/UmbracoApplicationBase.cs | 4 +- src/Umbraco.Web/UmbracoContext.cs | 2 +- src/Umbraco.Web/UrlHelperExtensions.cs | 4 +- 56 files changed, 614 insertions(+), 442 deletions(-) create mode 100644 src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs create mode 100644 src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs create mode 100644 src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs create mode 100644 src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs create mode 100644 src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs 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/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/Hosting/IHostingEnvironmentLifetime.cs b/src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs new file mode 100644 index 0000000000..891cedad20 --- /dev/null +++ b/src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Core.Hosting +{ + public interface IHostingEnvironmentLifetime + { + void RegisterObject(IRegisteredObject registeredObject); + void UnregisterObject(IRegisteredObject registeredObject); + } +} diff --git a/src/Umbraco.Core/Runtime/IMainDom.cs b/src/Umbraco.Core/Runtime/IMainDom.cs index 444fc1c7d0..1b7f09bc89 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(IHostingEnvironmentLifetime 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..0a4a250aa6 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 IHostingEnvironmentLifetime _hostingEnvironment; private readonly IMainDomLock _mainDomLock; // our own lock for local consistency @@ -42,17 +42,24 @@ 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(IHostingEnvironmentLifetime hostingEnvironment) + { + _hostingEnvironment = 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 +187,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) 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 565b2563e6..4b5e26651b 100644 --- a/src/Umbraco.Core/Services/IRuntimeState.cs +++ b/src/Umbraco.Core/Services/IRuntimeState.cs @@ -25,21 +25,6 @@ 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. /// @@ -71,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..52ed6c1d91 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(IHostingEnvironmentLifetime 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..4e183b9211 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, + IHostingEnvironmentLifetime 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..06b3cc0cc9 100644 --- a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs @@ -4,13 +4,13 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Manifest; -using Umbraco.Net; +using Umbraco.Core.Net; 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/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs index 67cfcded92..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() diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index 5cd51a174a..89ec036607 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,26 @@ 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; + /// + /// Constructor + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public CoreRuntime( Configs configs, IUmbracoVersion umbracoVersion, @@ -65,11 +77,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,12 +89,13 @@ namespace Umbraco.Core.Runtime protected ILogger Logger { get; } protected IBackOfficeInfo BackOfficeInfo { get; } + public IDbProviderFactoryCreator DbProviderFactoryCreator { get; } /// /// Gets the profiler. /// - protected IProfiler Profiler { get; set; } + protected IProfiler Profiler { get; } /// /// Gets the profiling logger. @@ -109,10 +118,10 @@ 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)); @@ -140,28 +149,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); @@ -179,15 +184,8 @@ namespace Umbraco.Core.Runtime composition = new Composition(register, typeLoader, ProfilingLogger, _state, Configs, IOHelper, appCaches); 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); @@ -205,13 +203,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) { @@ -228,11 +220,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 */ } } @@ -246,7 +238,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(IHostingEnvironmentLifetime)} 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() @@ -273,13 +287,13 @@ namespace Umbraco.Core.Runtime IOHelper.SetRootDirectory(path); } - private bool AcquireMainDom(IMainDom mainDom) + private bool AcquireMainDom(IMainDom mainDom, IHostingEnvironmentLifetime hostingEnvironmentLifetime) { using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Acquired.")) { try { - return mainDom.IsMainDom; + return mainDom.Acquire(hostingEnvironmentLifetime); } catch { @@ -338,12 +352,6 @@ namespace Umbraco.Core.Runtime _components?.Terminate(); } - /// - /// Composes the runtime. - /// - public virtual void Compose(Composition composition) - { - } #region Getters @@ -384,5 +392,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 420fba7ffc..e0099c5e7e 100644 --- a/src/Umbraco.Infrastructure/RuntimeState.cs +++ b/src/Umbraco.Infrastructure/RuntimeState.cs @@ -22,44 +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; } - /// - /// 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; @@ -70,23 +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 CurrentMigrationState { get; internal set; } + public string CurrentMigrationState { get; private set; } /// - public string FinalMigrationState { get; internal set; } + public string FinalMigrationState { get; private set; } /// public RuntimeLevel Level { get; internal set; } = RuntimeLevel.Unknown; @@ -248,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..31884992f7 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 IHostingEnvironmentLifetime _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, IHostingEnvironmentLifetime 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, IHostingEnvironmentLifetime 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, IHostingEnvironmentLifetime 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, IHostingEnvironmentLifetime 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..c867d81d69 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 IHostingEnvironmentLifetime _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, + IHostingEnvironmentLifetime 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..fa697a4743 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 IHostingEnvironmentLifetime _hostingEnvironment; private static BackgroundTaskRunner _rebuildOnStartupRunner; - public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IHostingEnvironment hostingEnvironment, IndexRebuilder indexRebuilder) + public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IHostingEnvironmentLifetime 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..3c189cc045 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 IHostingEnvironmentLifetime _hostingLifetime; private readonly IIOHelper _ioHelper; private readonly ModelsGenerationError _errors; @@ -51,12 +51,13 @@ namespace Umbraco.ModelsBuilder.Embedded IProfilingLogger logger, IModelsBuilderConfig config, IHostingEnvironment hostingEnvironment, + IHostingEnvironmentLifetime 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/TestHelperBase.cs b/src/Umbraco.Tests.Common/TestHelperBase.cs index 536bebee56..76aa38e246 100644 --- a/src/Umbraco.Tests.Common/TestHelperBase.cs +++ b/src/Umbraco.Tests.Common/TestHelperBase.cs @@ -12,11 +12,11 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Net; using Umbraco.Core.Persistence; using Umbraco.Core.Serialization; using Umbraco.Core.Strings; using Umbraco.Core.Sync; -using Umbraco.Net; using Umbraco.Web; using Umbraco.Web.Routing; @@ -31,7 +31,7 @@ namespace Umbraco.Tests.Common private UriUtility _uriUtility; private IIOHelper _ioHelper; - public TestHelperBase(Assembly entryAssembly) + protected TestHelperBase(Assembly entryAssembly) { SettingsForTests = new SettingsForTests(); MainDom = new SimpleMainDom(); @@ -52,12 +52,8 @@ namespace Umbraco.Tests.Common return new RuntimeState( Mock.Of(), Mock.Of(), - new Lazy(), - new Lazy(), GetUmbracoVersion(), - GetHostingEnvironment(), - GetBackOfficeInfo() - ); + GetBackOfficeInfo()); } public abstract IBackOfficeInfo GetBackOfficeInfo(); @@ -132,6 +128,7 @@ namespace Umbraco.Tests.Common } public abstract IHostingEnvironment GetHostingEnvironment(); + public abstract IHostingEnvironmentLifetime GetHostingEnvironmentLifetime(); public abstract IIpResolver GetIpResolver(); diff --git a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs index 2d86122770..b0b664484b 100644 --- a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs @@ -1,31 +1,17 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using System; +using System; using System.Collections.Generic; using System.Data.Common; using System.Data.SqlClient; using System.IO; -using Umbraco.Core.Persistence; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using Umbraco.Tests.Integration.Testing; -namespace Umbraco.Tests.Integration +namespace Umbraco.Tests.Integration.Implementations { public static class HostBuilderExtensions { - - /// - /// Ensures the lifetime of the host ends as soon as code executes - /// - /// - /// - public static IHostBuilder UseTestLifetime(this IHostBuilder hostBuilder) - { - hostBuilder.ConfigureServices((context, collection) => collection.AddSingleton()); - return hostBuilder; - } - public static IHostBuilder UseLocalDb(this IHostBuilder hostBuilder, string dbFilePath) { // Need to register SqlClient manually diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index 4c37903b0c..f1aa53694c 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -8,10 +8,11 @@ using System.Net; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Diagnostics; +using Umbraco.Core.Hosting; using Umbraco.Core.Logging; +using Umbraco.Core.Net; using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; -using Umbraco.Net; using Umbraco.Tests.Common; using Umbraco.Web.BackOffice; using Umbraco.Web.BackOffice.AspNetCore; @@ -19,11 +20,11 @@ using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment; namespace Umbraco.Tests.Integration.Implementations { - public class TestHelper : TestHelperBase { private IBackOfficeInfo _backOfficeInfo; private readonly IHostingEnvironment _hostingEnvironment; + private readonly IHostingEnvironmentLifetime _hostingLifetime; private readonly IIpResolver _ipResolver; private readonly IWebHostEnvironment _hostEnvironment; private readonly IHttpContextAccessor _httpContextAccessor; @@ -40,11 +41,12 @@ namespace Umbraco.Tests.Integration.Implementations && x.ContentRootPath == CurrentAssemblyDirectory && x.WebRootPath == CurrentAssemblyDirectory); // same folder for now? - _hostingEnvironment = new AspNetCoreHostingEnvironment( + _hostingEnvironment = new TestHostingEnvironment( SettingsForTests.GetDefaultHostingSettings(), _hostEnvironment, - _httpContextAccessor, - Mock.Of()); + _httpContextAccessor); + + _hostingLifetime = new AspNetCoreHostingEnvironmentLifetime(Mock.Of()); Logger = new ProfilingLogger(new ConsoleLogger(new MessageTemplates()), Profiler); } @@ -75,7 +77,9 @@ namespace Umbraco.Tests.Integration.Implementations } public override IHostingEnvironment GetHostingEnvironment() => _hostingEnvironment; + public override IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() => _hostingLifetime; public override IIpResolver GetIpResolver() => _ipResolver; + } } diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs b/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs new file mode 100644 index 0000000000..491b7e5480 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Umbraco.Core.Configuration; +using Umbraco.Web.BackOffice.AspNetCore; + +namespace Umbraco.Tests.Integration.Implementations +{ + + public class TestHostingEnvironment : AspNetCoreHostingEnvironment, Umbraco.Core.Hosting.IHostingEnvironment + { + public TestHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor) : base(hostingSettings, webHostEnvironment, httpContextAccessor) + { + } + + /// + /// Override for tests since we are not hosted + /// + /// + /// This is specifically used by IOHelper and we want this to return false so that the root path is manually calcualted which is what we want for tests. + /// + bool Umbraco.Core.Hosting.IHostingEnvironment.IsHosted { get; } = false; + } +} diff --git a/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs b/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs index 063644490b..a18360eff9 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs @@ -1,8 +1,8 @@ -using Microsoft.Extensions.Hosting; -using System.Threading; +using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; -namespace Umbraco.Tests.Integration +namespace Umbraco.Tests.Integration.Implementations { /// /// Ensures the host lifetime ends as soon as code execution is done diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index dae4d0cbb8..c9e0e94481 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -10,6 +10,7 @@ using NUnit.Framework; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Composing.LightInject; @@ -46,27 +47,36 @@ namespace Umbraco.Tests.Integration /// Manually configure the containers/dependencies and call Boot on Core runtime /// [Test] - public void BootCoreRuntime() + public void Boot_Core_Runtime() { // LightInject / Umbraco var container = UmbracoServiceProviderFactory.CreateServiceContainer(); var serviceProviderFactory = new UmbracoServiceProviderFactory(container); var umbracoContainer = serviceProviderFactory.GetContainer(); - // Create the core runtime + // Special case since we are not using the Generic Host, we need to manually add an AspNetCore service to the container + umbracoContainer.Register(x => Mock.Of()); + var testHelper = new TestHelper(); + + // Create the core runtime var coreRuntime = new CoreRuntime(testHelper.GetConfigs(), testHelper.GetUmbracoVersion(), testHelper.IOHelper, testHelper.Logger, testHelper.Profiler, testHelper.UmbracoBootPermissionChecker, testHelper.GetHostingEnvironment(), testHelper.GetBackOfficeInfo(), testHelper.DbProviderFactoryCreator, testHelper.MainDom, testHelper.GetTypeFinder()); - // boot it! - var factory = coreRuntime.Boot(umbracoContainer); + // boot it! + var factory = coreRuntime.Configure(umbracoContainer); Assert.IsTrue(coreRuntime.MainDom.IsMainDom); Assert.IsNull(coreRuntime.State.BootFailedException); Assert.AreEqual(RuntimeLevel.Install, coreRuntime.State.Level); Assert.IsTrue(MyComposer.IsComposed); + Assert.IsFalse(MyComponent.IsInit); + Assert.IsFalse(MyComponent.IsTerminated); + + coreRuntime.Start(); + Assert.IsTrue(MyComponent.IsInit); Assert.IsFalse(MyComponent.IsTerminated); @@ -78,7 +88,7 @@ namespace Umbraco.Tests.Integration } /// - /// Calling AddUmbracoCore to configure the container and boot the core runtime within a generic host + /// Calling AddUmbracoCore to configure the container /// [Test] public async Task AddUmbracoCore() @@ -99,22 +109,106 @@ namespace Umbraco.Tests.Integration }); var host = await hostBuilder.StartAsync(); + var app = new ApplicationBuilder(host.Services); // assert results - var runtimeState = umbracoContainer.GetInstance(); - var mainDom = umbracoContainer.GetInstance(); + var runtimeState = app.ApplicationServices.GetRequiredService(); + var mainDom = app.ApplicationServices.GetRequiredService(); + + Assert.IsFalse(mainDom.IsMainDom); // We haven't "Started" the runtime yet + Assert.IsNull(runtimeState.BootFailedException); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + Assert.IsFalse(MyComponent.IsInit); // We haven't "Started" the runtime yet + + await host.StopAsync(); + + Assert.IsFalse(MyComponent.IsTerminated); // we didn't "Start" the runtime so nothing was registered for shutdown + } + + /// + /// Calling AddUmbracoCore to configure the container and UseUmbracoCore to start the runtime + /// + /// + [Test] + public async Task UseUmbracoCore() + { + var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); + var testHelper = new TestHelper(); + + var hostBuilder = new HostBuilder() + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + AddRequiredNetCoreServices(services, testHelper); + + // Add it! + services.AddUmbracoConfiguration(); + services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + }); + + var host = await hostBuilder.StartAsync(); + var app = new ApplicationBuilder(host.Services); + + app.UseUmbracoCore(); + + + // assert results + var runtimeState = app.ApplicationServices.GetRequiredService(); + var mainDom = app.ApplicationServices.GetRequiredService(); Assert.IsTrue(mainDom.IsMainDom); Assert.IsNull(runtimeState.BootFailedException); Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); Assert.IsTrue(MyComponent.IsInit); - Assert.IsFalse(MyComponent.IsTerminated); await host.StopAsync(); Assert.IsTrue(MyComponent.IsTerminated); } + [Test] + public async Task Install_Database() + { + var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); + var testHelper = new TestHelper(); + + var hostBuilder = new HostBuilder() + //TODO: Need to have a configured umb version for the runtime state + .UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb")) + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + AddRequiredNetCoreServices(services, testHelper); + + // Add it! + services.AddUmbracoConfiguration(); + services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + }); + + var host = await hostBuilder.StartAsync(); + var app = new ApplicationBuilder(host.Services); + + app.UseUmbracoCore(); + + + var runtimeState = (RuntimeState)app.ApplicationServices.GetRequiredService(); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + + var dbBuilder = app.ApplicationServices.GetRequiredService(); + Assert.IsNotNull(dbBuilder); + + var canConnect = dbBuilder.CanConnectToDatabase; + Assert.IsTrue(canConnect); + + var dbResult = dbBuilder.CreateSchemaAndData(); + Assert.IsTrue(dbResult.Success); + + // TODO: Get this to work ... but to do that we need to mock or pass in a current umbraco version + //var dbFactory = app.ApplicationServices.GetRequiredService(); + //var profilingLogger = app.ApplicationServices.GetRequiredService(); + //runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger); + //Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); + } [Ignore("This test just shows that resolving services from the container before the host is done resolves 2 different instances")] [Test] @@ -128,6 +222,8 @@ namespace Umbraco.Tests.Integration .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { + // TODO: Try to re-register the service as a callback and see if it resolves to the same instance + lifetime1 = services.BuildServiceProvider().GetRequiredService(); }); @@ -141,46 +237,6 @@ namespace Umbraco.Tests.Integration } - [Test] - public async Task UseUmbracoCore() - { - var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); - var testHelper = new TestHelper(); - - var hostBuilder = new HostBuilder() - //TODO: Need to have a configured umb version for the runtime state - .UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb")) - //.UseTestLifetime() - .UseUmbraco(serviceProviderFactory) - .ConfigureServices((hostContext, services) => - { - AddRequiredNetCoreServices(services, testHelper); - - // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); - }); - - var host = await hostBuilder.StartAsync(); - - var runtimeState = (RuntimeState)umbracoContainer.GetInstance(); - Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); - - var dbBuilder = umbracoContainer.GetInstance(); - Assert.IsNotNull(dbBuilder); - - var canConnect = dbBuilder.CanConnectToDatabase; - Assert.IsTrue(canConnect); - - var dbResult = dbBuilder.CreateSchemaAndData(); - Assert.IsTrue(dbResult.Success); - - var dbFactory = umbracoContainer.GetInstance(); - var profilingLogger = umbracoContainer.GetInstance(); - runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger); - Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); - } - private LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory) { var container = new ServiceContainer(ContainerOptions.Default.Clone().WithMicrosoftSettings().WithAspNetCoreSettings()); @@ -189,9 +245,15 @@ namespace Umbraco.Tests.Integration return umbracoContainer; } + /// + /// These services need to be manually added because they do not get added by the generic host + /// + /// + /// private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper) { services.AddSingleton(x => testHelper.GetHttpContextAccessor()); + // the generic host does add IHostEnvironment but not this one because we are not actually in a web context services.AddSingleton(x => testHelper.GetWebHostEnvironment()); } diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs index 609dcd98b8..5eb57b6ca6 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs @@ -41,6 +41,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private readonly IEntityXmlSerializer _entitySerializer; private readonly IVariationContextAccessor _variationContextAccessor; private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IHostingEnvironmentLifetime _hostingLifetime; private readonly IHostingEnvironment _hostingEnvironment; #region Constructors @@ -57,6 +58,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache ILogger logger, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, + IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper, ISiteDomainHelper siteDomainHelper, IEntityXmlSerializer entitySerializer, @@ -67,7 +69,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache publishedSnapshotAccessor, variationContextAccessor, umbracoContextAccessor, documentRepository, mediaRepository, memberRepository, defaultCultureAccessor, - logger, globalSettings, hostingEnvironment, shortStringHelper, siteDomainHelper, entitySerializer, null, mainDom, testing, enableRepositoryEvents) + logger, globalSettings, hostingEnvironment, hostingLifetime, shortStringHelper, siteDomainHelper, entitySerializer, null, mainDom, testing, enableRepositoryEvents) { _umbracoContextAccessor = umbracoContextAccessor; } @@ -84,6 +86,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache ILogger logger, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, + IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper, ISiteDomainHelper siteDomainHelper, IEntityXmlSerializer entitySerializer, @@ -99,7 +102,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache _xmlStore = new XmlStore(serviceContext.ContentTypeService, serviceContext.ContentService, scopeProvider, _routesCache, _contentTypeCache, publishedSnapshotAccessor, mainDom, testing, enableRepositoryEvents, - documentRepository, mediaRepository, memberRepository, globalSettings, entitySerializer, hostingEnvironment, shortStringHelper); + documentRepository, mediaRepository, memberRepository, entitySerializer, hostingEnvironment, hostingLifetime, shortStringHelper); _domainService = serviceContext.DomainService; _memberService = serviceContext.MemberService; @@ -113,6 +116,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache _siteDomainHelper = siteDomainHelper; _entitySerializer = entitySerializer; _hostingEnvironment = hostingEnvironment; + _hostingLifetime = hostingLifetime; } public override void Dispose() diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs index 238da68370..b051682ed7 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs @@ -45,9 +45,8 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private readonly IDocumentRepository _documentRepository; private readonly IMediaRepository _mediaRepository; private readonly IMemberRepository _memberRepository; - private readonly IGlobalSettings _globalSettings; private readonly IEntityXmlSerializer _entitySerializer; - private readonly IHostingEnvironment _hostingEnvironment; + private readonly IHostingEnvironmentLifetime _hostingLifetime; private readonly IShortStringHelper _shortStringHelper; private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; private readonly PublishedContentTypeCache _contentTypeCache; @@ -58,7 +57,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private XmlStoreFilePersister _persisterTask; private volatile bool _released; - private bool _withRepositoryEvents; #region Constructors @@ -67,8 +65,8 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache /// /// 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, IHostingEnvironmentLifetime 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, IHostingEnvironmentLifetime 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/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..44481666bc 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -146,31 +146,31 @@ namespace Umbraco.Tests.Runtimes } */ - // 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); + //// 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()); + // 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); - } + // composition.RegisterUnique(scopeProvider); + //} private IMainDom _mainDom; - public override IFactory Boot(IRegister container) + public override IFactory Configure(IRegister container) { - var factory = base.Boot(container); + var factory = base.Configure(container); _mainDom = factory.GetInstance(); return factory; } diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index 99a5352a17..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; @@ -84,7 +84,6 @@ namespace Umbraco.Tests.Runtimes // 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); @@ -279,7 +278,6 @@ namespace Umbraco.Tests.Runtimes // 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..18eb3d19a4 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 IHostingEnvironmentLifetime _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..54cbec46e9 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.Core.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 IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() + => new AspNetHostingLifetime(); + public override IIpResolver GetIpResolver() => new AspNetIpResolver(); } @@ -320,6 +323,8 @@ namespace Umbraco.Tests.TestHelpers public static IHostingEnvironment GetHostingEnvironment() => _testHelperInternal.GetHostingEnvironment(); + public static IHostingEnvironmentLifetime 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..9222f7e4ab 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.Core.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 IHostingEnvironmentLifetime HostingLifetime { get; } = new AspNetHostingLifetime(); protected IIpResolver IpResolver => Factory.GetInstance(); protected IBackOfficeInfo BackOfficeInfo => Factory.GetInstance(); protected AppCaches AppCaches => Factory.GetInstance(); 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/AspNetCoreComposer.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs new file mode 100644 index 0000000000..e85f3cb3f9 --- /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.Core.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/AspNetCoreHostingEnvironmentShutdown.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs new file mode 100644 index 0000000000..3726e50e3b --- /dev/null +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.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 AspNetCoreHostingEnvironmentLifetime : IHostingEnvironmentLifetime + { + private readonly IHostApplicationLifetime _hostApplicationLifetime; + private readonly ConcurrentDictionary _registeredObjects = + new ConcurrentDictionary(); + + public AspNetCoreHostingEnvironmentLifetime(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/UmbracoBackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs index a79838bd3e..feb122a48b 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs @@ -2,6 +2,9 @@ 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 { @@ -14,5 +17,52 @@ namespace Umbraco.Web.BackOffice.AspNetCore 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, IHostingEnvironmentLifetime hostLifetime) + { + _runtime = runtime; + _hostLifetime = hostLifetime; + } + + private bool _completed = false; + private readonly IRuntime _runtime; + private readonly IHostingEnvironmentLifetime _hostLifetime; + + public void Stop(bool immediate) + { + if (!_completed) + { + _completed = true; + _runtime.Terminate(); + _hostLifetime.UnregisterObject(this); + } + + } + } } } diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs index 6c3cecad28..d283a7ffb1 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs @@ -19,8 +19,7 @@ using Umbraco.Core.Runtime; namespace Umbraco.Web.BackOffice.AspNetCore { - - + // TODO: Move to Umbraco.Web.Common public static class UmbracoCoreServiceCollectionExtensions { /// @@ -73,11 +72,12 @@ namespace Umbraco.Web.BackOffice.AspNetCore 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(); CreateCompositionRoot(services, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler); - // TODO: Get rid of this 'Current' requirement var globalSettings = configs.Global(); var umbracoVersion = new UmbracoVersion(globalSettings); @@ -95,9 +95,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore backOfficeInfo, typeFinder); - hostingEnvironment.RegisterObject(new CoreRuntimeShutdown(coreRuntime)); - - var factory = coreRuntime.Boot(umbContainer); + var factory = coreRuntime.Configure(umbContainer); return services; } @@ -119,7 +117,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); @@ -137,10 +135,6 @@ namespace Umbraco.Web.BackOffice.AspNetCore var httpContextAccessor = serviceProvider.GetRequiredService(); var webHostEnvironment = serviceProvider.GetRequiredService(); - // TODO: I'm unsure about this, by doing this it means we are resolving a "Different" instance to the one - // that controls the whole app because the instances comes from a different service provider. This - // could cause some issues with shutdowns, etc... we need to investigate. - var hostApplicationLifetime = serviceProvider.GetRequiredService(); configs = serviceProvider.GetService(); if (configs == null) @@ -150,7 +144,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore var coreDebug = configs.CoreDebug(); var globalSettings = configs.Global(); - hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor, hostApplicationLifetime); + hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor); ioHelper = new IOHelper(hostingEnvironment, globalSettings); logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, new AspNetCoreSessionIdResolver(httpContextAccessor), @@ -170,28 +164,6 @@ namespace Umbraco.Web.BackOffice.AspNetCore } } - /// - /// Ensures the runtime is shutdown when the application is shutting down - /// - private class CoreRuntimeShutdown : IRegisteredObject - { - public CoreRuntimeShutdown(IRuntime runtime) - { - _runtime = runtime; - } - - private bool _completed = false; - private readonly IRuntime _runtime; - - public void Stop(bool immediate) - { - if (!_completed) - { - _completed = true; - _runtime.Terminate(); - } - - } - } + } } diff --git a/src/Umbraco.Web/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/AspNetHostingLifetime.cs b/src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs new file mode 100644 index 0000000000..316ecb8389 --- /dev/null +++ b/src/Umbraco.Web/AspNet/AspNetHostingLifetime.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 AspNetHostingLifetime : IHostingEnvironmentLifetime + { + 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/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/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 5eb60cb629..ce08d5498d 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -134,6 +134,7 @@ + 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/UrlHelperExtensions.cs b/src/Umbraco.Web/UrlHelperExtensions.cs index a0bf5d3ded..f0ee309630 100644 --- a/src/Umbraco.Web/UrlHelperExtensions.cs +++ b/src/Umbraco.Web/UrlHelperExtensions.cs @@ -143,12 +143,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}.{ClientDependencySettings.Instance.Version}".GenerateHash(); } } From a0acc8126d20e370529d1da44b62d88fcdb502a9 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 16:52:42 +1100 Subject: [PATCH 05/16] oops change namespace back to Umbraco.net --- src/Umbraco.Core/Manifest/ManifestWatcher.cs | 2 +- src/Umbraco.Core/Net/IIpResolver.cs | 2 +- src/Umbraco.Core/Net/ISessionIdResolver.cs | 2 +- src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs | 2 +- src/Umbraco.Core/Net/IUserAgentProvider.cs | 2 +- src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs | 2 +- src/Umbraco.Infrastructure/Intall/InstallHelper.cs | 2 +- .../Intall/InstallSteps/StarterKitDownloadStep.cs | 2 +- .../Intall/InstallSteps/StarterKitInstallStep.cs | 2 +- .../Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs | 2 +- .../Logging/Serilog/LoggerConfigExtensions.cs | 2 +- src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs | 2 +- src/Umbraco.Tests.Common/TestHelperBase.cs | 2 +- src/Umbraco.Tests.Integration/Implementations/TestHelper.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestHelper.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs | 2 +- src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs | 2 +- .../AspNetCore/AspNetCoreSessionIdResolver.cs | 2 +- .../AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs | 2 +- .../AspNetCore/AspNetCoreUserAgentProvider.cs | 2 +- src/Umbraco.Web/AspNet/AspNetIpResolver.cs | 2 +- src/Umbraco.Web/AspNet/AspNetSessionManager.cs | 2 +- src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs | 2 +- src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs | 2 +- src/Umbraco.Web/Compose/AuditEventsComponent.cs | 2 +- src/Umbraco.Web/Composing/Current.cs | 2 +- src/Umbraco.Web/Editors/PackageInstallController.cs | 2 +- src/Umbraco.Web/Runtime/WebInitialComposer.cs | 2 +- src/Umbraco.Web/Security/AppBuilderExtensions.cs | 2 +- src/Umbraco.Web/Security/BackOfficeUserManager.cs | 2 +- src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs | 2 +- src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs | 2 +- src/Umbraco.Web/UmbracoDefaultOwinStartup.cs | 2 +- 34 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/Umbraco.Core/Manifest/ManifestWatcher.cs b/src/Umbraco.Core/Manifest/ManifestWatcher.cs index adf2be466b..23caac3a1b 100644 --- a/src/Umbraco.Core/Manifest/ManifestWatcher.cs +++ b/src/Umbraco.Core/Manifest/ManifestWatcher.cs @@ -4,7 +4,7 @@ using System.IO; using System.Linq; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Core.Manifest { diff --git a/src/Umbraco.Core/Net/IIpResolver.cs b/src/Umbraco.Core/Net/IIpResolver.cs index 8a7d670723..7fb6b8a793 100644 --- a/src/Umbraco.Core/Net/IIpResolver.cs +++ b/src/Umbraco.Core/Net/IIpResolver.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Net +namespace Umbraco.Net { public interface IIpResolver { diff --git a/src/Umbraco.Core/Net/ISessionIdResolver.cs b/src/Umbraco.Core/Net/ISessionIdResolver.cs index 94cdfb454a..745be5a435 100644 --- a/src/Umbraco.Core/Net/ISessionIdResolver.cs +++ b/src/Umbraco.Core/Net/ISessionIdResolver.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Net +namespace Umbraco.Net { public interface ISessionIdResolver { diff --git a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs index eb38c67e2e..10d5b10955 100644 --- a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Net +namespace Umbraco.Net { public interface IUmbracoApplicationLifetime { diff --git a/src/Umbraco.Core/Net/IUserAgentProvider.cs b/src/Umbraco.Core/Net/IUserAgentProvider.cs index d3f997c607..14246ea99e 100644 --- a/src/Umbraco.Core/Net/IUserAgentProvider.cs +++ b/src/Umbraco.Core/Net/IUserAgentProvider.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Net +namespace Umbraco.Net { public interface IUserAgentProvider { diff --git a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs index 06b3cc0cc9..a2ee650595 100644 --- a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Manifest; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Core.Compose { diff --git a/src/Umbraco.Infrastructure/Intall/InstallHelper.cs b/src/Umbraco.Infrastructure/Intall/InstallHelper.cs index 7aca4af09f..cf4b174cde 100644 --- a/src/Umbraco.Infrastructure/Intall/InstallHelper.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallHelper.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Cookie; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Models; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Persistence; using Umbraco.Core.Serialization; using Umbraco.Core.Services; diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs index a20637584f..d8986cacb7 100644 --- a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Umbraco.Core.Services; using Umbraco.Core.Configuration; using Umbraco.Core.Models.Packaging; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs index 0a6e67c829..4e14da30b7 100644 --- a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs @@ -2,7 +2,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Services; using Umbraco.Web.Install.Models; diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs index 052775d918..1558cdcf21 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs @@ -1,7 +1,7 @@ using Serilog.Core; using Serilog.Events; using System; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Core.Logging.Serilog.Enrichers { diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs index 59e0b8854f..f4e8f85281 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Hosting; using Umbraco.Core.Logging.Serilog.Enrichers; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Core.Logging.Serilog { diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs index 55b89d7996..bb77869e28 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Diagnostics; using Umbraco.Core.Hosting; using Umbraco.Core.IO; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Core.Logging.Serilog { diff --git a/src/Umbraco.Tests.Common/TestHelperBase.cs b/src/Umbraco.Tests.Common/TestHelperBase.cs index 76aa38e246..22177c1a50 100644 --- a/src/Umbraco.Tests.Common/TestHelperBase.cs +++ b/src/Umbraco.Tests.Common/TestHelperBase.cs @@ -12,7 +12,7 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Persistence; using Umbraco.Core.Serialization; using Umbraco.Core.Strings; diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index f1aa53694c..d218513ce3 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Diagnostics; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; using Umbraco.Tests.Common; diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 54cbec46e9..9cc9059499 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -21,7 +21,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Persistence; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Serialization; diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 9222f7e4ab..96576ac9a4 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -51,7 +51,7 @@ using Umbraco.Web.Templates; using Umbraco.Web.PropertyEditors; using Umbraco.Core.Dictionary; using Umbraco.Core.Models; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Request; using Umbraco.Core.Security; using Umbraco.Core.Services; diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs index e85f3cb3f9..3c65c24b1f 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Http; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Hosting; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Runtime; namespace Umbraco.Web.BackOffice.AspNetCore diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs index 520fe6b8aa..cee43757d8 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Http; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs index a27e378909..cafb02d367 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs index e7aba5e2de..0dca3edec8 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs @@ -1,7 +1,7 @@ using System.Threading; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs index a85970afaf..f9c9884704 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Http; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web/AspNet/AspNetIpResolver.cs b/src/Umbraco.Web/AspNet/AspNetIpResolver.cs index 026fb7ff12..7eaca54663 100644 --- a/src/Umbraco.Web/AspNet/AspNetIpResolver.cs +++ b/src/Umbraco.Web/AspNet/AspNetIpResolver.cs @@ -1,6 +1,6 @@ using System.Web; using Umbraco.Core; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web { diff --git a/src/Umbraco.Web/AspNet/AspNetSessionManager.cs b/src/Umbraco.Web/AspNet/AspNetSessionManager.cs index 9196cb137f..f81daadb0a 100644 --- a/src/Umbraco.Web/AspNet/AspNetSessionManager.cs +++ b/src/Umbraco.Web/AspNet/AspNetSessionManager.cs @@ -1,5 +1,5 @@ using System.Web; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Session; namespace Umbraco.Web.AspNet diff --git a/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs b/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs index 64988a20d9..245e8ea374 100644 --- a/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs @@ -1,6 +1,6 @@ using System.Threading; using System.Web; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.AspNet { diff --git a/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs b/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs index 4ba73292bb..bd37b62531 100644 --- a/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs +++ b/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs @@ -1,4 +1,4 @@ -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.AspNet { diff --git a/src/Umbraco.Web/Compose/AuditEventsComponent.cs b/src/Umbraco.Web/Compose/AuditEventsComponent.cs index d03f33d7ac..bd2520aa90 100644 --- a/src/Umbraco.Web/Compose/AuditEventsComponent.cs +++ b/src/Umbraco.Web/Compose/AuditEventsComponent.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 4424de6771..70083d47dd 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -11,7 +11,7 @@ using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Mapping; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.PackageActions; using Umbraco.Core.Packaging; using Umbraco.Core.PropertyEditors; diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 178a5c96d9..fe552650ea 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -14,7 +14,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Editors; using Umbraco.Core.Models.Packaging; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Packaging; using Umbraco.Core.Persistence; using Umbraco.Core.Services; diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 1d7fc8fd6e..2a746ffe4c 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -45,7 +45,7 @@ using Umbraco.Web.WebApi; using Umbraco.Web.PropertyEditors; using Umbraco.Examine; using Umbraco.Core.Models; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Request; using Umbraco.Core.Session; using Umbraco.Web.AspNet; diff --git a/src/Umbraco.Web/Security/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/AppBuilderExtensions.cs index 5416683eab..b3f950433c 100644 --- a/src/Umbraco.Web/Security/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/AppBuilderExtensions.cs @@ -17,7 +17,7 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Identity; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Composing; diff --git a/src/Umbraco.Web/Security/BackOfficeUserManager.cs b/src/Umbraco.Web/Security/BackOfficeUserManager.cs index 64b7054723..7de7ba37e5 100644 --- a/src/Umbraco.Web/Security/BackOfficeUserManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeUserManager.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Identity; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Models.Identity; diff --git a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs index ffa9a1c967..d393078cc6 100644 --- a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Services; using Umbraco.Core.Models.Membership; using Umbraco.Web.Composing; using System; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.Security.Providers { diff --git a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs index 9466dd6732..b099110911 100644 --- a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Security; using Umbraco.Core.Services; diff --git a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs index 8fcdc2c542..a0b7cdd225 100644 --- a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs +++ b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Mapping; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Services; using Umbraco.Web; using Umbraco.Web.Composing; From c988004762123e37a82fd2e8a2dfcfdefd1a5f3d Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:18:36 +1100 Subject: [PATCH 06/16] fixes test --- .../Runtimes/CoreRuntimeTests.cs | 42 ++----------------- 1 file changed, 3 insertions(+), 39 deletions(-) diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 44481666bc..08640f827a 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -136,48 +136,12 @@ 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) - { - return true; - } - */ - - //// 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 Configure(IRegister container) { - var factory = base.Configure(container); - _mainDom = factory.GetInstance(); - return factory; - } + container.Register(Lifetime.Singleton); - public override void Terminate() - { - base.Terminate(); + var factory = base.Configure(container); + return factory; } // runs with only one single component From 07966b522597970c3e010c600075bed7438cf28c Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:19:12 +1100 Subject: [PATCH 07/16] more unused code --- src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 08640f827a..8443de7b09 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) From 2d506c1fd0290e51c253177c304030530fab0fd2 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:23:31 +1100 Subject: [PATCH 08/16] Adds container test showing how we can pre-resolve a service and ensures its the same on that gets used. --- .../ContainerTests.cs | 34 ++++++++++++++++++- src/Umbraco.Tests.Integration/RuntimeTests.cs | 31 ++--------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/Umbraco.Tests.Integration/ContainerTests.cs b/src/Umbraco.Tests.Integration/ContainerTests.cs index f440944ab7..b439e32df1 100644 --- a/src/Umbraco.Tests.Integration/ContainerTests.cs +++ b/src/Umbraco.Tests.Integration/ContainerTests.cs @@ -1,4 +1,5 @@ -using LightInject; +using System.Threading.Tasks; +using LightInject; using LightInject.Microsoft.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -68,6 +69,37 @@ namespace Umbraco.Tests.Integration Assertions.AssertContainer(umbracoContainer.Container); } + [Explicit("This test just shows that resolving services from the container before the host is done resolves 2 different instances")] + [Test] + public async Task BuildServiceProvider_Before_Host_Is_Configured() + { + var umbracoContainer = RuntimeTests.GetUmbracoContainer(out var serviceProviderFactory); + + IHostApplicationLifetime lifetime1 = null; + + var hostBuilder = new HostBuilder() + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + // Resolve a service from the netcore container before the host has finished the ConfigureServices sequence + lifetime1 = services.BuildServiceProvider().GetRequiredService(); + + // Re-add as a callback, ensures its the same instance all the way through (hack) + services.AddSingleton(x => lifetime1); + }); + + var host = await hostBuilder.StartAsync(); + + var lifetime2 = host.Services.GetRequiredService(); + var lifetime3 = umbracoContainer.GetInstance(); + + lifetime1.StopApplication(); + Assert.IsTrue(lifetime1.ApplicationStopping.IsCancellationRequested); + Assert.AreEqual(lifetime1.ApplicationStopping.IsCancellationRequested, lifetime2.ApplicationStopping.IsCancellationRequested); + Assert.AreEqual(lifetime1.ApplicationStopping.IsCancellationRequested, lifetime3.ApplicationStopping.IsCancellationRequested); + + } + private class Foo { public Foo() diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index c9e0e94481..b12d02ca85 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -210,36 +210,9 @@ namespace Umbraco.Tests.Integration //Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); } - [Ignore("This test just shows that resolving services from the container before the host is done resolves 2 different instances")] - [Test] - public async Task BuildServiceProvider() + internal static LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory) { - var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); - - IHostApplicationLifetime lifetime1 = null; - - var hostBuilder = new HostBuilder() - .UseUmbraco(serviceProviderFactory) - .ConfigureServices((hostContext, services) => - { - // TODO: Try to re-register the service as a callback and see if it resolves to the same instance - - lifetime1 = services.BuildServiceProvider().GetRequiredService(); - }); - - var host = await hostBuilder.StartAsync(); - - var lifetime2 = host.Services.GetRequiredService(); - - lifetime1.StopApplication(); - Assert.IsTrue(lifetime1.ApplicationStopping.IsCancellationRequested); - Assert.AreEqual(lifetime1.ApplicationStopping.IsCancellationRequested, lifetime2.ApplicationStopping.IsCancellationRequested); - - } - - private LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory) - { - var container = new ServiceContainer(ContainerOptions.Default.Clone().WithMicrosoftSettings().WithAspNetCoreSettings()); + var container = UmbracoServiceProviderFactory.CreateServiceContainer(); serviceProviderFactory = new UmbracoServiceProviderFactory(container); var umbracoContainer = serviceProviderFactory.GetContainer(); return umbracoContainer; From 77ce21b0e32931cc99d9fbfa94a4d66d5f070bee Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:35:43 +1100 Subject: [PATCH 09/16] Adds notes/test about pre building the netcore container --- src/Umbraco.Tests.Integration/ContainerTests.cs | 8 ++++++++ .../AspNetCore/UmbracoCoreServiceCollectionExtensions.cs | 6 +++--- .../UmbracoWebsiteServiceCollectionExtensions.cs | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Tests.Integration/ContainerTests.cs b/src/Umbraco.Tests.Integration/ContainerTests.cs index b439e32df1..89cf2b5f7f 100644 --- a/src/Umbraco.Tests.Integration/ContainerTests.cs +++ b/src/Umbraco.Tests.Integration/ContainerTests.cs @@ -73,6 +73,14 @@ namespace Umbraco.Tests.Integration [Test] public async Task BuildServiceProvider_Before_Host_Is_Configured() { + // This is a test to show an anti-pattern used in netcore. This should be avoided in all cases if possible. + // There's a thread about this here: https://github.com/dotnet/aspnetcore/issues/14587 + // For some reason we are not being warned about this with our code analysis since we are using it + // in a couple of places but we should really try to see if we can avoid it. + // The test below shows how it could be possible to resolve an instance and then re-register it as a factory + // so that only one singleton instance is every created, but it's hacky and like Fowler says in that article + // it means the container won't be disposed, and maybe other services? not sure. + var umbracoContainer = RuntimeTests.GetUmbracoContainer(out var serviceProviderFactory); IHostApplicationLifetime lifetime1 = null; diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs index d283a7ffb1..20901822e3 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs @@ -29,6 +29,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// public static IServiceCollection AddUmbracoConfiguration(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 configuration = serviceProvider.GetService(); if (configuration == null) @@ -129,8 +130,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore out ILogger logger, out Configs configs, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment, out IBackOfficeInfo backOfficeInfo, out IProfiler profiler) { - // TODO: Resolving services before the Host is done configuring this way means that the services resolved - // are not going to be the same instances that are going to be used within the application! + // 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(); @@ -148,7 +148,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore 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()); 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(); From 926b0662e793bc32cb2f324ea7c8cdde8e6495c6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:39:36 +1100 Subject: [PATCH 10/16] another note --- src/Umbraco.Tests.Integration/ContainerTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Tests.Integration/ContainerTests.cs b/src/Umbraco.Tests.Integration/ContainerTests.cs index 89cf2b5f7f..945eeda2f0 100644 --- a/src/Umbraco.Tests.Integration/ContainerTests.cs +++ b/src/Umbraco.Tests.Integration/ContainerTests.cs @@ -80,6 +80,7 @@ namespace Umbraco.Tests.Integration // The test below shows how it could be possible to resolve an instance and then re-register it as a factory // so that only one singleton instance is every created, but it's hacky and like Fowler says in that article // it means the container won't be disposed, and maybe other services? not sure. + // In cases where we use it can we use IConfigureOptions? https://andrewlock.net/access-services-inside-options-and-startup-using-configureoptions/ var umbracoContainer = RuntimeTests.GetUmbracoContainer(out var serviceProviderFactory); From 1a8f422dce9442b1d725a97243169f488a894000 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:40:52 +1100 Subject: [PATCH 11/16] another note --- src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs | 1 + 1 file changed, 1 insertion(+) 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 { /// From a5d728cc51f5c026dd62fc7c9a10a07c33e52d85 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 18:21:44 +1100 Subject: [PATCH 12/16] Reduce the usage of BuildServiceProvider --- src/Umbraco.Tests.Integration/RuntimeTests.cs | 31 ++++++++++--------- .../UmbracoCoreServiceCollectionExtensions.cs | 22 ++++++------- src/Umbraco.Web.UI.NetCore/Startup.cs | 20 ++++++++++-- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index b12d02ca85..0e11a29b95 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -94,18 +94,18 @@ namespace Umbraco.Tests.Integration public async Task AddUmbracoCore() { var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); + var testHelper = new TestHelper(); var hostBuilder = new HostBuilder() .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { - var testHelper = new TestHelper(); - - AddRequiredNetCoreServices(services, testHelper); + var webHostEnvironment = testHelper.GetWebHostEnvironment(); + AddRequiredNetCoreServices(services, testHelper, webHostEnvironment); // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + services.AddUmbracoConfiguration(hostContext.Configuration); + services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly); }); var host = await hostBuilder.StartAsync(); @@ -138,12 +138,13 @@ namespace Umbraco.Tests.Integration var hostBuilder = new HostBuilder() .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => - { - AddRequiredNetCoreServices(services, testHelper); + { + var webHostEnvironment = testHelper.GetWebHostEnvironment(); + AddRequiredNetCoreServices(services, testHelper, webHostEnvironment); // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + services.AddUmbracoConfiguration(hostContext.Configuration); + services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly); }); var host = await hostBuilder.StartAsync(); @@ -178,11 +179,12 @@ namespace Umbraco.Tests.Integration .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { - AddRequiredNetCoreServices(services, testHelper); + var webHostEnvironment = testHelper.GetWebHostEnvironment(); + AddRequiredNetCoreServices(services, testHelper, webHostEnvironment); // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + services.AddUmbracoConfiguration(hostContext.Configuration); + services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly); }); var host = await hostBuilder.StartAsync(); @@ -223,11 +225,12 @@ namespace Umbraco.Tests.Integration /// /// /// - private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper) + /// + private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper, IWebHostEnvironment webHostEnvironment) { services.AddSingleton(x => testHelper.GetHttpContextAccessor()); // the generic host does add IHostEnvironment but not this one because we are not actually in a web context - services.AddSingleton(x => testHelper.GetWebHostEnvironment()); + services.AddSingleton(x => webHostEnvironment); } [RuntimeLevel(MinLevel = RuntimeLevel.Install)] diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs index 20901822e3..d747cb349a 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs @@ -26,14 +26,11 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// Adds the Umbraco Configuration requirements /// /// + /// /// - public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services) + public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services, IConfiguration configuration) { - // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured - 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); @@ -49,25 +46,27 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// Adds the Umbraco Back Core requirements /// /// + /// /// - 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; - return services.AddUmbracoCore(umbContainer, Assembly.GetEntryAssembly()); + return services.AddUmbracoCore(webHostEnvironment, umbContainer, Assembly.GetEntryAssembly()); } /// /// Adds the Umbraco Back Core requirements /// /// + /// /// /// /// - public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IRegister umbContainer, Assembly entryAssembly) + 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)); @@ -77,7 +76,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore // we resolve it before the host finishes configuring in the call to CreateCompositionRoot services.AddSingleton(); - CreateCompositionRoot(services, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler); + 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); @@ -126,7 +125,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore return coreRuntime; } - private static void CreateCompositionRoot(IServiceCollection services, + private static void 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) { @@ -134,7 +133,6 @@ namespace Umbraco.Web.BackOffice.AspNetCore var serviceProvider = services.BuildServiceProvider(); var httpContextAccessor = serviceProvider.GetRequiredService(); - var webHostEnvironment = serviceProvider.GetRequiredService(); configs = serviceProvider.GetService(); if (configs == null) diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index ab8c6e021c..2753676452 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -16,13 +16,29 @@ namespace Umbraco.Web.UI.BackOffice { public class Startup { + private readonly IWebHostEnvironment _webHostEnvironment; + private readonly IConfiguration _config; + + /// + /// Constructor + /// + /// + /// + /// + /// Only a few services are possible to be injected here https://github.com/dotnet/aspnetcore/issues/9337 + /// + public Startup(IWebHostEnvironment webHostEnvironment, IConfiguration config) + { + _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.AddUmbracoCore(); + services.AddUmbracoConfiguration(_config); + services.AddUmbracoCore(_webHostEnvironment); services.AddUmbracoWebsite(); } From fee1f6f0ab5d56470e7387635bb7a63f9991b137 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Thu, 26 Mar 2020 15:30:25 +1100 Subject: [PATCH 13/16] Update src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs Co-Authored-By: Bjarke Berg --- .../Implementations/HostBuilderExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs index b0b664484b..9f1d0b21c4 100644 --- a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs @@ -16,7 +16,7 @@ namespace Umbraco.Tests.Integration.Implementations { // Need to register SqlClient manually // TODO: Move this to someplace central - DbProviderFactories.RegisterFactory("System.Data.SqlClient", SqlClientFactory.Instance); + DbProviderFactories.RegisterFactory(Constants.DbProviderNames.SqlServer, SqlClientFactory.Instance); hostBuilder.ConfigureAppConfiguration(x => { From 9bb999728867ab9cfc350dc89b1c2a7824c87e3b Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Thu, 26 Mar 2020 15:31:27 +1100 Subject: [PATCH 14/16] Update src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs Co-Authored-By: Bjarke Berg --- .../Implementations/HostBuilderExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs index 9f1d0b21c4..6be56a547b 100644 --- a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.Integration.Implementations x.AddInMemoryCollection(new[] { - new KeyValuePair("ConnectionStrings:umbracoDbDSN", instance.GetConnectionString(dbName)) + new KeyValuePair($"ConnectionStrings:{Constants.System.UmbracoConnectionName}", instance.GetConnectionString(dbName)) }); }); return hostBuilder; From 29293bd25a67efeb0f8cca0cf6a7e41b0fe9cde9 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Thu, 26 Mar 2020 15:32:39 +1100 Subject: [PATCH 15/16] Update src/Umbraco.Tests.Integration/Implementations/TestHelper.cs Co-Authored-By: Bjarke Berg --- src/Umbraco.Tests.Integration/Implementations/TestHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index d218513ce3..ccbf7b03d4 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Integration.Implementations public IWebHostEnvironment GetWebHostEnvironment() => _hostEnvironment; - public override IDbProviderFactoryCreator DbProviderFactoryCreator => new SqlServerDbProviderFactoryCreator("System.Data.SqlClient", DbProviderFactories.GetFactory); + public override IDbProviderFactoryCreator DbProviderFactoryCreator => new SqlServerDbProviderFactoryCreator(Constants.DbProviderNames.SqlServer, DbProviderFactories.GetFactory); public override IBulkSqlInsertProvider BulkSqlInsertProvider => new SqlServerBulkSqlInsertProvider(); From f24cae51d885ed7e71e0f94be8334246224f1e50 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 26 Mar 2020 15:39:20 +1100 Subject: [PATCH 16/16] Renames IHostingEnvironmentLifetime to IApplicationShutdownRegistry --- ...ime.cs => IApplicationShutdownRegistry.cs} | 2 +- src/Umbraco.Core/Runtime/IMainDom.cs | 2 +- src/Umbraco.Core/Runtime/MainDom.cs | 9 ++++--- src/Umbraco.Core/SimpleMainDom.cs | 2 +- ...aseServerRegistrarAndMessengerComponent.cs | 2 +- .../Runtime/CoreRuntime.cs | 25 ++++--------------- .../Scheduling/BackgroundTaskRunner.cs | 10 ++++---- .../Scheduling/SchedulerComponent.cs | 4 +-- .../Search/BackgroundIndexRebuilder.cs | 4 +-- .../PureLiveModelFactory.cs | 4 +-- src/Umbraco.Tests.Common/TestHelperBase.cs | 2 +- .../Implementations/HostBuilderExtensions.cs | 1 + .../Implementations/TestHelper.cs | 6 ++--- .../XmlPublishedSnapshotService.cs | 6 ++--- .../LegacyXmlPublishedCache/XmlStore.cs | 6 ++--- .../Runtimes/CoreRuntimeTests.cs | 2 +- .../Scheduling/BackgroundTaskRunnerTests.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestHelper.cs | 6 ++--- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- ... AspNetCoreApplicationShutdownRegistry.cs} | 4 +-- .../AspNetCore/AspNetCoreComposer.cs | 2 +- ...oBackOfficeApplicationBuilderExtensions.cs | 6 ++--- ...s => AspNetApplicationShutdownRegistry.cs} | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 2 +- 24 files changed, 50 insertions(+), 63 deletions(-) rename src/Umbraco.Core/Hosting/{IHostingEnvironmentLifetime.cs => IApplicationShutdownRegistry.cs} (78%) rename src/Umbraco.Web.BackOffice/AspNetCore/{AspNetCoreHostingEnvironmentShutdown.cs => AspNetCoreApplicationShutdownRegistry.cs} (90%) rename src/Umbraco.Web/AspNet/{AspNetHostingLifetime.cs => AspNetApplicationShutdownRegistry.cs} (94%) diff --git a/src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs b/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs similarity index 78% rename from src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs rename to src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs index 891cedad20..93441f1a47 100644 --- a/src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs +++ b/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs @@ -1,6 +1,6 @@ namespace Umbraco.Core.Hosting { - public interface IHostingEnvironmentLifetime + public interface IApplicationShutdownRegistry { void RegisterObject(IRegisteredObject registeredObject); void UnregisterObject(IRegisteredObject registeredObject); diff --git a/src/Umbraco.Core/Runtime/IMainDom.cs b/src/Umbraco.Core/Runtime/IMainDom.cs index 1b7f09bc89..93a560ff7d 100644 --- a/src/Umbraco.Core/Runtime/IMainDom.cs +++ b/src/Umbraco.Core/Runtime/IMainDom.cs @@ -26,7 +26,7 @@ namespace Umbraco.Core /// /// /// - bool Acquire(IHostingEnvironmentLifetime hostingEnvironment); + 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 0a4a250aa6..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 IHostingEnvironmentLifetime _hostingEnvironment; + private IApplicationShutdownRegistry _hostingEnvironment; private readonly IMainDomLock _mainDomLock; // our own lock for local consistency @@ -50,9 +50,10 @@ namespace Umbraco.Core.Runtime #endregion - public bool Acquire(IHostingEnvironmentLifetime hostingEnvironment) + public bool Acquire(IApplicationShutdownRegistry hostingEnvironment) { - _hostingEnvironment = hostingEnvironment; + _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); + return LazyInitializer.EnsureInitialized(ref _isMainDom, ref _isInitialized, ref _locko, () => { hostingEnvironment.RegisterObject(this); @@ -199,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/SimpleMainDom.cs b/src/Umbraco.Core/SimpleMainDom.cs index 52ed6c1d91..e6bdda67d7 100644 --- a/src/Umbraco.Core/SimpleMainDom.cs +++ b/src/Umbraco.Core/SimpleMainDom.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core public bool IsMainDom { get; private set; } = true; // always acquire - public bool Acquire(IHostingEnvironmentLifetime hostingEnvironment) => true; + public bool Acquire(IApplicationShutdownRegistry hostingEnvironment) => true; /// public bool Register(Action release, int weight = 100) diff --git a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs index 4e183b9211..6c745f3877 100644 --- a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs @@ -99,7 +99,7 @@ namespace Umbraco.Web.Compose IServerMessenger serverMessenger, IServerRegistrationService registrationService, ILogger logger, - IHostingEnvironmentLifetime hostingEnvironment, + IApplicationShutdownRegistry hostingEnvironment, IRequestAccessor requestAccessor) { _runtime = runtime; diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index 89ec036607..139e9e9b67 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -28,21 +28,6 @@ namespace Umbraco.Core.Runtime private readonly IGlobalSettings _globalSettings; private readonly IConnectionStrings _connectionStrings; - - /// - /// Constructor - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// public CoreRuntime( Configs configs, IUmbracoVersion umbracoVersion, @@ -251,12 +236,12 @@ namespace Umbraco.Core.Runtime // run handlers RuntimeOptions.DoRuntimeEssentials(_factory); - var hostingEnvironmentLifetime = _factory.TryGetInstance(); + var hostingEnvironmentLifetime = _factory.TryGetInstance(); if (hostingEnvironmentLifetime == null) - throw new InvalidOperationException($"An instance of {typeof(IHostingEnvironmentLifetime)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(Start)}"); + 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()); + AcquireMainDom(MainDom, _factory.GetInstance()); // create & initialize the components _components = _factory.GetInstance(); @@ -287,13 +272,13 @@ namespace Umbraco.Core.Runtime IOHelper.SetRootDirectory(path); } - private bool AcquireMainDom(IMainDom mainDom, IHostingEnvironmentLifetime hostingEnvironmentLifetime) + private bool AcquireMainDom(IMainDom mainDom, IApplicationShutdownRegistry applicationShutdownRegistry) { using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Acquired.")) { try { - return mainDom.Acquire(hostingEnvironmentLifetime); + return mainDom.Acquire(applicationShutdownRegistry); } catch { diff --git a/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs b/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs index 31884992f7..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 IHostingEnvironmentLifetime _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, IHostingEnvironmentLifetime 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, IHostingEnvironmentLifetime 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, IHostingEnvironmentLifetime 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, IHostingEnvironmentLifetime 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/SchedulerComponent.cs b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs index c867d81d69..30d0bc7e4a 100644 --- a/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs +++ b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web.Scheduling private readonly IContentService _contentService; private readonly IAuditService _auditService; private readonly IProfilingLogger _logger; - private readonly IHostingEnvironmentLifetime _hostingEnvironment; + private readonly IApplicationShutdownRegistry _hostingEnvironment; private readonly IScopeProvider _scopeProvider; private readonly HealthCheckCollection _healthChecks; private readonly HealthCheckNotificationMethodCollection _notifications; @@ -57,7 +57,7 @@ namespace Umbraco.Web.Scheduling IContentService contentService, IAuditService auditService, HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications, IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger, - IHostingEnvironmentLifetime hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig, + IApplicationShutdownRegistry hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig, IIOHelper ioHelper, IServerMessenger serverMessenger, IRequestAccessor requestAccessor, ILoggingSettings loggingSettings, IKeepAliveSettings keepAliveSettings) { diff --git a/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs b/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs index fa697a4743..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 IHostingEnvironmentLifetime _hostingEnvironment; + private readonly IApplicationShutdownRegistry _hostingEnvironment; private static BackgroundTaskRunner _rebuildOnStartupRunner; - public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IHostingEnvironmentLifetime hostingEnvironment, IndexRebuilder indexRebuilder) + public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IApplicationShutdownRegistry hostingEnvironment, IndexRebuilder indexRebuilder) { _mainDom = mainDom; _logger = logger; diff --git a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs index 3c189cc045..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 IHostingEnvironmentLifetime _hostingLifetime; + private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly IIOHelper _ioHelper; private readonly ModelsGenerationError _errors; @@ -51,7 +51,7 @@ namespace Umbraco.ModelsBuilder.Embedded IProfilingLogger logger, IModelsBuilderConfig config, IHostingEnvironment hostingEnvironment, - IHostingEnvironmentLifetime hostingLifetime, + IApplicationShutdownRegistry hostingLifetime, IIOHelper ioHelper) { _umbracoServices = umbracoServices; diff --git a/src/Umbraco.Tests.Common/TestHelperBase.cs b/src/Umbraco.Tests.Common/TestHelperBase.cs index 22177c1a50..67108833c3 100644 --- a/src/Umbraco.Tests.Common/TestHelperBase.cs +++ b/src/Umbraco.Tests.Common/TestHelperBase.cs @@ -128,7 +128,7 @@ namespace Umbraco.Tests.Common } public abstract IHostingEnvironment GetHostingEnvironment(); - public abstract IHostingEnvironmentLifetime GetHostingEnvironmentLifetime(); + public abstract IApplicationShutdownRegistry GetHostingEnvironmentLifetime(); public abstract IIpResolver GetIpResolver(); diff --git a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs index 6be56a547b..60cac26349 100644 --- a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs @@ -5,6 +5,7 @@ using System.Data.SqlClient; using System.IO; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; +using Umbraco.Core; using Umbraco.Tests.Integration.Testing; namespace Umbraco.Tests.Integration.Implementations diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index ccbf7b03d4..4a986fa35a 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Integration.Implementations { private IBackOfficeInfo _backOfficeInfo; private readonly IHostingEnvironment _hostingEnvironment; - private readonly IHostingEnvironmentLifetime _hostingLifetime; + private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly IIpResolver _ipResolver; private readonly IWebHostEnvironment _hostEnvironment; private readonly IHttpContextAccessor _httpContextAccessor; @@ -46,7 +46,7 @@ namespace Umbraco.Tests.Integration.Implementations _hostEnvironment, _httpContextAccessor); - _hostingLifetime = new AspNetCoreHostingEnvironmentLifetime(Mock.Of()); + _hostingLifetime = new AspNetCoreApplicationShutdownRegistry(Mock.Of()); Logger = new ProfilingLogger(new ConsoleLogger(new MessageTemplates()), Profiler); } @@ -77,7 +77,7 @@ namespace Umbraco.Tests.Integration.Implementations } public override IHostingEnvironment GetHostingEnvironment() => _hostingEnvironment; - public override IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() => _hostingLifetime; + public override IApplicationShutdownRegistry GetHostingEnvironmentLifetime() => _hostingLifetime; public override IIpResolver GetIpResolver() => _ipResolver; diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs index 5eb57b6ca6..bf7cbe40c4 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs @@ -41,7 +41,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private readonly IEntityXmlSerializer _entitySerializer; private readonly IVariationContextAccessor _variationContextAccessor; private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private readonly IHostingEnvironmentLifetime _hostingLifetime; + private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly IHostingEnvironment _hostingEnvironment; #region Constructors @@ -58,7 +58,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache ILogger logger, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, - IHostingEnvironmentLifetime hostingLifetime, + IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper, ISiteDomainHelper siteDomainHelper, IEntityXmlSerializer entitySerializer, @@ -86,7 +86,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache ILogger logger, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, - IHostingEnvironmentLifetime hostingLifetime, + IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper, ISiteDomainHelper siteDomainHelper, IEntityXmlSerializer entitySerializer, diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs index b051682ed7..dadf8b6824 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs @@ -46,7 +46,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private readonly IMediaRepository _mediaRepository; private readonly IMemberRepository _memberRepository; private readonly IEntityXmlSerializer _entitySerializer; - private readonly IHostingEnvironmentLifetime _hostingLifetime; + private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly IShortStringHelper _shortStringHelper; private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; private readonly PublishedContentTypeCache _contentTypeCache; @@ -65,7 +65,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache /// /// 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, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper 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) { } @@ -74,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, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper) + bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper) { if (testing == false) EnsureConfigurationIsValid(); diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 8443de7b09..6ccb2c3b35 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -133,7 +133,7 @@ namespace Umbraco.Tests.Runtimes public override IFactory Configure(IRegister container) { - container.Register(Lifetime.Singleton); + container.Register(Lifetime.Singleton); var factory = base.Configure(container); return factory; diff --git a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs index 18eb3d19a4..2291584f66 100644 --- a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs +++ b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs @@ -19,7 +19,7 @@ namespace Umbraco.Tests.Scheduling public class BackgroundTaskRunnerTests { private ILogger _logger; - private IHostingEnvironmentLifetime _hostingEnvironment; + private IApplicationShutdownRegistry _hostingEnvironment; [OneTimeSetUp] public void InitializeFixture() diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 9cc9059499..11393e3e6b 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -62,8 +62,8 @@ namespace Umbraco.Tests.TestHelpers public override IHostingEnvironment GetHostingEnvironment() => new AspNetHostingEnvironment(SettingsForTests.GetDefaultHostingSettings()); - public override IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() - => new AspNetHostingLifetime(); + public override IApplicationShutdownRegistry GetHostingEnvironmentLifetime() + => new AspNetApplicationShutdownRegistry(); public override IIpResolver GetIpResolver() => new AspNetIpResolver(); @@ -323,7 +323,7 @@ namespace Umbraco.Tests.TestHelpers public static IHostingEnvironment GetHostingEnvironment() => _testHelperInternal.GetHostingEnvironment(); - public static IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() => _testHelperInternal.GetHostingEnvironmentLifetime(); + public static IApplicationShutdownRegistry GetHostingEnvironmentLifetime() => _testHelperInternal.GetHostingEnvironmentLifetime(); public static IIpResolver GetIpResolver() => _testHelperInternal.GetIpResolver(); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 96576ac9a4..0345aab2da 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -140,7 +140,7 @@ namespace Umbraco.Tests.Testing protected virtual IProfilingLogger ProfilingLogger => Factory.GetInstance(); protected IHostingEnvironment HostingEnvironment { get; } = new AspNetHostingEnvironment(TestHelpers.SettingsForTests.GetDefaultHostingSettings()); - protected IHostingEnvironmentLifetime HostingLifetime { get; } = new AspNetHostingLifetime(); + 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.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs similarity index 90% rename from src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs rename to src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs index 3726e50e3b..92af822836 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs @@ -7,13 +7,13 @@ using Umbraco.Core.Hosting; namespace Umbraco.Web.BackOffice.AspNetCore { - public class AspNetCoreHostingEnvironmentLifetime : IHostingEnvironmentLifetime + public class AspNetCoreApplicationShutdownRegistry : IApplicationShutdownRegistry { private readonly IHostApplicationLifetime _hostApplicationLifetime; private readonly ConcurrentDictionary _registeredObjects = new ConcurrentDictionary(); - public AspNetCoreHostingEnvironmentLifetime(IHostApplicationLifetime hostApplicationLifetime) + public AspNetCoreApplicationShutdownRegistry(IHostApplicationLifetime hostApplicationLifetime) { _hostApplicationLifetime = hostApplicationLifetime; } diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs index 3c65c24b1f..fc38e429a0 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore // Our own netcore implementations composition.RegisterUnique(); - composition.RegisterUnique(); + composition.RegisterUnique(); } } } diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs index feb122a48b..770f4b883f 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore 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 hostLifetime = app.ApplicationServices.GetRequiredService(); var runtime = app.ApplicationServices.GetRequiredService(); var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime); hostLifetime.RegisterObject(runtimeShutdown); @@ -43,7 +43,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// private class CoreRuntimeShutdown : IRegisteredObject { - public CoreRuntimeShutdown(IRuntime runtime, IHostingEnvironmentLifetime hostLifetime) + public CoreRuntimeShutdown(IRuntime runtime, IApplicationShutdownRegistry hostLifetime) { _runtime = runtime; _hostLifetime = hostLifetime; @@ -51,7 +51,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore private bool _completed = false; private readonly IRuntime _runtime; - private readonly IHostingEnvironmentLifetime _hostLifetime; + private readonly IApplicationShutdownRegistry _hostLifetime; public void Stop(bool immediate) { diff --git a/src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs b/src/Umbraco.Web/AspNet/AspNetApplicationShutdownRegistry.cs similarity index 94% rename from src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs rename to src/Umbraco.Web/AspNet/AspNetApplicationShutdownRegistry.cs index 316ecb8389..dbd6e9e834 100644 --- a/src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs +++ b/src/Umbraco.Web/AspNet/AspNetApplicationShutdownRegistry.cs @@ -6,7 +6,7 @@ using IRegisteredObject = Umbraco.Core.IRegisteredObject; namespace Umbraco.Web.Hosting { - public class AspNetHostingLifetime : IHostingEnvironmentLifetime + public class AspNetApplicationShutdownRegistry : IApplicationShutdownRegistry { private readonly ConcurrentDictionary _registeredObjects = new ConcurrentDictionary(); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index ce08d5498d..4b4f06ad2a 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -134,7 +134,7 @@ - +