diff --git a/src/Umbraco.Core/ApplicationContext.cs b/src/Umbraco.Core/ApplicationContext.cs deleted file mode 100644 index 3e8982d8a7..0000000000 --- a/src/Umbraco.Core/ApplicationContext.cs +++ /dev/null @@ -1,333 +0,0 @@ -using System; -using System.Configuration; -using System.Threading; -using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using Umbraco.Core.Services; -using Umbraco.Core.Sync; - -namespace Umbraco.Core -{ - /// - /// Represents the Umbraco application context. - /// - /// Only one singleton instance per running Umbraco application (AppDomain) - public class ApplicationContext : IDisposable - { - private volatile bool _disposed; - private readonly ReaderWriterLockSlim _disposalLocker = new ReaderWriterLockSlim(); - private bool _isReady; - readonly ManualResetEventSlim _isReadyEvent = new ManualResetEventSlim(false); - private DatabaseContext _databaseContext; - private ServiceContext _services; - private Lazy _configured; - - // ReSharper disable once InconsistentNaming - internal string _umbracoApplicationUrl; - - /// - /// Initializes a new instance of the class. - /// - /// A database context. - /// A service context. - /// A cache helper. - /// A logger. - public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, ProfilingLogger logger) - { - if (dbContext == null) throw new ArgumentNullException(nameof(dbContext)); - if (serviceContext == null) throw new ArgumentNullException(nameof(serviceContext)); - if (cache == null) throw new ArgumentNullException(nameof(cache)); - if (logger == null) throw new ArgumentNullException(nameof(logger)); - - _databaseContext = dbContext; - _services = serviceContext; - ApplicationCache = cache; - ProfilingLogger = logger; - - Initialize(); - } - - /// - /// Initializes a new instance of the class. - /// - /// A cache helper. - /// A logger. - /// For Unit Tests only. - public ApplicationContext(CacheHelper cache, ProfilingLogger logger) - { - if (cache == null) throw new ArgumentNullException(nameof(cache)); - if (logger == null) throw new ArgumentNullException(nameof(logger)); - - ApplicationCache = cache; - ProfilingLogger = logger; - - Initialize(); - } - - /// - /// Gets the current global application context. - /// - public static ApplicationContext Current => DependencyInjection.Current.ApplicationContext; // fixme - obsolete - - /// - /// Returns the application wide cache accessor - /// - /// - /// Any caching that is done in the application (app wide) should be done through this property - /// - public CacheHelper ApplicationCache { get; private set; } - - /// - /// Gets the profiling logger. - /// - public ProfilingLogger ProfilingLogger { get; } - - /// - /// Gets the MainDom. - /// - internal MainDom MainDom { get; private set; } - - /// - /// Gets a value indicating whether the application is configured. - /// - /// Meaning: installed and no need to upgrade anything. - public virtual bool IsConfigured => _configured.Value; - - /// - /// Gets a value indicating whether the application is ready. - /// - /// Meaning: ready to run, boot has completed, though maybe the application is not configured. - /// IsReady is set to true by the boot manager once it has successfully booted. The original - /// Umbraco module checked on content.Instance, now the boot task that sets the content - /// store ensures that it is ready. - /// - public bool IsReady - { - get - { - return _isReady; - } - internal set - { - if (IsReady) - throw new Exception("ApplicationContext has already been initialized."); - if (value == false) - throw new Exception("Value must be true."); - - _isReady = true; - _isReadyEvent.Set(); - } - } - - /// - /// Blocks until the application is ready. - /// - /// The time to wait, or -1 to wait indefinitely. - /// A value indicating whether the application is ready. - public bool WaitForReady(int timeout) - { - return _isReadyEvent.WaitHandle.WaitOne(timeout); - } - - /// - /// Gets a value indicating whether the application is upgrading. - /// - /// Meaning: the database is configured and the database context has access to an existing Umbraco schema, - /// however we are not 'configured' because we still need to upgrade. - public bool IsUpgrading - { - get - { - if (IsConfigured // configured already - || DatabaseContext == null // no database context - || DatabaseContext.IsDatabaseConfigured == false // database is not configured - || DatabaseContext.CanConnect == false) // database cannot connect - return false; - - // upgrading if we have some valid tables (else, no schema, need to install) - var schemaresult = DatabaseContext.ValidateDatabaseSchema(); - return schemaresult.ValidTables.Count > 0; - } - } - - /// - /// Gets the application Url. - /// - /// - /// The application url is the url that should be used by services to talk to the application, - /// eg keep alive or scheduled publishing services. It must exist on a global context because - /// some of these services may not run within a web context. - /// The format of the application url is: - /// - has a scheme (http or https) - /// - has the SystemDirectories.Umbraco path - /// - does not end with a slash - /// It is initialized on the first request made to the server, by UmbracoModule.EnsureApplicationUrl: - /// - if umbracoSettings:settings/web.routing/@umbracoApplicationUrl is set, use the value (new setting) - /// - if umbracoSettings:settings/scheduledTasks/@baseUrl is set, use the value (backward compatibility) - /// - otherwise, use the url of the (first) request. - /// Not locking, does not matter if several threads write to this. - /// See also issues: - /// - http://issues.umbraco.org/issue/U4-2059 - /// - http://issues.umbraco.org/issue/U4-6788 - /// - http://issues.umbraco.org/issue/U4-5728 - /// - http://issues.umbraco.org/issue/U4-5391 - /// - internal string UmbracoApplicationUrl - { - get - { - ApplicationUrlHelper.EnsureApplicationUrl(this); - return _umbracoApplicationUrl; - } - } - - private void Initialize() - { - MainDom = new MainDom(ProfilingLogger.Logger); - MainDom.Acquire(); - - ResetConfigured(); - } - - /// - /// Resets the IsConfigured value, which will then be discovered again. - /// - /// For Unit Tests usage, though it is harmless. - public void ResetConfigured() - { - // create the lazy value to resolve whether or not the application is 'configured' - // meaning: installed and no need to upgrade anything - _configured = new Lazy(() => - { - try - { - var configStatus = ConfigurationStatus; // the value in the web.config - var currentVersion = UmbracoVersion.GetSemanticVersion(); // the hard-coded current version of the binaries that are executing - - // if we have no value in web.config or value differs, we are not configured yet - if (string.IsNullOrWhiteSpace(configStatus) || configStatus != currentVersion) - { - ProfilingLogger.Logger.Debug($"CurrentVersion different from configStatus: '{currentVersion.ToSemanticString()}','{configStatus}'."); - return false; - } - - // versions match, now look for database state and migrations - // which requires that we do have a database that we can connect to - if (DatabaseContext.IsDatabaseConfigured == false || DatabaseContext.CanConnect == false) - { - ProfilingLogger.Logger.Debug("Database is not configured, or could not connect to the database."); - return false; - } - - // look for a migration entry for the current version - var entry = Services.MigrationEntryService.FindEntry(GlobalSettings.UmbracoMigrationName, UmbracoVersion.GetSemanticVersion()); - if (entry != null) - return true; // all clear! - - // even though the versions match, the db has not been properly upgraded - ProfilingLogger.Logger.Debug($"The migration for version: '{currentVersion.ToSemanticString()} has not been executed, there is no record in the database."); - return false; - } - catch (Exception ex) - { - LogHelper.Error("Error determining if application is configured, returning false.", ex); - return false; - } - }); - } - - // gets the configuration status, ie the version that's in web.config - private string ConfigurationStatus - { - get - { - try - { - return ConfigurationManager.AppSettings["umbracoConfigurationStatus"]; - } - catch - { - return string.Empty; - } - } - } - - /// - /// Gets the current database context. - /// - public DatabaseContext DatabaseContext - { - get - { - if (_databaseContext == null) - throw new InvalidOperationException("The DatabaseContext has not been set on the ApplicationContext."); - return _databaseContext; - } - // INTERNAL FOR UNIT TESTS - internal set { _databaseContext = value; } - } - - /// - /// Gets the current service context. - /// - public ServiceContext Services - { - get - { - if (_services == null) - throw new InvalidOperationException("The ServiceContext has not been set on the ApplicationContext."); - return _services; - } - // INTERNAL FOR UNIT TESTS - internal set { _services = value; } - } - - /// - /// Gets the server role. - /// - /// - internal ServerRole GetCurrentServerRole() - { - return DependencyInjection.Current.ServerRegistrar.GetCurrentServerRole(); - } - - /// - /// Disposes the application context. - /// - /// Do not this object if you require the Umbraco application to run. Disposing this object - /// is generally used for unit testing and when your application is shutting down after you have booted Umbraco. - /// - void IDisposable.Dispose() - { - if (_disposed) return; - - using (new WriteLock(_disposalLocker)) - { - // double check... bah... - if (_disposed) return; - - // clear the cache - if (ApplicationCache != null) - { - ApplicationCache.RuntimeCache.ClearAllCache(); - ApplicationCache.IsolatedRuntimeCache.ClearAllCaches(); - } - - // reset the instance objects - ApplicationCache = null; - if (_databaseContext != null) //need to check the internal field here - { - if (DatabaseContext.IsDatabaseConfigured) - DatabaseContext.Database?.Dispose(); - } - - DatabaseContext = null; - Services = null; - _isReady = false; //set the internal field - - _disposed = true; - } - } - } -} diff --git a/src/Umbraco.Core/ApplicationEventHandler.cs b/src/Umbraco.Core/ApplicationEventHandler.cs index 8d97baac95..47035f80dd 100644 --- a/src/Umbraco.Core/ApplicationEventHandler.cs +++ b/src/Umbraco.Core/ApplicationEventHandler.cs @@ -1,3 +1,11 @@ +using System; +using System.Linq; +using LightInject; +using Umbraco.Core.Components; +using Umbraco.Core.DependencyInjection; +using Umbraco.Core.Plugins; +using Umbraco.Core.Services; + namespace Umbraco.Core { /// @@ -5,115 +13,147 @@ namespace Umbraco.Core /// /// /// Allows you to override the methods that you would like to execute code for: ApplicationInitialized, ApplicationStarting, ApplicationStarted. - /// + /// /// By default none of these methods will execute if the Umbraco application is not configured or if the Umbraco database is not configured, however - /// if you need these methods to execute even if either of these are not configured you can override the properties: + /// if you need these methods to execute even if either of these are not configured you can override the properties: /// ExecuteWhenApplicationNotConfigured and ExecuteWhenDatabaseNotConfigured /// + // fixme - kill.kill.kill public abstract class ApplicationEventHandler : IApplicationEventHandler { - public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication) { - if (ShouldExecute(applicationContext)) - { - ApplicationInitialized(umbracoApplication, applicationContext); - } + if (ShouldExecute()) ApplicationInitialized(umbracoApplication); } - public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication) { - if (ShouldExecute(applicationContext)) - { - ApplicationStarting(umbracoApplication, applicationContext); - } + if (ShouldExecute()) ApplicationStarting(umbracoApplication); } - public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication) { - if (ShouldExecute(applicationContext)) - { - ApplicationStarted(umbracoApplication, applicationContext); - } + if (ShouldExecute()) ApplicationStarted(umbracoApplication); } /// /// Overridable method to execute when the ApplicationContext is created and other static objects that require initialization have been setup /// /// - /// - protected virtual void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) - { - - } + protected virtual void ApplicationInitialized(UmbracoApplicationBase umbracoApplication) + { } /// /// Overridable method to execute when All resolvers have been initialized but resolution is not frozen so they can be modified in this method /// /// - /// - protected virtual void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) - { - - } + protected virtual void ApplicationStarting(UmbracoApplicationBase umbracoApplication) + { } /// /// Overridable method to execute when Bootup is completed, this allows you to perform any other bootup logic required for the application. /// Resolution is frozen so now they can be used to resolve instances. /// /// - /// - protected virtual void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) - { + protected virtual void ApplicationStarted(UmbracoApplicationBase umbracoApplication) + { } + private bool ShouldExecute() + { + var level = Current.RuntimeState.Level; + + switch (Current.RuntimeState.Level) + { + case RuntimeLevel.Unknown: + case RuntimeLevel.Failed: + case RuntimeLevel.Boot: + return false; + case RuntimeLevel.Install: + case RuntimeLevel.Upgrade: + // sort-of equivalent I assume? + //if (!applicationContext.IsConfigured && ExecuteWhenApplicationNotConfigured) + if (ExecuteWhenApplicationNotConfigured) + return true; + //if (!applicationContext.DatabaseContext.IsDatabaseConfigured && ExecuteWhenDatabaseNotConfigured) + if (level == RuntimeLevel.Install && ExecuteWhenDatabaseNotConfigured) + return true; + return false; + case RuntimeLevel.Run: + //if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured) + return true; + default: + throw new NotSupportedException($"Invalid runtime level {level}"); + } } /// - /// Determine if the methods should execute based on the configuration status of the application. - /// - /// - /// - private bool ShouldExecute(ApplicationContext applicationContext) - { - if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured) - { - return true; - } - - if (!applicationContext.IsConfigured && ExecuteWhenApplicationNotConfigured) - { - return true; - } - - if (!applicationContext.DatabaseContext.IsDatabaseConfigured && ExecuteWhenDatabaseNotConfigured) - { - return true; - } - return false; - } - - /// - /// A flag to determine if the overridable methods for this class will execute even if the + /// A flag to determine if the overridable methods for this class will execute even if the /// Umbraco application is not configured /// /// /// An Umbraco Application is not configured when it requires a new install or upgrade. When the latest version in the /// assembly does not match the version in the config. /// - protected virtual bool ExecuteWhenApplicationNotConfigured - { - get { return false; } - } + protected virtual bool ExecuteWhenApplicationNotConfigured => false; /// - /// A flag to determine if the overridable methods for this class will execute even if the + /// A flag to determine if the overridable methods for this class will execute even if the /// Umbraco database is not configured /// /// /// The Umbraco database is not configured when we cannot connect to the database or when the database tables are not installed. /// - protected virtual bool ExecuteWhenDatabaseNotConfigured + protected virtual bool ExecuteWhenDatabaseNotConfigured => false; + } + + // that *could* replace CoreRuntime mess almost entirely + // but what about what's in WebRuntime? + + [DisableComponent] // disabled for now, breaks + public class ApplicationEventHandlerComponent : UmbracoComponentBase, IUmbracoCoreComponent + { + public override void Compose(ServiceContainer container) { - get { return false; } + base.Compose(container); + + // assuming we don't do anything in Compose? or is this where we should create the handlers? + } + + public void Initialize(PluginManager pluginManager, UmbracoApplicationBase umbracoApplication) + { + var startupHandlerTypes = pluginManager.ResolveApplicationStartupHandlers(); + var handlers = startupHandlerTypes.Select(x => + { + try + { + return Activator.CreateInstance(x); + } + catch + { + // fixme - breaks here! + // cannot unstanciate GridPropertyEditor and other oddities BUT they have been refactored in 7.6? + // well, no, so NOW is the time... bah... first we need to figure out STATES + throw new Exception("cannot instanciate " + x.FullName); + } + }).Cast().ToArray(); + + // just a test at that point + return; + + foreach (var handler in handlers) + handler.OnApplicationInitialized(umbracoApplication); + foreach (var handler in handlers) + handler.OnApplicationStarting(umbracoApplication); + + //This is a special case for the user service, we need to tell it if it's an upgrade, if so we need to ensure that + // exceptions are bubbled up if a user is attempted to be persisted during an upgrade (i.e. when they auth to login) + // fixme - wtf? never going back to FALSE ! + ((UserService) Current.Services.UserService).IsUpgrading = true; + + foreach (var handler in handlers) + handler.OnApplicationStarted(umbracoApplication); + + //applicationContext.IsReady = true; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs index 6f600c402e..f40ea424dd 100644 --- a/src/Umbraco.Core/Components/BootLoader.cs +++ b/src/Umbraco.Core/Components/BootLoader.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Reflection; using LightInject; using Umbraco.Core.Configuration; +using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; namespace Umbraco.Core.Components @@ -36,18 +37,15 @@ namespace Umbraco.Core.Components public int Weight = -1; } - public void Boot(IEnumerable componentTypes) + public void Boot(IEnumerable componentTypes, RuntimeLevel level) { if (_booted) throw new InvalidOperationException("Can not boot, has already booted."); - using (_proflog.TraceDuration($"Booting Umbraco {UmbracoVersion.GetSemanticVersion().ToSemanticString()} on {NetworkHelper.MachineName}.", "Booted.")) - { - var orderedComponentTypes = PrepareComponentTypes(componentTypes); + var orderedComponentTypes = PrepareComponentTypes(componentTypes); - InstanciateComponents(orderedComponentTypes); - ComposeComponents(); - InitializeComponents(); - } + InstanciateComponents(orderedComponentTypes); + ComposeComponents(level); + InitializeComponents(); // rejoice! _booted = true; @@ -175,7 +173,7 @@ namespace Umbraco.Core.Components } } - private void ComposeComponents() + private void ComposeComponents(RuntimeLevel level) { using (_proflog.DebugDuration($"Composing components. (log when >{LogThresholdMilliseconds}ms)", "Composed components.")) { @@ -184,7 +182,7 @@ namespace Umbraco.Core.Components var componentType = component.GetType(); using (_proflog.DebugDuration($"Composing {componentType.FullName}.", $"Composed {componentType.FullName}.", LogThresholdMilliseconds)) { - component.Compose(_container); + component.Compose(_container, level); } } } @@ -200,14 +198,14 @@ namespace Umbraco.Core.Components foreach (var component in _components) { var componentType = component.GetType(); - var initializers = componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public) + var initializers = componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(x => x.Name == "Initialize" && x.IsGenericMethod == false); using (_proflog.DebugDuration($"Initializing {componentType.FullName}.", $"Initialised {componentType.FullName}.", LogThresholdMilliseconds)) { foreach (var initializer in initializers) { var parameters = initializer.GetParameters() - .Select(x => _container.GetInstance(x.ParameterType)) + .Select(x => GetParameter(componentType, x.ParameterType)) .ToArray(); initializer.Invoke(component, parameters); } @@ -216,6 +214,13 @@ namespace Umbraco.Core.Components } } + private object GetParameter(Type componentType, Type parameterType) + { + var param = _container.TryGetInstance(parameterType); + if (param == null) throw new BootFailedException($"Could not get parameter of type {parameterType.FullName} for component {componentType.FullName}."); + return param; + } + public void Terminate() { if (_booted == false) throw new InvalidOperationException("Cannot terminate, has not booted."); diff --git a/src/Umbraco.Core/Components/IUmbracoComponent.cs b/src/Umbraco.Core/Components/IUmbracoComponent.cs index 787ce3c792..01e9e6fbf0 100644 --- a/src/Umbraco.Core/Components/IUmbracoComponent.cs +++ b/src/Umbraco.Core/Components/IUmbracoComponent.cs @@ -2,10 +2,21 @@ namespace Umbraco.Core.Components { + /// + /// Represents an Umbraco component. + /// public interface IUmbracoComponent { - void Compose(ServiceContainer container); + /// + /// Composes the component. + /// + /// The container. + /// The runtime level. + void Compose(ServiceContainer container, RuntimeLevel level); + /// + /// Terminates the component. + /// void Terminate(); } } diff --git a/src/Umbraco.Core/Components/UmbracoComponentBase.cs b/src/Umbraco.Core/Components/UmbracoComponentBase.cs index 7b89b25a31..7d67153b95 100644 --- a/src/Umbraco.Core/Components/UmbracoComponentBase.cs +++ b/src/Umbraco.Core/Components/UmbracoComponentBase.cs @@ -2,11 +2,25 @@ namespace Umbraco.Core.Components { + /// + /// Provides a base class for implementations. + /// public abstract class UmbracoComponentBase : IUmbracoComponent { + /// + public virtual void Compose(ServiceContainer container, RuntimeLevel level) + { + Compose(container); + } + + /// + /// Composes the component. + /// + /// The container. public virtual void Compose(ServiceContainer container) { } + /// public virtual void Terminate() { } } diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index b718edbf39..068d1a574a 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -10,6 +10,7 @@ using System.Web.Security; using System.Xml; using System.Xml.Linq; using System.Xml.XPath; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Security; @@ -19,12 +20,12 @@ namespace Umbraco.Core.Configuration //NOTE: Do not expose this class ever until we cleanup all configuration including removal of static classes, etc... // we have this two tasks logged: // http://issues.umbraco.org/issue/U4-58 - // http://issues.umbraco.org/issue/U4-115 + // http://issues.umbraco.org/issue/U4-115 //TODO: Replace checking for if the app settings exist and returning an empty string, instead return the defaults! /// - /// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information from web.config appsettings + /// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information from web.config appsettings /// [Obsolete("TODO: Need to move this configuration class into the proper configuration accesors for v8!")] public class GlobalSettings @@ -72,7 +73,7 @@ namespace Umbraco.Core.Configuration public static string ReservedUrls { get - { + { if (_reservedUrls == null) { var urls = ConfigurationManager.AppSettings.ContainsKey("umbracoReservedUrls") @@ -80,7 +81,7 @@ namespace Umbraco.Core.Configuration : string.Empty; //ensure the built on (non-changeable) reserved paths are there at all times - _reservedUrls = StaticReservedUrls + urls; + _reservedUrls = StaticReservedUrls + urls; } return _reservedUrls; } @@ -167,11 +168,11 @@ namespace Umbraco.Core.Configuration /// /// THIS IS TEMPORARY AND SHOULD BE REMOVED WHEN WE MIGRATE/UPDATE THE CONFIG SETTINGS TO BE A REAL CONFIG SECTION /// AND SHOULD PROBABLY BE HANDLED IN A MORE ROBUST WAY. - /// + /// /// This will return the MVC area that we will route all custom routes through like surface controllers, etc... /// We will use the 'Path' (default ~/umbraco) to create it but since it cannot contain '/' and people may specify a path of ~/asdf/asdf/admin /// we will convert the '/' to '-' and use that as the path. its a bit lame but will work. - /// + /// /// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something /// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco". /// @@ -233,12 +234,12 @@ namespace Umbraco.Core.Configuration { if (value.ToLower().Contains("SQLCE4Umbraco.SqlCEHelper".ToLower())) { - ApplicationContext.Current.DatabaseContext.ConfigureEmbeddedDatabaseConnection(); + Current.DatabaseContext.ConfigureEmbeddedDatabaseConnection(); } else { - ApplicationContext.Current.DatabaseContext.ConfigureDatabaseConnection(value); - } + Current.DatabaseContext.ConfigureDatabaseConnection(value); + } } } } @@ -264,7 +265,7 @@ namespace Umbraco.Core.Configuration SaveSetting("umbracoConfigurationStatus", value); } } - + /// /// Gets or sets the Umbraco members membership providers' useLegacyEncoding state. This will return a boolean /// @@ -280,7 +281,7 @@ namespace Umbraco.Core.Configuration SetMembershipProvidersLegacyEncoding(Constants.Conventions.Member.UmbracoMemberProviderName, value); } } - + /// /// Gets or sets the Umbraco users membership providers' useLegacyEncoding state. This will return a boolean /// @@ -296,7 +297,7 @@ namespace Umbraco.Core.Configuration SetMembershipProvidersLegacyEncoding(UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider, value); } } - + /// /// Saves a setting into the configuration file. /// @@ -337,7 +338,7 @@ namespace Umbraco.Core.Configuration setting.Remove(); xml.Save(fileName, SaveOptions.DisableFormatting); ConfigurationManager.RefreshSection("appSettings"); - } + } } private static void SetMembershipProvidersLegacyEncoding(string providerName, bool useLegacyEncoding) @@ -359,16 +360,16 @@ namespace Umbraco.Core.Configuration var membershipConfigs = webConfigXml.XPathSelectElements("configuration/system.web/membership/providers/add").ToList(); - if (membershipConfigs.Any() == false) + if (membershipConfigs.Any() == false) return; var provider = membershipConfigs.SingleOrDefault(c => c.Attribute("name") != null && c.Attribute("name").Value == providerName); - if (provider == null) + if (provider == null) return; provider.SetAttributeValue("useLegacyEncoding", useLegacyEncoding); - + webConfigXml.Save(webConfigFilename, SaveOptions.DisableFormatting); } @@ -381,7 +382,7 @@ namespace Umbraco.Core.Configuration return false; } - return membershipProvider.UseLegacyEncoding; + return membershipProvider.UseLegacyEncoding; } /// @@ -418,36 +419,6 @@ namespace Umbraco.Core.Configuration } } - /// - /// Gets a value indicating whether the current version of umbraco is configured. - /// - /// true if configured; otherwise, false. - [Obsolete("Do not use this, it is no longer in use and will be removed from the codebase in future versions")] - internal static bool Configured - { - get - { - try - { - string configStatus = ConfigurationStatus; - string currentVersion = UmbracoVersion.GetSemanticVersion().ToSemanticString(); - - - if (currentVersion != configStatus) - { - LogHelper.Debug("CurrentVersion different from configStatus: '" + currentVersion + "','" + configStatus + "'"); - } - - - return (configStatus == currentVersion); - } - catch - { - return false; - } - } - } - /// /// Gets the time out in minutes. /// @@ -525,7 +496,7 @@ namespace Umbraco.Core.Configuration get { //defaults to false - return ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp") + return ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp") && bool.Parse(ConfigurationManager.AppSettings["umbracoContentXMLUseLocalTemp"]); //default to false } } @@ -597,7 +568,7 @@ namespace Umbraco.Core.Configuration [Obsolete("Use Umbraco.Core.Configuration.UmbracoVersion.Current instead", false)] public static string CurrentVersion { - get { return UmbracoVersion.GetSemanticVersion().ToSemanticString(); } + get { return UmbracoVersion.SemanticVersion.ToSemanticString(); } } /// @@ -729,7 +700,7 @@ namespace Umbraco.Core.Configuration } /// - /// Determines whether the current request is reserved based on the route table and + /// Determines whether the current request is reserved based on the route table and /// whether the specified URL is reserved or is inside a reserved path. /// /// @@ -768,7 +739,7 @@ namespace Umbraco.Core.Configuration // store references to strings to determine changes _reservedPathsCache = GlobalSettings.ReservedPaths; _reservedUrlsCache = GlobalSettings.ReservedUrls; - + // add URLs and paths to a new list var newReservedList = new HashSet(); foreach (var reservedUrlTrimmed in _reservedUrlsCache @@ -810,7 +781,7 @@ namespace Umbraco.Core.Configuration return _reservedList.Any(x => pathPart.InvariantStartsWith(x)); } - + } diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index 2e10a7b1e4..ee87379d90 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -4,39 +4,41 @@ using Semver; namespace Umbraco.Core.Configuration { - public class UmbracoVersion + /// + /// Represents the version of the executing code. + /// + public static class UmbracoVersion { // BEWARE! // This class is parsed and updated by the build scripts. // Do NOT modify it unless you understand what you are doing. /// - /// Gets the current version of Umbraco. - /// Version class with the specified major, minor, build (Patch), and revision numbers. + /// Gets the version of the executing code. /// - /// - /// CURRENT UMBRACO VERSION ID. - /// public static Version Current { get; } = new Version("8.0.0"); /// - /// Gets the version comment (like beta or RC). + /// Gets the version comment of the executing code (eg "beta"). /// - /// The version comment. public static string CurrentComment => "alpha0016"; - // Get the version of the Umbraco.Core.dll by looking at a class in that dll - // Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx + /// + /// Gets the assembly version of Umbraco.Code.dll. + /// + /// Get it by looking at a class in that dll, due to medium trust issues, + /// see http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx, + /// however fixme we don't support medium trust anymore? public static string AssemblyVersion => new AssemblyName(typeof(UmbracoVersion).Assembly.FullName).Version.ToString(); - public static SemVersion GetSemanticVersion() - { - return new SemVersion( + /// + /// Gets the semantic version of the executing code. + /// + public static SemVersion SemanticVersion => new SemVersion( Current.Major, Current.Minor, Current.Build, CurrentComment.IsNullOrWhiteSpace() ? null : CurrentComment, Current.Revision > 0 ? Current.Revision.ToInvariantString() : null); - } } } \ No newline at end of file diff --git a/src/Umbraco.Core/CoreRuntime.cs b/src/Umbraco.Core/CoreRuntime.cs index e176f3cc1c..f5db9f8cbe 100644 --- a/src/Umbraco.Core/CoreRuntime.cs +++ b/src/Umbraco.Core/CoreRuntime.cs @@ -1,28 +1,22 @@ using System; using System.Collections.Generic; -using System.IO; +using System.Configuration; using System.Threading.Tasks; using System.Threading; -using AutoMapper; using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; using Umbraco.Core.Logging; -using Umbraco.Core.Manifest; -using Umbraco.Core.Models.Mapping; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Persistence.Migrations; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Mappers; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Plugins; -using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; -using Umbraco.Core.Sync; -using Umbraco.Core.Strings; -using Umbraco.Core._Legacy.PackageActions; namespace Umbraco.Core { @@ -35,46 +29,7 @@ namespace Umbraco.Core public class CoreRuntime : IRuntime { private BootLoader _bootLoader; - private DisposableTimer _timer; - - // fixme cleanup these - private IServiceContainer _appStartupEvtContainer; - private bool _isInitialized; - private bool _isStarted; - private bool _isComplete; - - - // what the UmbracoApplication does is... - // create the container and configure for core - // create and register a logger - // then: - //GetBootManager() - // .Initialize() - // .Startup(appContext => OnApplicationStarting(sender, e)) - // .Complete(appContext => OnApplicationStarted(sender, e)); - // - // edit so it becomes: - //GetBootLoader() - // .Boot(); - // - // merge all RegisterX into one Register - // - // WebBootLoader should - // configure the container for web BUT that should be AFTER the components have initialized? OR? - // - // Startup runs all app event handler OnApplicationStarting methods - // then triggers the OnApplicationStarting event of the app - // Complete - // freezes resolution - // ensures database connection (else?) - // tells user service it is upgrading (?) - // runs all app event handler OnApplicationStarted methods - // then triggers the OnApplicationStarted event of the app - // and sets Ready - // - // note: what's deciding whether install, upgrade, run? - - private RuntimeState _state; // fixme what about web?! + private RuntimeState _state; /// /// Initializes a new instance of the class. @@ -89,16 +44,19 @@ namespace Umbraco.Core /// public virtual void Boot(ServiceContainer container) { - // create and register essential stuff + Compose(container); + + // prepare essential stuff + + _state = (RuntimeState) container.GetInstance(); + _state.Level = RuntimeLevel.Boot; Logger = container.GetInstance(); - container.RegisterInstance(Profiler = GetProfiler()); - container.RegisterInstance(ProfilingLogger = new ProfilingLogger(Current.Logger, Profiler)); + Profiler = container.GetInstance(); + ProfilingLogger = container.GetInstance(); - container.RegisterInstance(_state = new RuntimeState()); - - // then compose - Compose(container); + // fixme - totally temp + container.RegisterInstance(UmbracoApplication); // the boot loader boots using a container scope, so anything that is PerScope will // be disposed after the boot loader has booted, and anything else will remain. @@ -109,33 +67,202 @@ namespace Umbraco.Core // are NOT disposed - which is not a big deal as long as they remain lightweight // objects. - _bootLoader = new BootLoader(container); - _bootLoader.Boot(GetComponentTypes()); + using (ProfilingLogger.TraceDuration($"Booting Umbraco {UmbracoVersion.SemanticVersion.ToSemanticString()} on {NetworkHelper.MachineName}.", "Booted.")) + { + Logger.Debug($"Runtime: {GetType().FullName}"); + + using (ProfilingLogger.DebugDuration("Acquiring MainDom.", "Aquired.")) + { + // become the main domain - before anything else + var mainDom = container.GetInstance(); + mainDom.Acquire(); + } + + using (ProfilingLogger.DebugDuration("Determining runtime level.", "Determined.")) + { + var dbfactory = container.GetInstance(); + SetRuntimeStateLevel(_state, dbfactory, Logger); + } + + Logger.Debug($"Runtime level: {_state.Level}"); + + IEnumerable componentTypes; + using (ProfilingLogger.TraceDuration("Resolving component types.", "Resolved.")) + { + componentTypes = GetComponentTypes(); + } + + // boot + _bootLoader = new BootLoader(container); + _bootLoader.Boot(componentTypes, _state.Level); + } } + /// public virtual void Terminate() { _bootLoader?.Terminate(); } + /// public virtual void Compose(ServiceContainer container) { - // create and register essential stuff + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); - var cache = GetApplicationCache(); - container.RegisterInstance(cache); - container.RegisterInstance(cache.RuntimeCache); + container.RegisterSingleton(_ => new CacheHelper( + // we need to have the dep clone runtime cache provider to ensure + // all entities are cached properly (cloned in and cloned out) + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), + new StaticCacheProvider(), + // we have no request based cache when not running in web-based context + new NullCacheProvider(), + new IsolatedRuntimeCache(type => + // we need to have the dep clone runtime cache provider to ensure + // all entities are cached properly (cloned in and cloned out) + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); + container.RegisterSingleton(factory => factory.GetInstance().RuntimeCache); - container.RegisterInstance(new PluginManager(cache.RuntimeCache, ProfilingLogger)); + container.RegisterSingleton(factory => new PluginManager(factory.GetInstance(), factory.GetInstance())); + + // register syntax providers + container.Register("MySqlSyntaxProvider"); + container.Register("SqlCeSyntaxProvider"); + container.Register("SqlServerSyntaxProvider"); + + // register persistence mappers - means the only place the collection can be modified + // is in a runtime - afterwards it has been frozen and it is too late + MapperCollectionBuilder.Register(container) + .AddProducer(f => f.GetInstance().ResolveAssignedMapperTypes()); + + // register database factory + // will be initialized with syntax providers and a logger, and will try to configure + // from the default connection string name, if possible, else will remain non-configured + // until the database context configures it properly (eg when installing) + container.RegisterSingleton(); + + // register a database accessor - will be replaced + // by HybridUmbracoDatabaseAccessor in the web runtime + container.RegisterSingleton(); + + // register MainDom + container.RegisterSingleton(); } - /// - /// Gets the Umbraco HttpApplication. - /// - protected UmbracoApplicationBase UmbracoApplication { get; } + private static void SetRuntimeStateLevel(RuntimeState runtimeState, IDatabaseFactory databaseFactory, ILogger logger) + { + var localVersion = LocalVersion; // the local, files, version + var codeVersion = runtimeState.SemanticVersion; // the executing code version + var connect = false; + + if (string.IsNullOrWhiteSpace(localVersion)) + { + // there is no local version, we are not installed + logger.Debug("No local version, need to install Umbraco."); + runtimeState.Level = RuntimeLevel.Install; + } + else if (localVersion != codeVersion) + { + // there *is* a local version, but it does not match the code version + // need to upgrade + logger.Debug($"Local version \"{localVersion}\" != code version, need to upgrade Umbraco."); + runtimeState.Level = RuntimeLevel.Upgrade; + } + else if (databaseFactory.Configured == false) + { + // local version *does* match code version, but the database is not configured + // install (again? this is a weird situation...) + logger.Debug("Database is not configured, need to install Umbraco."); + runtimeState.Level = RuntimeLevel.Install; + } + + // anything other than install wants a database - see if we can connect + if (runtimeState.Level != RuntimeLevel.Install) + { + for (var i = 0; i < 5; i++) + { + connect = databaseFactory.CanConnect; + if (connect) break; + logger.Debug(i == 0 + ? "Could not immediately connect to database, trying again." + : "Could not connect to database."); + Thread.Sleep(1000); + } + + if (connect == false) + { + // cannot connect to configured database, this is bad, fail + logger.Debug("Could not connect to database."); + runtimeState.Level = RuntimeLevel.Failed; + + // in fact, this is bad enough that we want to throw + throw new BootFailedException("A connection string is configured but Umbraco could not connect to the database."); + } + } + + // if we cannot connect, cannot do more + if (connect == false) return; + + // else + // look for a matching migration entry - bypassing services entirely - they are not 'up' yet + // fixme - in a LB scenario, ensure that the DB gets upgraded only once! + // fixme - eventually move to yol-style guid-based transitions + var database = databaseFactory.GetDatabase(); + var codeVersionString = codeVersion.ToString(); + var sql = database.Sql() + .Select() + .From() + .Where(x => x.Name.InvariantEquals(GlobalSettings.UmbracoMigrationName) && x.Version == codeVersionString); + bool exists; + try + { + exists = database.FirstOrDefault(sql) != null; + } + catch + { + // can connect to the database but cannot access the migration table... need to install + logger.Debug("Could not check migrations, need to install Umbraco."); + runtimeState.Level = RuntimeLevel.Install; + return; + } + + if (exists) + { + // the database version matches the code & files version, all clear, can run + runtimeState.Level = RuntimeLevel.Run; + return; + } + + // the db version does not match... but we do have a migration table + // so, at least one valid table, so we quite probably are installed & need to upgrade + + // although the files version matches the code version, the database version does not + // which means the local files have been upgraded but not the database - need to upgrade + logger.Debug("Database migrations have not executed, need to upgrade Umbraco."); + runtimeState.Level = RuntimeLevel.Upgrade; + } + + private static string LocalVersion + { + get + { + try + { + // fixme - this should live in its own independent file! NOT web.config! + return ConfigurationManager.AppSettings["umbracoConfigurationStatus"]; + } + catch + { + return string.Empty; + } + } + } #region Locals + // fixme - we almost certainly DONT need these! + protected ILogger Logger { get; private set; } protected IProfiler Profiler { get; private set; } @@ -150,39 +277,32 @@ namespace Umbraco.Core protected virtual IEnumerable GetComponentTypes() => Current.PluginManager.ResolveTypes(); - protected virtual IProfiler GetProfiler() => new LogProfiler(Logger); + //protected virtual IProfiler GetProfiler() => new LogProfiler(Logger); - protected virtual CacheHelper GetApplicationCache() => new CacheHelper( - // we need to have the dep clone runtime cache provider to ensure - // all entities are cached properly (cloned in and cloned out) - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), - new StaticCacheProvider(), - // we have no request based cache when not running in web-based context - new NullCacheProvider(), - new IsolatedRuntimeCache(type => - // we need to have the dep clone runtime cache provider to ensure - // all entities are cached properly (cloned in and cloned out) - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); + //protected virtual CacheHelper GetApplicationCache() => new CacheHelper( + // // we need to have the dep clone runtime cache provider to ensure + // // all entities are cached properly (cloned in and cloned out) + // new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), + // new StaticCacheProvider(), + // // we have no request based cache when not running in web-based context + // new NullCacheProvider(), + // new IsolatedRuntimeCache(type => + // // we need to have the dep clone runtime cache provider to ensure + // // all entities are cached properly (cloned in and cloned out) + // new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); #endregion - #region Core + // fixme - kill everything below! - // cannot run if the db is not there - // tries to connect to db (if configured) - private void EnsureDatabaseConnection() - { - if (Current.ApplicationContext.IsConfigured == false) return; - if (Current.ApplicationContext.DatabaseContext.IsDatabaseConfigured == false) return; + private IServiceContainer _appStartupEvtContainer; + private bool _isInitialized; + private bool _isStarted; + private bool _isComplete; - for (var i = 0; i < 5; i++) - { - if (Current.ApplicationContext.DatabaseContext.CanConnect) return; - Thread.Sleep(1000); - } + protected UmbracoApplicationBase UmbracoApplication { get; } - throw new UmbracoStartupFailedException("Umbraco cannot start: a connection string is configured but Umbraco could not connect to the database."); - } + protected ServiceContainer Container => Current.Container; /// /// Special method to extend the use of Umbraco by enabling the consumer to overwrite @@ -195,33 +315,18 @@ namespace Umbraco.Core IOHelper.SetRootDirectory(rootPath); } - #endregion - - // FIXME everything below needs to be sorted out! - - - protected ServiceContainer Container => Current.Container; // fixme kill - public virtual IRuntime Initialize() { if (_isInitialized) throw new InvalidOperationException("The boot manager has already been initialized"); - //ApplicationCache = Container.GetInstance(); //GetApplicationCache(); - - _timer = ProfilingLogger.TraceDuration( - string.Format("Umbraco {0} application starting on {1}", UmbracoVersion.GetSemanticVersion().ToSemanticString(), NetworkHelper.MachineName), - "Umbraco application startup complete"); - - //now we need to call the initialize methods //Create a 'child'container which is a copy of all of the current registrations and begin a sub scope for it // this child container will be used to manage the application event handler instances and the scope will be // completed at the end of the boot process to allow garbage collection // using (Container.BeginScope()) { } // fixme - throws _appStartupEvtContainer = Container.Clone(); // fixme - but WHY clone? because *then* it has its own scope?! bah ;-( - //using (_appStartupEvtContainer.BeginScope()) // fixme - works wtf? - _appStartupEvtContainer.BeginScope(); // fixme - but then attend to end a scope before all child scopes are completed wtf?! + _appStartupEvtContainer.BeginScope(); _appStartupEvtContainer.RegisterCollection(factory => factory.GetInstance().ResolveApplicationStartupHandlers()); // fixme - parallel? what about our dependencies? @@ -235,7 +340,7 @@ namespace Umbraco.Core //only log if more than 150ms 150)) { - x.OnApplicationInitialized(UmbracoApplication, Current.ApplicationContext); + x.OnApplicationInitialized(UmbracoApplication); } } catch (Exception ex) @@ -257,7 +362,7 @@ namespace Umbraco.Core /// /// /// - public virtual IRuntime Startup(Action afterStartup) + public virtual IRuntime Startup(Action afterStartup) { if (_isStarted) throw new InvalidOperationException("The boot manager has already been initialized"); @@ -273,7 +378,7 @@ namespace Umbraco.Core //only log if more than 150ms 150)) { - x.OnApplicationStarting(UmbracoApplication, Current.ApplicationContext); + x.OnApplicationStarting(UmbracoApplication); } } catch (Exception ex) @@ -285,7 +390,7 @@ namespace Umbraco.Core if (afterStartup != null) { - afterStartup(ApplicationContext.Current); + afterStartup(); } _isStarted = true; @@ -298,22 +403,15 @@ namespace Umbraco.Core /// /// /// - public virtual IRuntime Complete(Action afterComplete) + public virtual IRuntime Complete(Action afterComplete) { if (_isComplete) throw new InvalidOperationException("The boot manager has already been completed"); - Complete2(); - - //Here we need to make sure the db can be connected to - EnsureDatabaseConnection(); - - //This is a special case for the user service, we need to tell it if it's an upgrade, if so we need to ensure that // exceptions are bubbled up if a user is attempted to be persisted during an upgrade (i.e. when they auth to login) - ((UserService) Current.ApplicationContext.Services.UserService).IsUpgrading = true; - - + // fixme - wtf? never going back to FALSE ! + ((UserService) Current.Services.UserService).IsUpgrading = true; //call OnApplicationStarting of each application events handler Parallel.ForEach(_appStartupEvtContainer.GetAllInstances(), x => @@ -326,7 +424,7 @@ namespace Umbraco.Core //only log if more than 150ms 150)) { - x.OnApplicationStarted(UmbracoApplication, Current.ApplicationContext); + x.OnApplicationStarted(UmbracoApplication); } } catch (Exception ex) @@ -345,20 +443,12 @@ namespace Umbraco.Core if (afterComplete != null) { - afterComplete(ApplicationContext.Current); + afterComplete(); } _isComplete = true; - // we're ready to serve content! - Current.ApplicationContext.IsReady = true; - - //stop the timer and log the output - _timer.Dispose(); return this; } - - protected virtual void Complete2() - { } } } diff --git a/src/Umbraco.Core/CoreRuntimeComponent.cs b/src/Umbraco.Core/CoreRuntimeComponent.cs index b000d4a5bb..2927a6e23e 100644 --- a/src/Umbraco.Core/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/CoreRuntimeComponent.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using System.Configuration; using System.IO; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using AutoMapper; using LightInject; @@ -11,6 +13,7 @@ using Umbraco.Core.Components; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.DependencyInjection; +using Umbraco.Core.Exceptions; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Manifest; @@ -23,6 +26,7 @@ using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Sync; using Umbraco.Core._Legacy.PackageActions; +using IntegerValidator = Umbraco.Core.PropertyEditors.IntegerValidator; namespace Umbraco.Core { @@ -38,9 +42,20 @@ namespace Umbraco.Core container.RegisterFrom(); container.RegisterFrom(); + + + + + + + + + + + //TODO: Don't think we'll need this when the resolvers are all container resolvers container.RegisterSingleton(); - container.RegisterSingleton(); + container.Register(factory => FileSystemProviderManager.Current.GetFileSystemProvider()); // fixme - should we capture Logger, etc here or use factory? @@ -70,7 +85,7 @@ namespace Umbraco.Core container.RegisterSingleton(factory => UmbracoConfig.For.UmbracoSettings().DistributedCall.Enabled ? (IServerRegistrar)new ConfigServerRegistrar(UmbracoConfig.For.UmbracoSettings()) : (IServerRegistrar)new DatabaseServerRegistrar( - new Lazy(() => factory.GetInstance().Services.ServerRegistrationService), + new Lazy(factory.GetInstance), new DatabaseServerRegistrarOptions())); // by default we'll use the database server messenger with default options (no callbacks), @@ -78,7 +93,12 @@ namespace Umbraco.Core // fixme - painful, have to take care of lifetime! - we CANNOT ask users to remember! // fixme - same issue with PublishedContentModelFactory and many more, I guess! container.RegisterSingleton(factory - => new DatabaseServerMessenger(factory.GetInstance(), true, new DatabaseServerMessengerOptions())); + => new DatabaseServerMessenger( + factory.GetInstance(), + factory.GetInstance(), + factory.GetInstance(), + factory.GetInstance(), + true, new DatabaseServerMessengerOptions())); CacheRefresherCollectionBuilder.Register(container) .AddProducer(factory => factory.GetInstance().ResolveCacheRefreshers()); @@ -103,27 +123,18 @@ namespace Umbraco.Core container.RegisterSingleton(); } - public void Initialize(IEnumerable modelMapperConfigurations) + internal void Initialize( + IEnumerable modelMapperConfigurations) { //TODO: Remove these for v8! LegacyPropertyEditorIdToAliasConverter.CreateMappingsForCoreEditors(); LegacyParameterEditorAliasConverter.CreateMappingsForCoreEditors(); - InitializeModelMappers(modelMapperConfigurations); - - } - - private void InitializeModelMappers(IEnumerable modelMapperConfigurations) - { + // model mapper configurations have been registered & are created by the container Mapper.Initialize(configuration => { - // fixme why ApplicationEventHandler?! - //foreach (var m in ApplicationEventsResolver.Current.ApplicationEventHandlers.OfType()) foreach (var m in modelMapperConfigurations) - { - //Logger.Debug("FIXME " + m.GetType().FullName); - m.ConfigureMappings(configuration, Current.ApplicationContext); - } + m.ConfigureMappings(configuration); }); } } diff --git a/src/Umbraco.Core/DatabaseContext.cs b/src/Umbraco.Core/DatabaseContext.cs index 59b92a31eb..e28b44e723 100644 --- a/src/Umbraco.Core/DatabaseContext.cs +++ b/src/Umbraco.Core/DatabaseContext.cs @@ -28,24 +28,30 @@ namespace Umbraco.Core { private readonly IDatabaseFactory _factory; private readonly ILogger _logger; + private readonly IRuntimeState _runtime; + private readonly IMigrationEntryService _migrationEntryService; private DatabaseSchemaResult _databaseSchemaValidationResult; /// - /// Initializes a new instance of the class with a database factory and a logger. + /// Initializes a new instance of the class. /// /// A database factory. /// A logger. + /// + /// /// The database factory will try to configure itself but may fail eg if the default /// Umbraco connection string is not available because we are installing. In which case this /// database context must sort things out and configure the database factory before it can be /// used. - public DatabaseContext(IDatabaseFactory factory, ILogger logger) + public DatabaseContext(IDatabaseFactory factory, ILogger logger, IRuntimeState runtime, IMigrationEntryService migrationEntryService) { if (factory == null) throw new ArgumentNullException(nameof(factory)); if (logger == null) throw new ArgumentNullException(nameof(logger)); _factory = factory; _logger = logger; + _runtime = runtime; + _migrationEntryService = migrationEntryService; } /// @@ -69,8 +75,8 @@ namespace Umbraco.Core public UmbracoDatabase Database => _factory.GetDatabase(); /// - /// Gets a value indicating whether the database is configured, ie whether it exists - /// and can be reached. It does not necessarily mean that Umbraco is installed nor + /// Gets a value indicating whether the database is configured. It does not necessarily + /// mean that it is possible to connect, nor that Umbraco is installed, nor /// up-to-date. /// public bool IsDatabaseConfigured => _factory.Configured; @@ -161,7 +167,7 @@ namespace Umbraco.Core /// The name the provider (Sql, Sql Azure, Sql Ce, MySql). /// /// A connection string. - public string GetDatabaseConnectionString(string server, string databaseName, string user, string password, string databaseProvider, out string providerName) + public static string GetDatabaseConnectionString(string server, string databaseName, string user, string password, string databaseProvider, out string providerName) { providerName = Constants.DbProviderNames.SqlServer; var test = databaseProvider.ToLower(); @@ -195,7 +201,7 @@ namespace Umbraco.Core /// The name or address of the database server. /// The name of the database /// A connection string. - public string GetIntegratedSecurityDatabaseConnectionString(string server, string databaseName) + public static string GetIntegratedSecurityDatabaseConnectionString(string server, string databaseName) { return $"Server={server};Database={databaseName};Integrated Security=true"; } @@ -208,7 +214,7 @@ namespace Umbraco.Core /// The user name. /// The user password. /// A connection string. - public string GetAzureConnectionString(string server, string databaseName, string user, string password) + public static string GetAzureConnectionString(string server, string databaseName, string user, string password) { if (server.Contains(".") && ServerStartsWithTcp(server) == false) server = $"tcp:{server}"; @@ -358,7 +364,7 @@ namespace Umbraco.Core return _databaseSchemaValidationResult; } - internal Result CreateDatabaseSchemaAndData(ApplicationContext applicationContext) + internal Result CreateDatabaseSchemaAndData() { try { @@ -398,7 +404,7 @@ namespace Umbraco.Core if (string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus) && installedSchemaVersion.Equals(new Version(0, 0, 0))) { var helper = new DatabaseSchemaHelper(database, _logger); - helper.CreateDatabaseSchema(true, applicationContext); + helper.CreateDatabaseSchema(_runtime, _migrationEntryService, true); message = message + "

Installation completed!

"; @@ -487,7 +493,7 @@ namespace Umbraco.Core //DO the upgrade! - var runner = new MigrationRunner(builder, migrationEntryService, _logger, currentInstalledVersion, UmbracoVersion.GetSemanticVersion(), GlobalSettings.UmbracoMigrationName); + var runner = new MigrationRunner(builder, migrationEntryService, _logger, currentInstalledVersion, UmbracoVersion.SemanticVersion, GlobalSettings.UmbracoMigrationName); var migrationContext = new MigrationContext(database, _logger); var upgraded = runner.Execute(migrationContext /*, true*/); diff --git a/src/Umbraco.Core/DependencyInjection/Current.cs b/src/Umbraco.Core/DependencyInjection/Current.cs index 5b9e033a50..3f83d33291 100644 --- a/src/Umbraco.Core/DependencyInjection/Current.cs +++ b/src/Umbraco.Core/DependencyInjection/Current.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Plugins; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Sync; using Umbraco.Core._Legacy.PackageActions; @@ -29,7 +30,7 @@ namespace Umbraco.Core.DependencyInjection if (_container == null) throw new Exception("No container has been set."); return _container; } - set // ok to set - don't be stupid + set { if (_container != null) throw new Exception("A container has already been set."); _container = value; @@ -39,6 +40,7 @@ namespace Umbraco.Core.DependencyInjection internal static bool HasContainer => _container != null; // for UNIT TESTS exclusively! + // resets *everything* that is 'current' internal static void Reset() { _container = null; @@ -47,7 +49,7 @@ namespace Umbraco.Core.DependencyInjection _logger = null; _profiler = null; _profilingLogger = null; - _applicationContext = null; + _pluginManager = null; // fixme - some of our tests don't reset it? Resetted?.Invoke(null, EventArgs.Empty); } @@ -56,17 +58,8 @@ namespace Umbraco.Core.DependencyInjection #region Getters - // fixme - refactor - // some of our tests want to *set* the current application context and bypass the container - // so for the time being we support it, however we should fix our tests - - private static ApplicationContext _applicationContext; - - public static ApplicationContext ApplicationContext - { - get { return _applicationContext ?? (_applicationContext = Container.GetInstance()); } - set { _applicationContext = value; } - } + public static IRuntimeState RuntimeState + => Container.GetInstance(); // fixme - refactor // some of our tests did mess with the current plugin manager @@ -76,7 +69,9 @@ namespace Umbraco.Core.DependencyInjection public static PluginManager PluginManager { - get { return _pluginManager ?? (_pluginManager = Container.TryGetInstance() ?? PluginManager.Default); } + get { return _pluginManager + ?? (_pluginManager = Container.TryGetInstance() + ?? new PluginManager(ApplicationCache.RuntimeCache, ProfilingLogger)); } set { _pluginManager = value; } } @@ -122,7 +117,7 @@ namespace Umbraco.Core.DependencyInjection private static IShortStringHelper _shortStringHelper; public static IShortStringHelper ShortStringHelper - => _shortStringHelper ?? (_shortStringHelper = _container?.TryGetInstance() + => _shortStringHelper ?? (_shortStringHelper = _container?.TryGetInstance() ?? new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(UmbracoConfig.For.UmbracoSettings()))); private static ILogger _logger; @@ -130,17 +125,26 @@ namespace Umbraco.Core.DependencyInjection private static ProfilingLogger _profilingLogger; public static ILogger Logger - => _logger ?? (_logger = _container?.TryGetInstance() + => _logger ?? (_logger = _container?.TryGetInstance() ?? new DebugDiagnosticsLogger()); public static IProfiler Profiler - => _profiler ?? (_profiler = _container?.TryGetInstance() + => _profiler ?? (_profiler = _container?.TryGetInstance() ?? new LogProfiler(Logger)); public static ProfilingLogger ProfilingLogger => _profilingLogger ?? (_profilingLogger = _container?.TryGetInstance()) ?? new ProfilingLogger(Logger, Profiler); + public static CacheHelper ApplicationCache + => Container.GetInstance(); + + public static ServiceContext Services + => Container.GetInstance(); + + public static DatabaseContext DatabaseContext + => Container.GetInstance(); + #endregion } } diff --git a/src/Umbraco.Core/DependencyInjection/LightInjectExtensions.cs b/src/Umbraco.Core/DependencyInjection/LightInjectExtensions.cs index 72b06e1918..5ce859ae74 100644 --- a/src/Umbraco.Core/DependencyInjection/LightInjectExtensions.cs +++ b/src/Umbraco.Core/DependencyInjection/LightInjectExtensions.cs @@ -25,6 +25,10 @@ namespace Umbraco.Core.DependencyInjection // in Umbraco we do NOT want to do property injection by default, so we have to disable it. // from the docs, the following line will cause the container to "now only try to inject // dependencies for properties that is annotated with the InjectAttribute." + // + // could not find it documented, but tests & code review shows that LightInject considers a + // property to be "injectable" when its setter exists and is not static, nor private, nor + // it is an index property. which means that eg protected or internal setters are OK. container.EnableAnnotatedPropertyInjection(); // see notes in MixedScopeManagerProvider @@ -204,5 +208,46 @@ namespace Umbraco.Core.DependencyInjection foreach (var type in implementationTypes(container)) container.Register(type); } + + /// + /// Registers a base type for auto-registration. + /// + /// The base type. + /// The container. + /// + /// Any type that inherits/implements the base type will be auto-registered on-demand. + /// This methods works with actual types. Use the other overload for eg generic definitions. + /// + public static void RegisterAuto(this IServiceContainer container) + { + container.RegisterFallback((serviceType, serviceName) => + { + // https://github.com/seesharper/LightInject/issues/173 + if (typeof(T).IsAssignableFrom(serviceType)) + container.Register(serviceType); + return false; + }, null); + } + + /// + /// Registers a base type for auto-registration. + /// + /// The container. + /// The base type. + /// + /// Any type that inherits/implements the base type will be auto-registered on-demand. + /// This methods works with actual types, as well as generic definitions eg typeof(MyBase{}). + /// + public static void RegisterAuto(this IServiceContainer container, Type type) + { + container.RegisterFallback((serviceType, serviceName) => + { + //Current.Logger.Debug(typeof(LightInjectExtensions), $"Fallback for type {serviceType.FullName}."); + // https://github.com/seesharper/LightInject/issues/173 + if (type.IsAssignableFromGtd(serviceType)) + container.Register(serviceType); + return false; + }, null); + } } } diff --git a/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs b/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs index 71f9968dc5..02f0b6d6d1 100644 --- a/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs +++ b/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs @@ -20,6 +20,8 @@ namespace Umbraco.Core.DependencyInjection public void Compose(IServiceRegistry container) { + // fixme - moved these to CoreRuntime + /* // register syntax providers container.Register("MySqlSyntaxProvider"); container.Register("SqlCeSyntaxProvider"); @@ -31,8 +33,10 @@ namespace Umbraco.Core.DependencyInjection // until the database context configures it properly (eg when installing) container.RegisterSingleton(); - // register a database accessor - will be replaced + // register a database accessor - will be replaced - fixme - what does this mean? + // by HybridUmbracoDatabaseAccessor in the web project - so what? container.RegisterSingleton(); + */ // register database context container.RegisterSingleton(); @@ -117,9 +121,10 @@ namespace Umbraco.Core.DependencyInjection var serviceContainer = container as IServiceContainer; if (serviceContainer == null) throw new Exception("Container is not IServiceContainer."); + // fixme fixme fixme more // register persistence mappers - MapperCollectionBuilder.Register(serviceContainer) - .AddProducer(f => f.GetInstance().ResolveAssignedMapperTypes()); + //MapperCollectionBuilder.Register(serviceContainer) + // .AddProducer(f => f.GetInstance().ResolveAssignedMapperTypes()); } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Exceptions/BootFailedException.cs b/src/Umbraco.Core/Exceptions/BootFailedException.cs new file mode 100644 index 0000000000..b2836f22ed --- /dev/null +++ b/src/Umbraco.Core/Exceptions/BootFailedException.cs @@ -0,0 +1,18 @@ +using System; + +namespace Umbraco.Core.Exceptions +{ + /// + /// An exception that is thrown if the Umbraco application cannnot boot. + /// + public class BootFailedException : Exception + { + /// + /// Initializes a new instance of the class with a specified error message. + /// + /// The message that describes the error. + public BootFailedException(string message) + : base(message) + { } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Exceptions/UmbracoStartupFailedException.cs b/src/Umbraco.Core/Exceptions/UmbracoStartupFailedException.cs deleted file mode 100644 index d27d38de9a..0000000000 --- a/src/Umbraco.Core/Exceptions/UmbracoStartupFailedException.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace Umbraco.Core.Exceptions -{ - /// - /// An exception that is thrown if the umbraco application cannnot boot - /// - public class UmbracoStartupFailedException : Exception - { - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The message that describes the error. - public UmbracoStartupFailedException(string message) : base(message) - { - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/IApplicationEventHandler.cs b/src/Umbraco.Core/IApplicationEventHandler.cs index 866ce220d4..1421af63ea 100644 --- a/src/Umbraco.Core/IApplicationEventHandler.cs +++ b/src/Umbraco.Core/IApplicationEventHandler.cs @@ -11,22 +11,19 @@ namespace Umbraco.Core /// ApplicationContext is created and other static objects that require initialization have been setup ///
/// - /// - void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext); + void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication); /// /// All resolvers have been initialized but resolution is not frozen so they can be modified in this method /// /// - /// - void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext); + void OnApplicationStarting(UmbracoApplicationBase umbracoApplication); /// /// Bootup is completed, this allows you to perform any other bootup logic required for the application. /// Resolution is frozen so now they can be used to resolve instances. /// /// - /// - void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext); + void OnApplicationStarted(UmbracoApplicationBase umbracoApplication); } } \ No newline at end of file diff --git a/src/Umbraco.Core/IRuntime.cs b/src/Umbraco.Core/IRuntime.cs index 5321e91272..ce0f77ffe4 100644 --- a/src/Umbraco.Core/IRuntime.cs +++ b/src/Umbraco.Core/IRuntime.cs @@ -3,24 +3,7 @@ using LightInject; namespace Umbraco.Core { - // fixme - move! - public class RuntimeState - { - /// - /// Gets a value indicating whether the application is running in debug mode. - /// - public bool Debug { get; } - - public RuntimeSomething Something { get; } - } - - public enum RuntimeSomething - { - Boot, - Run - } - - /// + /// /// Defines the Umbraco runtime. /// public interface IRuntime @@ -35,28 +18,5 @@ namespace Umbraco.Core /// Terminates the runtime. /// void Terminate(); - - // fixme - everything below is obsolete! - - /// - /// Fires first in the application startup process before any customizations can occur - /// - /// - IRuntime Initialize(); - - /// - /// Fires after initialization and calls the callback to allow for customizations to occur - /// - /// - /// - IRuntime Startup(Action afterStartup); - - /// - /// Fires after startup and calls the callback once customizations are locked - /// - /// - /// - IRuntime Complete(Action afterComplete); - } } \ No newline at end of file diff --git a/src/Umbraco.Core/IRuntimeState.cs b/src/Umbraco.Core/IRuntimeState.cs new file mode 100644 index 0000000000..3c399f6a92 --- /dev/null +++ b/src/Umbraco.Core/IRuntimeState.cs @@ -0,0 +1,59 @@ +using System; +using Semver; +using Umbraco.Core.Sync; + +namespace Umbraco.Core +{ + /// + /// Represents the state of the Umbraco runtime. + /// + public interface IRuntimeState + { + /// + /// Gets the version of the executing code. + /// + Version Version { get; } + + /// + /// Gets the version comment of the executing code. + /// + string VersionComment { get; } + + /// + /// Gets the semantic version of the executing code. + /// + SemVersion SemanticVersion { get; } + + /// + /// Gets a value indicating whether the application is running in debug mode. + /// + bool Debug { get; } + + /// + /// Gets a value indicating whether the runtime is the current main domain. + /// + bool IsMainDom { get; } + + /// + /// Get the server's current role. + /// + ServerRole ServerRole { get; } + + /// + /// Gets the Umbraco application url. + /// + /// This is eg "http://www.example.com". + Uri ApplicationUrl { get; } + + /// + /// Gets the Umbraco application virtual path. + /// + /// This is either "/" or eg "/virtual". + string ApplicationVirtualPath { get; } + + /// + /// Gets the runtime level of execution. + /// + RuntimeLevel Level { get; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Logging/WebProfiler.cs b/src/Umbraco.Core/Logging/WebProfiler.cs index 244835f792..6b5d98e46c 100644 --- a/src/Umbraco.Core/Logging/WebProfiler.cs +++ b/src/Umbraco.Core/Logging/WebProfiler.cs @@ -15,8 +15,7 @@ namespace Umbraco.Core.Logging ///Binds to application events to enable the MiniProfiler ///
/// - /// - protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication) { UmbracoApplicationBase.ApplicationInit += UmbracoApplicationApplicationInit; } diff --git a/src/Umbraco.Core/MainDom.cs b/src/Umbraco.Core/MainDom.cs index 4fd8b0862b..e30f2eecac 100644 --- a/src/Umbraco.Core/MainDom.cs +++ b/src/Umbraco.Core/MainDom.cs @@ -92,7 +92,7 @@ namespace Umbraco.Core try { - _logger.Debug("Stopping..."); + _logger.Debug("Stopping."); foreach (var callback in _callbacks.OrderBy(x => x.Key).Select(x => x.Value)) { try @@ -113,7 +113,7 @@ namespace Umbraco.Core // in any case... _isMainDom = false; _asyncLocker.Dispose(); - _logger.Debug("Released MainDom."); + _logger.Debug("Released."); } } @@ -126,11 +126,11 @@ namespace Umbraco.Core // the handler is not installed so that would be the hosting environment if (_signaled) { - _logger.Debug("Cannot acquire MainDom (signaled)."); + _logger.Debug("Cannot acquire (signaled)."); return false; } - _logger.Debug("Acquiring MainDom..."); + _logger.Debug("Acquiring."); // signal other instances that we want the lock, then wait one the lock, // which may timeout, and this is accepted - see comments below @@ -157,7 +157,7 @@ namespace Umbraco.Core HostingEnvironment.RegisterObject(this); - _logger.Debug("Acquired MainDom."); + _logger.Debug("Acquired."); return true; } } diff --git a/src/Umbraco.Core/Models/ContentExtensions.cs b/src/Umbraco.Core/Models/ContentExtensions.cs index 6a8ee044bf..be8deeb8f9 100644 --- a/src/Umbraco.Core/Models/ContentExtensions.cs +++ b/src/Umbraco.Core/Models/ContentExtensions.cs @@ -11,6 +11,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.IO; using Umbraco.Core.Media; using Umbraco.Core.Models.EntityBase; @@ -233,7 +234,7 @@ namespace Umbraco.Core.Models [EditorBrowsable(EditorBrowsableState.Never)] public static IEnumerable Ancestors(this IContent content) { - return ApplicationContext.Current.Services.ContentService.GetAncestors(content); + return Current.Services.ContentService.GetAncestors(content); } /// @@ -251,7 +252,7 @@ namespace Umbraco.Core.Models [EditorBrowsable(EditorBrowsableState.Never)] public static IEnumerable Children(this IContent content) { - return ApplicationContext.Current.Services.ContentService.GetChildren(content.Id); + return Current.Services.ContentService.GetChildren(content.Id); } /// @@ -269,7 +270,7 @@ namespace Umbraco.Core.Models [EditorBrowsable(EditorBrowsableState.Never)] public static IEnumerable Descendants(this IContent content) { - return ApplicationContext.Current.Services.ContentService.GetDescendants(content); + return Current.Services.ContentService.GetDescendants(content); } /// @@ -287,7 +288,7 @@ namespace Umbraco.Core.Models [EditorBrowsable(EditorBrowsableState.Never)] public static IContent Parent(this IContent content) { - return ApplicationContext.Current.Services.ContentService.GetById(content.ParentId); + return Current.Services.ContentService.GetById(content.ParentId); } #endregion @@ -308,7 +309,7 @@ namespace Umbraco.Core.Models [EditorBrowsable(EditorBrowsableState.Never)] public static IEnumerable Ancestors(this IMedia media) { - return ApplicationContext.Current.Services.MediaService.GetAncestors(media); + return Current.Services.MediaService.GetAncestors(media); } /// @@ -326,7 +327,7 @@ namespace Umbraco.Core.Models [EditorBrowsable(EditorBrowsableState.Never)] public static IEnumerable Children(this IMedia media) { - return ApplicationContext.Current.Services.MediaService.GetChildren(media.Id); + return Current.Services.MediaService.GetChildren(media.Id); } /// @@ -344,7 +345,7 @@ namespace Umbraco.Core.Models [EditorBrowsable(EditorBrowsableState.Never)] public static IEnumerable Descendants(this IMedia media) { - return ApplicationContext.Current.Services.MediaService.GetDescendants(media); + return Current.Services.MediaService.GetDescendants(media); } /// @@ -362,7 +363,7 @@ namespace Umbraco.Core.Models [EditorBrowsable(EditorBrowsableState.Never)] public static IMedia Parent(this IMedia media) { - return ApplicationContext.Current.Services.MediaService.GetById(media.ParentId); + return Current.Services.MediaService.GetById(media.ParentId); } #endregion @@ -528,7 +529,7 @@ namespace Umbraco.Core.Models [EditorBrowsable(EditorBrowsableState.Never)] public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileBase value) { - content.SetValue(propertyTypeAlias, value, ApplicationContext.Current.Services.DataTypeService); + content.SetValue(propertyTypeAlias, value, Current.Services.DataTypeService); } /// @@ -583,7 +584,7 @@ namespace Umbraco.Core.Models [EditorBrowsable(EditorBrowsableState.Never)] public static void SetValue(this IContentBase content, string propertyTypeAlias, string fileName, Stream fileStream) { - content.SetValue(propertyTypeAlias, fileName, fileStream, ApplicationContext.Current.Services.DataTypeService); + content.SetValue(propertyTypeAlias, fileName, fileStream, Current.Services.DataTypeService); } private static void SetFileOnContent(IContentBase content, string propertyTypeAlias, string filename, Stream fileStream, IDataTypeService dataTypeService) @@ -676,12 +677,12 @@ namespace Umbraco.Core.Models #region User/Profile methods - + [Obsolete("Use the overload that declares the IUserService to use")] [EditorBrowsable(EditorBrowsableState.Never)] public static IProfile GetCreatorProfile(this IMedia media) { - return ApplicationContext.Current.Services.UserService.GetProfileById(media.CreatorId); + return Current.Services.UserService.GetProfileById(media.CreatorId); } /// @@ -691,12 +692,12 @@ namespace Umbraco.Core.Models { return userService.GetProfileById(media.CreatorId); } - + [Obsolete("Use the overload that declares the IUserService to use")] [EditorBrowsable(EditorBrowsableState.Never)] public static IProfile GetCreatorProfile(this IContentBase content) { - return ApplicationContext.Current.Services.UserService.GetProfileById(content.CreatorId); + return Current.Services.UserService.GetProfileById(content.CreatorId); } /// @@ -706,12 +707,12 @@ namespace Umbraco.Core.Models { return userService.GetProfileById(content.CreatorId); } - + [Obsolete("Use the overload that declares the IUserService to use")] [EditorBrowsable(EditorBrowsableState.Never)] public static IProfile GetWriterProfile(this IContent content) { - return ApplicationContext.Current.Services.UserService.GetProfileById(content.WriterId); + return Current.Services.UserService.GetProfileById(content.WriterId); } /// @@ -737,7 +738,7 @@ namespace Umbraco.Core.Models #region Tag methods - + /// /// Sets tags for the property - will add tags to the tags table and set the property value to be the comma delimited value of the tags. @@ -864,11 +865,11 @@ namespace Umbraco.Core.Models return packagingService.Export(content, true, raiseEvents: false); } - + [Obsolete("Use the overload that declares the IPackagingService to use")] public static XElement ToXml(this IContent content) { - return ApplicationContext.Current.Services.PackagingService.Export(content, raiseEvents: false); + return Current.Services.PackagingService.Export(content, raiseEvents: false); } /// @@ -885,7 +886,7 @@ namespace Umbraco.Core.Models [Obsolete("Use the overload that declares the IPackagingService to use")] public static XElement ToXml(this IMedia media) { - return ApplicationContext.Current.Services.PackagingService.Export(media, raiseEvents: false); + return Current.Services.PackagingService.Export(media, raiseEvents: false); } /// @@ -935,7 +936,7 @@ namespace Umbraco.Core.Models [Obsolete("Use the overload that declares the IPackagingService to use")] public static XElement ToXml(this IMember member) { - return ((PackagingService)(ApplicationContext.Current.Services.PackagingService)).Export(member); + return ((PackagingService)(Current.Services.PackagingService)).Export(member); } /// diff --git a/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs b/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs index 534b4367ff..898ce49ce2 100644 --- a/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs +++ b/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs @@ -4,12 +4,20 @@ using AutoMapper; using Umbraco.Core.Models.Mapping; using Umbraco.Core.Models.Membership; using Umbraco.Core.Security; +using Umbraco.Core.Services; namespace Umbraco.Core.Models.Identity { public class IdentityModelMappings : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + private readonly ILocalizedTextService _textService; + + public IdentityModelMappings(ILocalizedTextService textService) + { + _textService = textService; + } + + public override void ConfigureMappings(IMapperConfiguration config) { config.CreateMap() .ForMember(user => user.Email, expression => expression.MapFrom(user => user.Email)) @@ -17,7 +25,7 @@ namespace Umbraco.Core.Models.Identity .ForMember(user => user.LockoutEndDateUtc, expression => expression.MapFrom(user => user.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?) null)) .ForMember(user => user.UserName, expression => expression.MapFrom(user => user.Username)) .ForMember(user => user.PasswordHash, expression => expression.MapFrom(user => GetPasswordHash(user.RawPasswordValue))) - .ForMember(user => user.Culture, expression => expression.MapFrom(user => user.GetUserCulture(applicationContext.Services.TextService))) + .ForMember(user => user.Culture, expression => expression.MapFrom(user => user.GetUserCulture(_textService))) .ForMember(user => user.Name, expression => expression.MapFrom(user => user.Name)) .ForMember(user => user.StartMediaId, expression => expression.MapFrom(user => user.StartMediaId)) .ForMember(user => user.StartContentId, expression => expression.MapFrom(user => user.StartContentId)) diff --git a/src/Umbraco.Core/Models/Mapping/ModelMapperConfiguration.cs b/src/Umbraco.Core/Models/Mapping/ModelMapperConfiguration.cs index 8febce06d5..8768776281 100644 --- a/src/Umbraco.Core/Models/Mapping/ModelMapperConfiguration.cs +++ b/src/Umbraco.Core/Models/Mapping/ModelMapperConfiguration.cs @@ -7,8 +7,6 @@ namespace Umbraco.Core.Models.Mapping /// public abstract class ModelMapperConfiguration { - public abstract void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext); + public abstract void ConfigureMappings(IMapperConfiguration config); } - - } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Membership/MembershipUserExtensions.cs b/src/Umbraco.Core/Models/Membership/MembershipUserExtensions.cs index 2289983033..943be94c84 100644 --- a/src/Umbraco.Core/Models/Membership/MembershipUserExtensions.cs +++ b/src/Umbraco.Core/Models/Membership/MembershipUserExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Web.Security; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Security; using Umbraco.Core.Services; @@ -38,7 +39,7 @@ namespace Umbraco.Core.Models.Membership { return MembershipScenario.NativeUmbraco; } - var memberType = ApplicationContext.Current.Services.MemberTypeService.Get(Constants.Conventions.MemberTypes.DefaultAlias); + var memberType = Current.Services.MemberTypeService.Get(Constants.Conventions.MemberTypes.DefaultAlias); return memberType != null ? MembershipScenario.CustomProviderWithUmbracoLink : MembershipScenario.StandaloneCustomProvider; diff --git a/src/Umbraco.Core/Models/PropertyExtensions.cs b/src/Umbraco.Core/Models/PropertyExtensions.cs index 53119d4931..65f91d201f 100644 --- a/src/Umbraco.Core/Models/PropertyExtensions.cs +++ b/src/Umbraco.Core/Models/PropertyExtensions.cs @@ -2,6 +2,7 @@ using System.Xml; using System.Xml.Linq; using Umbraco.Core.Configuration; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; @@ -17,8 +18,8 @@ namespace Umbraco.Core.Models public static XElement ToXml(this Property property) { var xmlSerializer = new EntityXmlSerializer(); - return xmlSerializer.Serialize(ApplicationContext.Current.Services.DataTypeService, property); + return xmlSerializer.Serialize(Current.Services.DataTypeService, property); } - + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs b/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs index ba30d48548..dd723f2eca 100644 --- a/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs +++ b/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs @@ -44,10 +44,9 @@ namespace Umbraco.Core.Persistence /// Safe method that is only able to create the schema in non-configured /// umbraco instances. /// - public void CreateDatabaseSchema(ApplicationContext applicationContext) + public void CreateDatabaseSchema(IRuntimeState runtime, IMigrationEntryService migrationEntryService) { - if (applicationContext == null) throw new ArgumentNullException(nameof(applicationContext)); - CreateDatabaseSchema(true, applicationContext); + CreateDatabaseSchema(runtime, migrationEntryService, true); } /// @@ -55,24 +54,15 @@ namespace Umbraco.Core.Persistence /// with the option to guard the db from having the schema created /// multiple times. /// + /// /// - /// - public void CreateDatabaseSchema(bool guardConfiguration, ApplicationContext applicationContext) + /// + public void CreateDatabaseSchema(IRuntimeState runtime, IMigrationEntryService migrationEntryService, bool guardConfiguration) { - if (applicationContext == null) throw new ArgumentNullException(nameof(applicationContext)); - - if (guardConfiguration && applicationContext.IsConfigured) + if (guardConfiguration && runtime.Level == RuntimeLevel.Run) throw new Exception("Umbraco is already configured!"); - CreateDatabaseSchemaDo(applicationContext.Services.MigrationEntryService); - } - - internal void CreateDatabaseSchemaDo(bool guardConfiguration, ApplicationContext applicationContext) - { - if (guardConfiguration && applicationContext.IsConfigured) - throw new Exception("Umbraco is already configured!"); - - CreateDatabaseSchemaDo(applicationContext.Services.MigrationEntryService); + CreateDatabaseSchemaDo(migrationEntryService); } internal void CreateDatabaseSchemaDo(IMigrationEntryService migrationEntryService) diff --git a/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs b/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs index 1a257f3ce8..7762978355 100644 --- a/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs +++ b/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs @@ -38,13 +38,13 @@ namespace Umbraco.Core.Persistence throw new NotSupportedException($"Provider \"{providerName}\" is not supported."); var factory = DbProviderFactories.GetFactory(providerName); - var conn = factory.CreateConnection(); + var connection = factory.CreateConnection(); - if (conn == null) + if (connection == null) throw new InvalidOperationException($"Could not create a connection for provider \"{providerName}\"."); - conn.ConnectionString = connectionString; - using (var connection = conn) + connection.ConnectionString = connectionString; + using (connection) { return connection.IsAvailable(); } @@ -60,7 +60,7 @@ namespace Umbraco.Core.Persistence catch (DbException e) { // Don't swallow this error, the exception is super handy for knowing "why" its not available - LogHelper.WarnWithException("Configured database is reporting as not being available!", e); + LogHelper.WarnWithException("Configured database is reporting as not being available.", e); return false; } diff --git a/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs b/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs index a9e2777514..79bd5931b3 100644 --- a/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs @@ -44,25 +44,6 @@ namespace Umbraco.Core.Persistence private IQueryFactory _queryFactory; private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); - public bool Configured { get; private set; } - public ISqlSyntaxProvider SqlSyntax - { - get - { - EnsureConfigured(); - return _sqlSyntax; - } - } - - public IQueryFactory QueryFactory - { - get - { - EnsureConfigured(); - return _queryFactory ?? (_queryFactory = new QueryFactory(SqlSyntax, _mappers)); - } - } - /// /// Initializes a new instance of the with the default connection, and a logger. /// @@ -100,8 +81,6 @@ namespace Umbraco.Core.Persistence _logger = logger; _umbracoDatabaseAccessor = umbracoDatabaseAccessor; - _logger.Debug("Created!"); - var settings = ConfigurationManager.ConnectionStrings[connectionStringName]; if (settings == null) return; // not configured @@ -111,7 +90,10 @@ namespace Umbraco.Core.Persistence var connectionString = settings.ConnectionString; var providerName = settings.ProviderName; if (string.IsNullOrWhiteSpace(connectionString) || string.IsNullOrWhiteSpace(providerName)) + { + logger.Debug("Missing connection string or provider name, defer configuration."); return; // not configured + } Configure(settings.ConnectionString, settings.ProviderName); } @@ -138,19 +120,56 @@ namespace Umbraco.Core.Persistence _logger = logger; _umbracoDatabaseAccessor = umbracoDatabaseAccessor; - _logger.Debug("Created!"); - if (string.IsNullOrWhiteSpace(connectionString) || string.IsNullOrWhiteSpace(providerName)) + { + logger.Debug("Missing connection string or provider name, defer configuration."); return; // not configured + } Configure(connectionString, providerName); } + /// + /// Gets a value indicating whether the database is configured (no connect test). + /// + /// + public bool Configured { get; private set; } + + /// + /// Gets a value indicating whether it is possible to connect to the database. + /// + public bool CanConnect => Configured && DbConnectionExtensions.IsConnectionAvailable(_connectionString, _providerName); + + /// + /// Gets the database sql syntax provider. + /// + public ISqlSyntaxProvider SqlSyntax + { + get + { + EnsureConfigured(); + return _sqlSyntax; + } + } + + /// + /// Gets the database query factory. + /// + public IQueryFactory QueryFactory + { + get + { + EnsureConfigured(); + return _queryFactory ?? (_queryFactory = new QueryFactory(SqlSyntax, _mappers)); + } + } + + // will be configured by the database context public void Configure(string connectionString, string providerName) { using (new WriteLock(_lock)) { - _logger.Debug("Configuring!"); + _logger.Debug("Configuring."); if (Configured) throw new InvalidOperationException("Already configured."); @@ -186,9 +205,9 @@ namespace Umbraco.Core.Persistence .UsingDatabase(CreateDatabaseInstance) // creating UmbracoDatabase instances .WithFluentConfig(config)); // with proper configuration - if (_databaseFactory == null) throw new NullReferenceException("The call to DatabaseFactory.Config yielded a null DatabaseFactory instance"); + if (_databaseFactory == null) throw new NullReferenceException("The call to DatabaseFactory.Config yielded a null DatabaseFactory instance."); - _logger.Debug("Created _nonHttpInstance"); + _logger.Debug("Configured."); Configured = true; } } @@ -209,12 +228,6 @@ namespace Umbraco.Core.Persistence //provider = _syntaxProviders.FirstOrDefault(x => x.GetType() == typeof(SqlServerSyntaxProvider)); } - /// - /// Gets a value indicating whether it is possible to connect to the database. - /// - /// - public bool CanConnect => Configured && DbConnectionExtensions.IsConnectionAvailable(_connectionString, _providerName); - private void EnsureConfigured() { using (new ReadLock(_lock)) diff --git a/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs b/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs index 313c5a5bd3..ba80ae053c 100644 --- a/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs +++ b/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs @@ -1,8 +1,9 @@ using System; +using Umbraco.Core.DependencyInjection; namespace Umbraco.Core.Persistence.Mappers { - public interface IMapperCollection + public interface IMapperCollection : IBuilderCollection { BaseMapper this[Type type] { get; } } diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index 6a22749f15..8f2bab7dcb 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -316,7 +316,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial { Id = 1, Name = GlobalSettings.UmbracoMigrationName, - Version = UmbracoVersion.GetSemanticVersion().ToString(), + Version = UmbracoVersion.SemanticVersion.ToString(), CreateDate = DateTime.Now }; diff --git a/src/Umbraco.Core/Plugins/PluginManager.cs b/src/Umbraco.Core/Plugins/PluginManager.cs index 0185991869..9d37874598 100644 --- a/src/Umbraco.Core/Plugins/PluginManager.cs +++ b/src/Umbraco.Core/Plugins/PluginManager.cs @@ -93,20 +93,6 @@ namespace Umbraco.Core.Plugins } } - public static PluginManager Current => DependencyInjection.Current.PluginManager; - - internal static PluginManager Default - { - get - { - var appctx = ApplicationContext.Current; - var cacheProvider = appctx == null // fixme - should Current have an ApplicationCache? - ? new NullCacheProvider() - : appctx.ApplicationCache.RuntimeCache; - return new PluginManager(cacheProvider, DependencyInjection.Current.ProfilingLogger); - } - } - #region Hash checking methods /// diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs index 7b55c9462b..57f268040e 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs @@ -6,6 +6,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Grid; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; @@ -50,12 +51,12 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters //TODO: Change all singleton access to use ctor injection in v8!!! //TODO: That would mean that property value converters would need to be request lifespan, hrm.... var gridConfig = UmbracoConfig.For.GridConfig( - ApplicationContext.Current.ProfilingLogger.Logger, - ApplicationContext.Current.ApplicationCache.RuntimeCache, + Current.ProfilingLogger.Logger, + Current.ApplicationCache.RuntimeCache, new DirectoryInfo(HttpContext.Current.Server.MapPath(SystemDirectories.AppPlugins)), new DirectoryInfo(HttpContext.Current.Server.MapPath(SystemDirectories.Config)), HttpContext.Current.IsDebuggingEnabled); - + var sections = GetArray(obj, "sections"); foreach (var section in sections.Cast()) { diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueConverter.cs index f1d00f22ab..54f64823fb 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueConverter.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; @@ -34,7 +35,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters public ImageCropperValueConverter() { - _dataTypeService = ApplicationContext.Current.Services.DataTypeService; + _dataTypeService = Current.Services.DataTypeService; } public ImageCropperValueConverter(IDataTypeService dataTypeService) diff --git a/src/Umbraco.Core/RuntimeLevel.cs b/src/Umbraco.Core/RuntimeLevel.cs new file mode 100644 index 0000000000..456c0e3296 --- /dev/null +++ b/src/Umbraco.Core/RuntimeLevel.cs @@ -0,0 +1,37 @@ +namespace Umbraco.Core +{ + public enum RuntimeLevel + { + /// + /// The runtime has failed to boot and cannot run. + /// + Failed = -1, + + /// + /// The level is unknown. + /// + Unknown = 0, + + /// + /// The runtime is booting. + /// + Boot = 1, + + /// + /// The runtime has detected that Umbraco is not installed at all, ie there is + /// no database, and is currently installing Umbraco. + /// + Install = 2, + + /// + /// The runtime has detected an Umbraco install which needed to be upgraded, and + /// is currently upgrading Umbraco. + /// + Upgrade = 3, + + /// + /// The runtime has detected an up-to-date Umbraco install and is running. + /// + Run = 4 + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/RuntimeState.cs b/src/Umbraco.Core/RuntimeState.cs new file mode 100644 index 0000000000..7c3f9b3d6a --- /dev/null +++ b/src/Umbraco.Core/RuntimeState.cs @@ -0,0 +1,117 @@ +using System; +using System.Threading; +using System.Web; +using Semver; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Logging; +using Umbraco.Core.Sync; + +namespace Umbraco.Core +{ + /// + /// Represents the state of the Umbraco runtime. + /// + internal class RuntimeState : IRuntimeState + { + private readonly ILogger _logger; + private readonly Lazy _serverRegistrar; + private readonly Lazy _mainDom; + private RuntimeLevel _level; + + /// + /// Initializes a new instance of the class. + /// + /// A logger. + /// A (lazy) server registrar. + /// A (lazy) MainDom. + public RuntimeState(ILogger logger, Lazy serverRegistrar, Lazy mainDom) + { + _logger = logger; + _serverRegistrar = serverRegistrar; + _mainDom = mainDom; + } + + private IServerRegistrar ServerRegistrar => _serverRegistrar.Value; + + /// + /// Gets the application MainDom. + /// + /// This is NOT exposed in the interface as MainDom is internal. + public MainDom MainDom => _mainDom.Value; + + /// + /// Gets the version of the executing code. + /// + public Version Version => UmbracoVersion.Current; + + /// + /// Gets the version comment of the executing code. + /// + public string VersionComment => UmbracoVersion.CurrentComment; + + /// + /// Gets the semantic version of the executing code. + /// + public SemVersion SemanticVersion => UmbracoVersion.SemanticVersion; + + /// + /// Gets a value indicating whether the application is running in debug mode. + /// + public bool Debug { get; } = GlobalSettings.DebugMode; + + /// + /// Gets a value indicating whether the runtime is the current main domain. + /// + public bool IsMainDom => MainDom.IsMainDom; + + /// + /// Get the server's current role. + /// + public ServerRole ServerRole => ServerRegistrar.GetCurrentServerRole(); + + /// + /// Gets the Umbraco application url. + /// + /// This is eg "http://www.example.com". + public Uri ApplicationUrl { get; private set; } + + /// + /// Gets the Umbraco application virtual path. + /// + /// This is either "/" or eg "/virtual". + public string ApplicationVirtualPath { get; } = HttpRuntime.AppDomainAppVirtualPath; + + /// + /// Gets the runtime level of execution. + /// + public RuntimeLevel Level + { + get { return _level; } + internal set { _level = value; if (value == RuntimeLevel.Run) _runLevel.Set(); } + } + + /// + /// Ensures that the property has a value. + /// + /// + /// + internal void EnsureApplicationUrl(HttpRequestBase request = null, IUmbracoSettingsSection settings = null) + { + if (ApplicationUrl != null) return; + ApplicationUrl = new Uri(ApplicationUrlHelper.GetApplicationUrl(_logger, request, settings)); + } + + private readonly ManualResetEventSlim _runLevel = new ManualResetEventSlim(false); + + /// + /// Waits for the runtime level to become RuntimeLevel.Run. + /// + /// A timeout. + /// True if the runtime level became RuntimeLevel.Run before the timeout, otherwise false. + internal bool WaitForRunLevel(TimeSpan timeout) + { + return _runLevel.WaitHandle.WaitOne(timeout); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs index 02eb0e97e3..9eacaa792f 100644 --- a/src/Umbraco.Core/Services/PackagingService.cs +++ b/src/Umbraco.Core/Services/PackagingService.cs @@ -9,6 +9,7 @@ using System.Xml.Linq; using System.Xml.XPath; using Newtonsoft.Json; using Umbraco.Core.Configuration; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -261,7 +262,7 @@ namespace Umbraco.Core.Services { //TODO: We need to refactor this so the packager isn't making direct db calls for an 'edge' case - var database = ApplicationContext.Current.DatabaseContext.Database; + var database = Current.DatabaseContext.Database; var dtos = database.Fetch("WHERE datatypeNodeId = @Id", new { Id = propertyType.DataTypeDefinitionId }); var propertyValueList = new List(); diff --git a/src/Umbraco.Core/Strategies/ManifestWatcherHandler.cs b/src/Umbraco.Core/Strategies/ManifestWatcherHandler.cs index ad28f2e0bf..efa9138306 100644 --- a/src/Umbraco.Core/Strategies/ManifestWatcherHandler.cs +++ b/src/Umbraco.Core/Strategies/ManifestWatcherHandler.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.IO; using Umbraco.Core.Manifest; @@ -9,7 +10,7 @@ namespace Umbraco.Core.Strategies { private ManifestWatcher _mw; - protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication) { UmbracoApplicationBase.ApplicationEnd += app_ApplicationEnd; } @@ -22,9 +23,9 @@ namespace Umbraco.Core.Strategies } } - protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication) { - _mw = new ManifestWatcher(applicationContext.ProfilingLogger.Logger); + _mw = new ManifestWatcher(Current.ProfilingLogger.Logger); _mw.Start(Directory.GetDirectories(IOHelper.MapPath("~/App_Plugins/"))); } } diff --git a/src/Umbraco.Core/Strategies/RelateOnCopyHandler.cs b/src/Umbraco.Core/Strategies/RelateOnCopyHandler.cs index 7a172ae1a8..b7db0fdf47 100644 --- a/src/Umbraco.Core/Strategies/RelateOnCopyHandler.cs +++ b/src/Umbraco.Core/Strategies/RelateOnCopyHandler.cs @@ -1,13 +1,14 @@ using System; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Models; using Umbraco.Core.Services; namespace Umbraco.Core.Strategies { - //TODO: This should just exist in the content service/repo! + //TODO: This should just exist in the content service/repo! public sealed class RelateOnCopyHandler : ApplicationEventHandler { - protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication) { ContentService.Copied += ContentServiceCopied; } @@ -16,7 +17,7 @@ namespace Umbraco.Core.Strategies { if (e.RelateToOriginal) { - var relationService = ApplicationContext.Current.Services.RelationService; + var relationService = Current.Services.RelationService; var relationType = relationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias); @@ -33,7 +34,7 @@ namespace Umbraco.Core.Strategies var relation = new Relation(e.Original.Id, e.Copy.Id, relationType); relationService.Save(relation); - ApplicationContext.Current.Services.AuditService.Add( + Current.Services.AuditService.Add( AuditType.Copy, string.Format("Copied content with Id: '{0}' related to original content with Id: '{1}'", e.Copy.Id, e.Original.Id), e.Copy.WriterId, e.Copy.Id); diff --git a/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs b/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs index 7628332738..f2cfc3ac3b 100644 --- a/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs +++ b/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Umbraco.Core.DependencyInjection; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Services; @@ -8,7 +9,7 @@ namespace Umbraco.Core.Strategies { public sealed class RelateOnTrashHandler : ApplicationEventHandler { - protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication) { ContentService.Moved += ContentService_Moved; ContentService.Trashed += ContentService_Trashed; @@ -18,7 +19,7 @@ namespace Umbraco.Core.Strategies { foreach (var item in e.MoveInfoCollection.Where(x => x.OriginalPath.Contains(Constants.System.RecycleBinContent.ToInvariantString()))) { - var relationService = ApplicationContext.Current.Services.RelationService; + var relationService = Current.Services.RelationService; var relationTypeAlias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias; var relations = relationService.GetByChildId(item.Entity.Id); @@ -31,7 +32,7 @@ namespace Umbraco.Core.Strategies private void ContentService_Trashed(IContentService sender, MoveEventArgs e) { - var relationService = ApplicationContext.Current.Services.RelationService; + var relationService = Current.Services.RelationService; var relationTypeAlias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias; var relationType = relationService.GetRelationTypeByAlias(relationTypeAlias); @@ -56,7 +57,7 @@ namespace Umbraco.Core.Strategies var relation = new Relation(originalParentId, item.Entity.Id, relationType); relationService.Save(relation); - ApplicationContext.Current.Services.AuditService.Add(AuditType.Delete, + Current.Services.AuditService.Add(AuditType.Delete, string.Format("Trashed content with Id: '{0}' related to original parent content with Id: '{1}'", item.Entity.Id, originalParentId), item.Entity.WriterId, item.Entity.Id); diff --git a/src/Umbraco.Core/Sync/ApplicationUrlHelper.cs b/src/Umbraco.Core/Sync/ApplicationUrlHelper.cs index 556c0e73a3..a321aa583e 100644 --- a/src/Umbraco.Core/Sync/ApplicationUrlHelper.cs +++ b/src/Umbraco.Core/Sync/ApplicationUrlHelper.cs @@ -4,6 +4,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.DependencyInjection; using Umbraco.Core.IO; +using Umbraco.Core.Logging; namespace Umbraco.Core.Sync { @@ -15,8 +16,6 @@ namespace Umbraco.Core.Sync // because we cannot logger.Info because type is static private static readonly Type TypeOfApplicationUrlHelper = typeof(ApplicationUrlHelper); - private static Func _applicationUrlProvider; - /// /// Gets or sets a custom provider for the umbraco application url. /// @@ -27,54 +26,32 @@ namespace Umbraco.Core.Sync /// in config files but is determined programmatically. /// Must be assigned before resolution is frozen. /// - public static Func ApplicationUrlProvider // FIXME need another way to do it, eg an interface, injected! + // FIXME need another way to do it, eg an interface, injected! + public static Func ApplicationUrlProvider { get; set; } + + internal static string GetApplicationUrl(ILogger logger, HttpRequestBase request = null, IUmbracoSettingsSection settings = null) { - get + var umbracoApplicationUrl = TryGetApplicationUrl(settings ?? UmbracoConfig.For.UmbracoSettings(), logger); + if (umbracoApplicationUrl != null) + return umbracoApplicationUrl; + + umbracoApplicationUrl = ApplicationUrlProvider?.Invoke(request); + if (string.IsNullOrWhiteSpace(umbracoApplicationUrl) == false) { - return _applicationUrlProvider; - } - set - { - _applicationUrlProvider = value; - } - } - - // request: will be null if called from ApplicationContext - // settings: for unit tests only - internal static void EnsureApplicationUrl(ApplicationContext appContext, HttpRequestBase request = null, IUmbracoSettingsSection settings = null) - { - // if initialized, return - if (appContext._umbracoApplicationUrl != null) return; - - var logger = appContext.ProfilingLogger.Logger; - - // try settings and IServerRegistrar - if (TrySetApplicationUrl(appContext, settings ?? UmbracoConfig.For.UmbracoSettings())) - return; - - // try custom provider - if (_applicationUrlProvider != null) - { - var url = _applicationUrlProvider(request); - if (url.IsNullOrWhiteSpace() == false) - { - appContext._umbracoApplicationUrl = url.TrimEnd('/'); - logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (provider)"); - return; - } + umbracoApplicationUrl = umbracoApplicationUrl.TrimEnd('/'); + logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + umbracoApplicationUrl + " (provider)"); + return umbracoApplicationUrl; } - // last chance, - // use the current request as application url - if (request == null) return; - SetApplicationUrlFromCurrentRequest(appContext, request); + if (request == null) return null; + + umbracoApplicationUrl = GetApplicationUrlFromCurrentRequest(request); + logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + umbracoApplicationUrl + " (UmbracoModule request)"); + return umbracoApplicationUrl; } - // internal for tests - internal static bool TrySetApplicationUrl(ApplicationContext appContext, IUmbracoSettingsSection settings) + internal static string TryGetApplicationUrl(IUmbracoSettingsSection settings, ILogger logger) { - var logger = appContext.ProfilingLogger.Logger; - // try umbracoSettings:settings/web.routing/@umbracoApplicationUrl // which is assumed to: // - end with SystemDirectories.Umbraco @@ -84,9 +61,9 @@ namespace Umbraco.Core.Sync var url = settings.WebRouting.UmbracoApplicationUrl; if (url.IsNullOrWhiteSpace() == false) { - appContext._umbracoApplicationUrl = url.TrimEnd('/'); - logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (using web.routing/@umbracoApplicationUrl)"); - return true; + var umbracoApplicationUrl = url.TrimEnd('/'); + logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + umbracoApplicationUrl + " (using web.routing/@umbracoApplicationUrl)"); + return umbracoApplicationUrl; } // try umbracoSettings:settings/scheduledTasks/@baseUrl @@ -100,9 +77,9 @@ namespace Umbraco.Core.Sync { var ssl = GlobalSettings.UseSSL ? "s" : ""; url = "http" + ssl + "://" + url; - appContext._umbracoApplicationUrl = url.TrimEnd('/'); - logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (using scheduledTasks/@baseUrl)"); - return true; + var umbracoApplicationUrl = url.TrimEnd('/'); + logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + umbracoApplicationUrl + " (using scheduledTasks/@baseUrl)"); + return umbracoApplicationUrl; } // try the server registrar @@ -114,19 +91,17 @@ namespace Umbraco.Core.Sync url = Current.ServerRegistrar.GetCurrentServerUmbracoApplicationUrl(); if (url.IsNullOrWhiteSpace() == false) { - appContext._umbracoApplicationUrl = url.TrimEnd('/'); - logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (IServerRegistrar)"); - return true; + var umbracoApplicationUrl = url.TrimEnd('/'); + logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + umbracoApplicationUrl + " (IServerRegistrar)"); + return umbracoApplicationUrl; } // else give up... - return false; + return null; } - private static void SetApplicationUrlFromCurrentRequest(ApplicationContext appContext, HttpRequestBase request) + private static string GetApplicationUrlFromCurrentRequest(HttpRequestBase request) { - var logger = appContext.ProfilingLogger.Logger; - // if (HTTP and SSL not required) or (HTTPS and SSL required), // use ports from request // otherwise, @@ -141,8 +116,7 @@ namespace Umbraco.Core.Sync var ssl = GlobalSettings.UseSSL ? "s" : ""; // force, whatever the first request var url = "http" + ssl + "://" + request.ServerVariables["SERVER_NAME"] + port + IOHelper.ResolveUrl(SystemDirectories.Umbraco); - appContext._umbracoApplicationUrl = url.TrimEnd('/'); - logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (UmbracoModule request)"); + return url.TrimEnd('/'); } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs index 46c5aa3681..48658d6d0b 100644 --- a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Web; +using LightInject; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NPoco; @@ -15,7 +16,6 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Sync { @@ -29,35 +29,45 @@ namespace Umbraco.Core.Sync // public class DatabaseServerMessenger : ServerMessengerBase { - private readonly ApplicationContext _appContext; + private readonly IRuntimeState _runtime; private readonly DatabaseServerMessengerOptions _options; private readonly ManualResetEvent _syncIdle; private readonly object _locko = new object(); - private readonly ILogger _logger; + private readonly ProfilingLogger _profilingLogger; private int _lastId = -1; private DateTime _lastSync; private DateTime _lastPruned; private bool _initialized; private bool _syncing; private bool _released; - private readonly ProfilingLogger _profilingLogger; - protected ApplicationContext ApplicationContext { get { return _appContext; } } - - public DatabaseServerMessenger(ApplicationContext appContext, bool distributedEnabled, DatabaseServerMessengerOptions options) + public DatabaseServerMessenger( + IRuntimeState runtime, DatabaseContext dbContext, ILogger logger, ProfilingLogger proflog, + bool distributedEnabled, DatabaseServerMessengerOptions options) : base(distributedEnabled) { - if (appContext == null) throw new ArgumentNullException("appContext"); - if (options == null) throw new ArgumentNullException("options"); + if (dbContext == null) throw new ArgumentNullException(nameof(dbContext)); + if (logger == null) throw new ArgumentNullException(nameof(logger)); + if (proflog == null) throw new ArgumentNullException(nameof(proflog)); + if (options == null) throw new ArgumentNullException(nameof(options)); - _appContext = appContext; + DatabaseContext = dbContext; + Logger = logger; + _runtime = runtime; + _profilingLogger = proflog; _options = options; _lastPruned = _lastSync = DateTime.UtcNow; _syncIdle = new ManualResetEvent(true); - _profilingLogger = appContext.ProfilingLogger; - _logger = appContext.ProfilingLogger.Logger; } + protected ILogger Logger { get; } + + protected DatabaseContext DatabaseContext { get; } + + protected UmbracoDatabase Database => DatabaseContext.Database; + + protected Sql Sql() => DatabaseContext.Sql(); + #region Messenger protected override bool RequiresDistributed(IEnumerable servers, ICacheRefresher refresher, MessageType dispatchType) @@ -74,11 +84,11 @@ namespace Umbraco.Core.Sync IEnumerable ids = null, string json = null) { - var idsA = ids == null ? null : ids.ToArray(); + var idsA = ids?.ToArray(); Type idType; if (GetArrayType(idsA, out idType) == false) - throw new ArgumentException("All items must be of the same type, either int or Guid.", "ids"); + throw new ArgumentException("All items must be of the same type, either int or Guid.", nameof(ids)); var instructions = RefreshInstruction.GetInstructions(refresher, messageType, idsA, idType, json); @@ -89,7 +99,7 @@ namespace Umbraco.Core.Sync OriginIdentity = LocalIdentity }; - ApplicationContext.DatabaseContext.Database.Insert(dto); + Database.Insert(dto); } #endregion @@ -109,7 +119,9 @@ namespace Umbraco.Core.Sync // the service will *not* be able to properly handle our notifications anymore const int weight = 10; - var registered = ApplicationContext.MainDom.Register( + var runtime = _runtime as RuntimeState; + if (runtime == null) throw new NotSupportedException($"Unsupported IRuntimeState implementation {_runtime.GetType().FullName}, expecting {typeof(RuntimeState).FullName}."); + var registered = runtime.MainDom.Register( () => { lock (_locko) @@ -146,7 +158,7 @@ namespace Umbraco.Core.Sync { // we haven't synced - in this case we aren't going to sync the whole thing, we will assume this is a new // server and it will need to rebuild it's own caches, eg Lucene or the xml cache file. - _logger.Warn("No last synced Id found, this generally means this is a new server/install." + Logger.Warn("No last synced Id found, this generally means this is a new server/install." + " The server will build its caches and indexes, and then adjust its last synced Id to the latest found in" + " the database and maintain cache updates based on that Id."); @@ -155,11 +167,11 @@ namespace Umbraco.Core.Sync else { //check for how many instructions there are to process - var count = _appContext.DatabaseContext.Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoCacheInstruction WHERE id > @lastId", new {lastId = _lastId}); + var count = Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoCacheInstruction WHERE id > @lastId", new {lastId = _lastId}); if (count > _options.MaxProcessingInstructionCount) { //too many instructions, proceed to cold boot - _logger.Warn("The instruction count ({0}) exceeds the specified MaxProcessingInstructionCount ({1})." + Logger.Warn("The instruction count ({0}) exceeds the specified MaxProcessingInstructionCount ({1})." + " The server will skip existing instructions, rebuild its caches and indexes entirely, adjust its last synced Id" + " to the latest found in the database and maintain cache updates based on that Id.", () => count, () => _options.MaxProcessingInstructionCount); @@ -173,7 +185,7 @@ namespace Umbraco.Core.Sync // go get the last id in the db and store it // note: do it BEFORE initializing otherwise some instructions might get lost // when doing it before, some instructions might run twice - not an issue - var maxId = _appContext.DatabaseContext.Database.ExecuteScalar("SELECT MAX(id) FROM umbracoCacheInstruction"); + var maxId = Database.ExecuteScalar("SELECT MAX(id) FROM umbracoCacheInstruction"); //if there is a max currently, or if we've never synced if (maxId > 0 || _lastId < 0) @@ -221,7 +233,7 @@ namespace Umbraco.Core.Sync _lastPruned = _lastSync; - switch (_appContext.GetCurrentServerRole()) + switch (Current.RuntimeState.ServerRole) { case ServerRole.Single: case ServerRole.Master: @@ -256,12 +268,12 @@ namespace Umbraco.Core.Sync // // FIXME not true if we're running on a background thread, assuming we can? - var sql = _appContext.DatabaseContext.Sql().SelectAll() + var sql = Sql().SelectAll() .From() .Where(dto => dto.Id > _lastId) .OrderBy(dto => dto.Id); - var dtos = _appContext.DatabaseContext.Database.Fetch(sql); + var dtos = Database.Fetch(sql); if (dtos.Count <= 0) return; // only process instructions coming from a remote server, and ignore instructions coming from @@ -287,7 +299,7 @@ namespace Umbraco.Core.Sync } catch (JsonException ex) { - _logger.Error(string.Format("Failed to deserialize instructions ({0}: \"{1}\").", dto.Id, dto.Instructions), ex); + Logger.Error(string.Format("Failed to deserialize instructions ({0}: \"{1}\").", dto.Id, dto.Instructions), ex); lastId = dto.Id; // skip continue; } @@ -300,8 +312,8 @@ namespace Umbraco.Core.Sync } catch (Exception ex) { - _logger.Error( - string.Format("DISTRIBUTED CACHE IS NOT UPDATED. Failed to execute instructions ({0}: \"{1}\"). Instruction is being skipped/ignored", dto.Id, dto.Instructions), ex); + Logger.Error( + $"DISTRIBUTED CACHE IS NOT UPDATED. Failed to execute instructions ({dto.Id}: \"{dto.Instructions}\"). Instruction is being skipped/ignored", ex); //we cannot throw here because this invalid instruction will just keep getting processed over and over and errors // will be thrown over and over. The only thing we can do is ignore and move on. @@ -327,12 +339,12 @@ namespace Umbraco.Core.Sync // using 2 queries is faster than convoluted joins - var maxId = _appContext.DatabaseContext.Database.ExecuteScalar("SELECT MAX(id) FROM umbracoCacheInstruction;"); + var maxId = Database.ExecuteScalar("SELECT MAX(id) FROM umbracoCacheInstruction;"); var delete = new Sql().Append(@"DELETE FROM umbracoCacheInstruction WHERE utcStamp < @pruneDate AND id < @maxId", new { pruneDate, maxId }); - _appContext.DatabaseContext.Database.Execute(delete); + Database.Execute(delete); } /// @@ -350,10 +362,10 @@ namespace Umbraco.Core.Sync { if (_lastId == 0) { - var sql = _appContext.DatabaseContext.Sql().Select("COUNT(*)") + var sql = Sql().Select("COUNT(*)") .From(); - var count = _appContext.DatabaseContext.Database.ExecuteScalar(sql); + var count = Database.ExecuteScalar(sql); //if there are instructions but we haven't synced, then a cold boot is necessary if (count > 0) @@ -361,11 +373,11 @@ namespace Umbraco.Core.Sync } else { - var sql = _appContext.DatabaseContext.Sql().SelectAll() + var sql = Sql().SelectAll() .From() .Where(dto => dto.Id == _lastId); - var dtos = _appContext.DatabaseContext.Database.Fetch(sql); + var dtos = Database.Fetch(sql); //if the last synced instruction is not found in the db, then a cold boot is necessary if (dtos.Count == 0) diff --git a/src/Umbraco.Core/TypeExtensions.cs b/src/Umbraco.Core/TypeExtensions.cs index a8d4495879..02c08878b8 100644 --- a/src/Umbraco.Core/TypeExtensions.cs +++ b/src/Umbraco.Core/TypeExtensions.cs @@ -426,6 +426,34 @@ namespace Umbraco.Core assemblyName.FullName.StartsWith("App_Code.") ? "App_Code" : assemblyName.Name); } + /// + /// Determines whether an instance of a specified type can be assigned to the current type instance. + /// + /// The current type. + /// The type to compare with the current type. + /// A value indicating whether an instance of the specified type can be assigned to the current type instance. + /// This extended version supports the current type being a generic type definition, and will + /// consider that eg List{int} is "assignable to" IList{}. + public static bool IsAssignableFromGtd(this Type type, Type c) + { + // type *can* be a generic type definition + // c is a real type, cannot be a generic type definition + + if (type.IsGenericTypeDefinition == false) + return type.IsAssignableFrom(c); + + if (c.IsInterface == false) + { + var t = c; + while (t != typeof(object)) + { + if (t.IsGenericType && t.GetGenericTypeDefinition() == type) return true; + t = t.BaseType; + } + } + + return c.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == type); + } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 546146d7a8..6528dc95b0 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -68,7 +68,6 @@ - @@ -274,12 +273,13 @@ - + True True Files.resx + @@ -475,6 +475,8 @@ + + diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 734c3a2ffc..ffa623c507 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -76,10 +76,9 @@ namespace Umbraco.Core _runtime.Boot(container); // this is extra that should get removed - _runtime - .Initialize() - .Startup(appContext => OnApplicationStarting(sender, evargs)) - .Complete(appContext => OnApplicationStarted(sender, evargs)); + ((CoreRuntime)_runtime).Initialize(); + ((CoreRuntime)_runtime).Startup(() => OnApplicationStarting(sender, evargs)); + ((CoreRuntime)_runtime).Complete(() => OnApplicationStarted(sender, evargs)); } // called by ASP.NET (auto event wireup) once per app domain diff --git a/src/Umbraco.Tests/ApplicationContextTests.cs b/src/Umbraco.Tests/ApplicationContextTests.cs index 85e59403e0..19b0ac6136 100644 --- a/src/Umbraco.Tests/ApplicationContextTests.cs +++ b/src/Umbraco.Tests/ApplicationContextTests.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests [Test] public void Is_Configured() { - ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", UmbracoVersion.GetSemanticVersion().ToSemanticString()); + ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", UmbracoVersion.SemanticVersion.ToSemanticString()); var migrationEntryService = new Mock(); migrationEntryService.Setup(x => x.FindEntry(It.IsAny(), It.IsAny())) @@ -32,19 +32,20 @@ namespace Umbraco.Tests var logger = Mock.Of(); var dbCtx = new Mock(databaseFactory, logger); - var appCtx = new ApplicationContext( - dbCtx.Object, - new ServiceContext(migrationEntryService:migrationEntryService.Object), - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(logger, Mock.Of())); + //var appCtx = new ApplicationContext( + // dbCtx.Object, + // new ServiceContext(migrationEntryService:migrationEntryService.Object), + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(logger, Mock.Of())); - Assert.IsTrue(appCtx.IsConfigured); + //Assert.IsTrue(appCtx.IsConfigured); + Assert.Fail("Must rewrite the test with Runtime!"); } [Test] public void Is_Not_Configured_By_Migration_Not_Found() { - ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", UmbracoVersion.GetSemanticVersion().ToSemanticString()); + ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", UmbracoVersion.SemanticVersion.ToSemanticString()); var migrationEntryService = new Mock(); migrationEntryService.Setup(x => x.FindEntry(It.IsAny(), It.IsAny())) @@ -54,13 +55,14 @@ namespace Umbraco.Tests var logger = Mock.Of(); var dbCtx = new Mock(databaseFactory, logger); - var appCtx = new ApplicationContext( - dbCtx.Object, - new ServiceContext(migrationEntryService: migrationEntryService.Object), - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(logger, Mock.Of())); + //var appCtx = new ApplicationContext( + // dbCtx.Object, + // new ServiceContext(migrationEntryService: migrationEntryService.Object), + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(logger, Mock.Of())); - Assert.IsFalse(appCtx.IsConfigured); + //Assert.IsFalse(appCtx.IsConfigured); + Assert.Fail("Must rewrite the test with Runtime!"); } [Test] @@ -74,13 +76,14 @@ namespace Umbraco.Tests var logger = Mock.Of(); var dbCtx = new Mock(databaseFactory, logger); - var appCtx = new ApplicationContext( - dbCtx.Object, - new ServiceContext(migrationEntryService: migrationEntryService.Object), - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(logger, Mock.Of())); + //var appCtx = new ApplicationContext( + // dbCtx.Object, + // new ServiceContext(migrationEntryService: migrationEntryService.Object), + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(logger, Mock.Of())); - Assert.IsFalse(appCtx.IsConfigured); + //Assert.IsFalse(appCtx.IsConfigured); + Assert.Fail("Must rewrite the test with Runtime!"); } [Test] @@ -94,13 +97,14 @@ namespace Umbraco.Tests var logger = Mock.Of(); var dbCtx = new Mock(databaseFactory, logger); - var appCtx = new ApplicationContext( - dbCtx.Object, - new ServiceContext(migrationEntryService: migrationEntryService.Object), - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // dbCtx.Object, + // new ServiceContext(migrationEntryService: migrationEntryService.Object), + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); - Assert.IsFalse(appCtx.IsConfigured); + //Assert.IsFalse(appCtx.IsConfigured); + Assert.Fail("Must rewrite the test with Runtime!"); } [Test] @@ -114,13 +118,14 @@ namespace Umbraco.Tests var logger = Mock.Of(); var dbCtx = new Mock(databaseFactory, logger); - var appCtx = new ApplicationContext( - dbCtx.Object, - new ServiceContext(migrationEntryService: migrationEntryService.Object), - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // dbCtx.Object, + // new ServiceContext(migrationEntryService: migrationEntryService.Object), + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); - Assert.IsFalse(appCtx.IsConfigured); + //Assert.IsFalse(appCtx.IsConfigured); + Assert.Fail("Must rewrite the test with Runtime!"); } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/ApplicationUrlHelperTests.cs b/src/Umbraco.Tests/ApplicationUrlHelperTests.cs index 0a6e2dd085..a2dc372b17 100644 --- a/src/Umbraco.Tests/ApplicationUrlHelperTests.cs +++ b/src/Umbraco.Tests/ApplicationUrlHelperTests.cs @@ -1,3 +1,4 @@ +using System; using System.Configuration; using System.IO; using System.Linq; @@ -47,9 +48,11 @@ namespace Umbraco.Tests [Test] public void NoApplicationUrlByDefault() { - var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); - Assert.IsNull(appCtx._umbracoApplicationUrl); + //var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); + //Assert.IsNull(appCtx._umbracoApplicationUrl); + var state = new RuntimeState(Mock.Of(), new Lazy(Mock.Of), new Lazy(Mock.Of)); + Assert.IsNull(state.ApplicationUrl); } [Test] @@ -59,21 +62,23 @@ namespace Umbraco.Tests var settings = Mock.Of(section => section.DistributedCall == Mock.Of(callSection => callSection.Servers == Enumerable.Empty()) - && section.WebRouting == Mock.Of(wrSection => wrSection.UmbracoApplicationUrl == (string)null) + && section.WebRouting == Mock.Of(wrSection => wrSection.UmbracoApplicationUrl == (string) null) && section.ScheduledTasks == Mock.Of()); ApplicationUrlHelper.ApplicationUrlProvider = request => "http://server1.com/umbraco"; Initialize(settings); - var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + var state = new RuntimeState(Mock.Of(), new Lazy(Mock.Of), new Lazy(Mock.Of)); + //var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); // does not make a diff here - ApplicationUrlHelper.EnsureApplicationUrl(appCtx, settings: settings); + //ApplicationUrlHelper.EnsureApplicationUrl(appCtx, settings: settings); + state.EnsureApplicationUrl(settings: settings); - Assert.AreEqual("http://server1.com/umbraco", appCtx._umbracoApplicationUrl); + Assert.AreEqual("http://server1.com/umbraco", state.ApplicationUrl); } [Test] @@ -88,15 +93,12 @@ namespace Umbraco.Tests Initialize(settings); - var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); - ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); // does not make a diff here - ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings); + var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of()); // still NOT set - Assert.IsNull(appCtx._umbracoApplicationUrl); + Assert.IsNull(url); } [Test] @@ -116,14 +118,11 @@ namespace Umbraco.Tests Initialize(settings); - var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); - ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); - ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings); + var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of()); - Assert.AreEqual("http://server1.com:80/umbraco", appCtx._umbracoApplicationUrl); + Assert.AreEqual("http://server1.com:80/umbraco", url); var role = _registrar.GetCurrentServerRole(); Assert.AreEqual(ServerRole.Master, role); @@ -146,14 +145,11 @@ namespace Umbraco.Tests Initialize(settings); - var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); - ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); - ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings); + var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of()); - Assert.AreEqual("http://server1.com:80/umbraco", appCtx._umbracoApplicationUrl); + Assert.AreEqual("http://server1.com:80/umbraco", url); var role = _registrar.GetCurrentServerRole(); Assert.AreEqual(ServerRole.Slave, role); @@ -176,14 +172,11 @@ namespace Umbraco.Tests Initialize(settings); - var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); - ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); - ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings); + var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of()); - Assert.IsNull(appCtx._umbracoApplicationUrl); + Assert.IsNull(url); var role = _registrar.GetCurrentServerRole(); Assert.AreEqual(ServerRole.Single, role); @@ -250,14 +243,11 @@ namespace Umbraco.Tests Initialize(settings); - var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); - ConfigurationManager.AppSettings.Set("umbracoUseSSL", "false"); - ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings); + var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of()); - Assert.AreEqual("http://mycoolhost.com/umbraco", appCtx._umbracoApplicationUrl); + Assert.AreEqual("http://mycoolhost.com/umbraco", url); } [Test] @@ -270,14 +260,11 @@ namespace Umbraco.Tests Initialize(settings); - var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); - ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); - ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings); + var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of()); - Assert.AreEqual("https://mycoolhost.com/umbraco", appCtx._umbracoApplicationUrl); + Assert.AreEqual("https://mycoolhost.com/umbraco", url); } [Test] @@ -290,14 +277,11 @@ namespace Umbraco.Tests Initialize(settings); - var appCtx = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); - ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); // does not make a diff here - ApplicationUrlHelper.TrySetApplicationUrl(appCtx, settings); + var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of()); - Assert.AreEqual("httpx://whatever.com/umbraco", appCtx._umbracoApplicationUrl); + Assert.AreEqual("httpx://whatever.com/umbraco", url); } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs index 3f3644b8ae..c6a4ad7aae 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs @@ -25,7 +25,7 @@ namespace Umbraco.Tests.Cache.PublishedCache private string GetXml() { - return @" @@ -53,7 +53,7 @@ namespace Umbraco.Tests.Cache.PublishedCache base.Initialize(); _httpContextFactory = new FakeHttpContextFactory("~/Home"); - + var settings = SettingsForTests.GenerateMockSettings(); SettingsForTests.ConfigureSettings(settings); @@ -65,15 +65,15 @@ namespace Umbraco.Tests.Cache.PublishedCache var facade = new Facade( new PublishedContentCache(xmlStore, domainCache, cacheProvider, ContentTypesCache, null, null), new PublishedMediaCache(xmlStore, ServiceContext.MediaService, ServiceContext.UserService, cacheProvider, ContentTypesCache), - new PublishedMemberCache(null, cacheProvider, ApplicationContext.Services.MemberService, ContentTypesCache), + new PublishedMemberCache(null, cacheProvider, Current.Services.MemberService, ContentTypesCache), domainCache); var facadeService = new Mock(); facadeService.Setup(x => x.CreateFacade(It.IsAny())).Returns(facade); _umbracoContext = UmbracoContext.CreateContext( - _httpContextFactory.HttpContext, ApplicationContext, + _httpContextFactory.HttpContext, facadeService.Object, - new WebSecurity(_httpContextFactory.HttpContext, ApplicationContext), + new WebSecurity(_httpContextFactory.HttpContext, Current.Services.UserService), settings, Enumerable.Empty()); @@ -111,9 +111,9 @@ namespace Umbraco.Tests.Cache.PublishedCache Assert.AreEqual(nodeId, result.Id); } - - [TestCase("/", 1046)] + + [TestCase("/", 1046)] [TestCase("/sub1", 1173)] [TestCase("/Sub1", 1173)] public void Get_Node_By_Route_Hiding_Top_Level_Nodes(string route, int nodeId) diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index e2bcc2a9b1..30dfc6da0b 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -21,6 +21,7 @@ using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Web.PublishedCache.XmlPublishedCache; using Umbraco.Core.DependencyInjection; +using Current = Umbraco.Web.Current; namespace Umbraco.Tests.Cache.PublishedCache { @@ -65,7 +66,7 @@ namespace Umbraco.Tests.Cache.PublishedCache //var publishedMedia = PublishedMediaTests.GetNode(mRoot.Id, GetUmbracoContext("/test", 1234)); var umbracoContext = GetUmbracoContext("/test", 1234); - var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null), umbracoContext.Application.Services.MediaService, umbracoContext.Application.Services.UserService, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null), Current.Services.MediaService, Current.Services.UserService, new StaticCacheProvider(), ContentTypesCache); var publishedMedia = cache.GetById(mRoot.Id); Assert.IsNotNull(publishedMedia); diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index 1cfc8993e5..b5b25a92e9 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using LightInject; using Moq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Components; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Logging; @@ -38,7 +39,7 @@ namespace Umbraco.Tests.Components var thing = new BootLoader(container); Composed.Clear(); - thing.Boot(new [] { typeof (Component1), typeof (Component2), typeof (Component3), typeof (Component4) }); + thing.Boot(new [] { typeof (Component1), typeof (Component2), typeof (Component3), typeof (Component4) }, RuntimeLevel.Unknown); Assert.AreEqual(4, Composed.Count); Assert.AreEqual(typeof(Component1), Composed[0]); Assert.AreEqual(typeof(Component4), Composed[1]); @@ -62,7 +63,7 @@ namespace Umbraco.Tests.Components Composed.Clear(); try { - thing.Boot(new[] { typeof(Component1), typeof(Component2), typeof(Component3) }); + thing.Boot(new[] { typeof(Component1), typeof(Component2), typeof(Component3) }, RuntimeLevel.Unknown); Assert.Fail("Expected exception."); } catch (Exception e) @@ -87,7 +88,7 @@ namespace Umbraco.Tests.Components var thing = new BootLoader(container); Composed.Clear(); - thing.Boot(new[] { typeof(Component1), typeof(Component5) }); + thing.Boot(new[] { typeof(Component1), typeof(Component5) }, RuntimeLevel.Unknown); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component1), Composed[0]); Assert.AreEqual(typeof(Component5), Composed[1]); @@ -109,7 +110,7 @@ namespace Umbraco.Tests.Components var thing = new BootLoader(container); Composed.Clear(); - thing.Boot(new[] { typeof(Component6), typeof(Component7), typeof(Component8) }); + thing.Boot(new[] { typeof(Component6), typeof(Component7), typeof(Component8) }, RuntimeLevel.Unknown); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component6), Composed[0]); Assert.AreEqual(typeof(Component8), Composed[1]); @@ -129,7 +130,7 @@ namespace Umbraco.Tests.Components var thing = new BootLoader(container); Composed.Clear(); - thing.Boot(new[] { typeof(Component9), typeof(Component2), typeof(Component4) }); + thing.Boot(new[] { typeof(Component9), typeof(Component2), typeof(Component4) }, RuntimeLevel.Unknown); Assert.AreEqual(3, Composed.Count); Assert.AreEqual(typeof(Component4), Composed[0]); Assert.AreEqual(typeof(Component2), Composed[1]); @@ -150,21 +151,21 @@ namespace Umbraco.Tests.Components var thing = new BootLoader(container); Composed.Clear(); - thing.Boot(new[] { typeof(Component10) }); + thing.Boot(new[] { typeof(Component10) }, RuntimeLevel.Unknown); Assert.AreEqual(1, Composed.Count); Assert.AreEqual(typeof(Component10), Composed[0]); thing = new BootLoader(container); Composed.Clear(); - Assert.Throws(() => thing.Boot(new[] { typeof(Component11) })); + Assert.Throws(() => thing.Boot(new[] { typeof(Component11) }, RuntimeLevel.Unknown)); thing = new BootLoader(container); Composed.Clear(); - Assert.Throws(() => thing.Boot(new[] { typeof(Component2) })); + Assert.Throws(() => thing.Boot(new[] { typeof(Component2) }, RuntimeLevel.Unknown)); thing = new BootLoader(container); Composed.Clear(); - thing.Boot(new[] { typeof(Component12) }); + thing.Boot(new[] { typeof(Component12) }, RuntimeLevel.Unknown); Assert.AreEqual(1, Composed.Count); Assert.AreEqual(typeof(Component12), Composed[0]); } @@ -183,7 +184,7 @@ namespace Umbraco.Tests.Components var thing = new BootLoader(container); Composed.Clear(); - thing.Boot(new[] { typeof(Component6), typeof(Component8) }); // 8 disables 7 which is not in the list + thing.Boot(new[] { typeof(Component6), typeof(Component8) }, RuntimeLevel.Unknown); // 8 disables 7 which is not in the list Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component6), Composed[0]); Assert.AreEqual(typeof(Component8), Composed[1]); diff --git a/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs b/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs index 8b6b80979e..0f671de08e 100644 --- a/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs +++ b/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Configurations [Test] public void Is_Version_From_Assembly_Correct() { - Assert.That(UmbracoVersion.GetSemanticVersion(), Is.EqualTo("6.0.0")); + Assert.That(UmbracoVersion.SemanticVersion, Is.EqualTo("6.0.0")); } [TestCase("~/umbraco", "/", "umbraco")] diff --git a/src/Umbraco.Tests/Macros/MacroTests.cs b/src/Umbraco.Tests/Macros/MacroTests.cs index 14f857db24..7ec4343647 100644 --- a/src/Umbraco.Tests/Macros/MacroTests.cs +++ b/src/Umbraco.Tests/Macros/MacroTests.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Macros new StaticCacheProvider(), new NullCacheProvider(), new IsolatedRuntimeCache(type => new ObjectCacheRuntimeCacheProvider())); - Current.ApplicationContext = new ApplicationContext(cacheHelper, new ProfilingLogger(Mock.Of(), Mock.Of())); + //Current.ApplicationContext = new ApplicationContext(cacheHelper, new ProfilingLogger(Mock.Of(), Mock.Of())); UmbracoConfig.For.SetUmbracoSettings(SettingsForTests.GetDefault()); } @@ -42,8 +42,8 @@ namespace Umbraco.Tests.Macros [TearDown] public void TearDown() { - Current.ApplicationContext.ApplicationCache.RuntimeCache.ClearAllCache(); - Current.ApplicationContext.DisposeIfDisposable(); + Current.ApplicationCache.RuntimeCache.ClearAllCache(); + //Current.ApplicationContext.DisposeIfDisposable(); Current.Reset(); } diff --git a/src/Umbraco.Tests/MockTests.cs b/src/Umbraco.Tests/MockTests.cs index f39171fc0c..81d74d140f 100644 --- a/src/Umbraco.Tests/MockTests.cs +++ b/src/Umbraco.Tests/MockTests.cs @@ -45,10 +45,10 @@ namespace Umbraco.Tests [Test] public void Can_Create_Empty_App_Context() { - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); - Assert.Pass(); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); + //Assert.Pass(); } [Test] @@ -63,34 +63,19 @@ namespace Umbraco.Tests { var databaseFactory = TestObjects.GetIDatabaseFactoryMock(); var logger = Mock.Of(); - var dbCtx = new DatabaseContext(databaseFactory, logger); - Assert.Pass(); - } - - [Test] - public void Can_Create_App_Context_With_Services() - { - var databaseFactory = TestObjects.GetIDatabaseFactoryMock(); - var logger = Mock.Of(); - - var appCtx = new ApplicationContext( - new DatabaseContext(databaseFactory, logger), - TestObjects.GetServiceContextMock(), - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(logger, Mock.Of())); - + var dbCtx = new DatabaseContext(databaseFactory, logger, Mock.Of(), Mock.Of()); Assert.Pass(); } [Test] public void Can_Get_Umbraco_Context() { - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.EnsureContext( - Mock.Of(), appCtx, + Mock.Of(), Mock.Of(), new Mock(null, null).Object, Mock.Of(), @@ -103,9 +88,9 @@ namespace Umbraco.Tests [Test] public void Can_Mock_Umbraco_Helper() { - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var facade = new Mock(); facade.Setup(x => x.MemberCache).Returns(Mock.Of()); @@ -113,7 +98,7 @@ namespace Umbraco.Tests facadeService.Setup(x => x.CreateFacade(It.IsAny())).Returns(facade.Object); var umbCtx = UmbracoContext.EnsureContext( - Mock.Of(), appCtx, + Mock.Of(), facadeService.Object, new Mock(null, null).Object, Mock.Of(), @@ -127,7 +112,9 @@ namespace Umbraco.Tests Mock.Of(), new UrlProvider(umbCtx, new[] {Mock.Of()}, UrlProviderMode.Auto), Mock.Of(), Mock.Of(), - new MembershipHelper(umbCtx, Mock.Of(), Mock.Of())); + new MembershipHelper(umbCtx, Mock.Of(), Mock.Of()), + new ServiceContext(), + CacheHelper.CreateDisabledCacheHelper()); Assert.Pass(); } @@ -135,9 +122,9 @@ namespace Umbraco.Tests [Test] public void Can_Mock_Umbraco_Helper_Get_Url() { - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var facade = new Mock(); facade.Setup(x => x.MemberCache).Returns(Mock.Of()); @@ -145,7 +132,7 @@ namespace Umbraco.Tests facadeService.Setup(x => x.CreateFacade(It.IsAny())).Returns(facade.Object); var umbCtx = UmbracoContext.EnsureContext( - Mock.Of(), appCtx, + Mock.Of(), facadeService.Object, new Mock(null, null).Object, Mock.Of(), @@ -166,7 +153,9 @@ namespace Umbraco.Tests urlHelper.Object }, UrlProviderMode.Auto), Mock.Of(), Mock.Of(), - new MembershipHelper(umbCtx, Mock.Of(), Mock.Of())); + new MembershipHelper(umbCtx, Mock.Of(), Mock.Of()), + new ServiceContext(), + CacheHelper.CreateDisabledCacheHelper()); Assert.AreEqual("/hello/world/1234", helper.Url(1234)); } diff --git a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs index 0d9c11ef8c..2cbfe60f92 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs @@ -44,21 +44,21 @@ namespace Umbraco.Tests.Models.Mapping var databaseFactory = TestObjects.GetIDatabaseFactoryMock(); - //Create an app context using mocks - var appContext = new ApplicationContext( - new DatabaseContext(databaseFactory, logger), + ////Create an app context using mocks + //var appContext = new ApplicationContext( + // new DatabaseContext(databaseFactory, logger, Mock.Of(), Mock.Of()), - //Create service context using mocks - new ServiceContext( + // //Create service context using mocks + // new ServiceContext( - contentService: _contentService.Object, - contentTypeService:_contentTypeService.Object, - dataTypeService:_dataTypeService.Object, - entityService:_entityService.Object, - fileService: _fileService.Object), + // contentService: _contentService.Object, + // contentTypeService:_contentTypeService.Object, + // dataTypeService:_dataTypeService.Object, + // entityService:_entityService.Object, + // fileService: _fileService.Object), - nullCacheHelper, - new ProfilingLogger(logger, Mock.Of())); + // nullCacheHelper, + // new ProfilingLogger(logger, Mock.Of())); // create a fake property editor collection to return fake property editors var editors = new PropertyEditor[] { new TextboxPropertyEditor(Mock.Of()), }; @@ -68,10 +68,10 @@ namespace Umbraco.Tests.Models.Mapping Mapper.Initialize(configuration => { //initialize our content type mapper - var mapper = new ContentTypeModelMapper(editorsMock.Object); - mapper.ConfigureMappings(configuration, appContext); + var mapper = new ContentTypeModelMapper(editorsMock.Object, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); + mapper.ConfigureMappings(configuration); var entityMapper = new EntityModelMapper(); - entityMapper.ConfigureMappings(configuration, appContext); + entityMapper.ConfigureMappings(configuration); }); } diff --git a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs index c03cf341e8..2c788e38d7 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs @@ -120,10 +120,10 @@ namespace Umbraco.Tests.Models.Mapping AssertBasics(result, content); foreach (var p in content.Properties) { - AssertDisplayProperty(result, p, ApplicationContext); + AssertDisplayProperty(result, p); } Assert.AreEqual(content.PropertyGroups.Count(), result.Tabs.Count() - 1); - Assert.IsTrue(result.Tabs.Any(x => x.Label == ApplicationContext.Services.TextService.Localize("general/properties"))); + Assert.IsTrue(result.Tabs.Any(x => x.Label == Current.Services.TextService.Localize("general/properties"))); Assert.IsTrue(result.Tabs.First().IsActive); Assert.IsTrue(result.Tabs.Except(new[] {result.Tabs.First()}).All(x => x.IsActive == false)); } @@ -166,16 +166,16 @@ namespace Umbraco.Tests.Models.Mapping AssertBasics(result, content); foreach (var p in content.Properties) { - AssertDisplayProperty(result, p, ApplicationContext); + AssertDisplayProperty(result, p); } Assert.AreEqual(content.PropertyGroups.Count(), result.Tabs.Count() - 1); - Assert.IsTrue(result.Tabs.Any(x => x.Label == ApplicationContext.Services.TextService.Localize("general/properties"))); - Assert.AreEqual(2, result.Tabs.Where(x => x.Label == ApplicationContext.Services.TextService.Localize("general/properties")).SelectMany(x => x.Properties.Where(p => p.Alias.StartsWith("_umb_") == false)).Count()); + Assert.IsTrue(result.Tabs.Any(x => x.Label == Current.Services.TextService.Localize("general/properties"))); + Assert.AreEqual(2, result.Tabs.Where(x => x.Label == Current.Services.TextService.Localize("general/properties")).SelectMany(x => x.Properties.Where(p => p.Alias.StartsWith("_umb_") == false)).Count()); } #region Assertions - private void AssertDisplayProperty(ContentItemBasic result, Property p, ApplicationContext applicationContext) + private void AssertDisplayProperty(ContentItemBasic result, Property p) where T : ContentPropertyDisplay where TPersisted : IContentBase { @@ -233,7 +233,7 @@ namespace Umbraco.Tests.Models.Mapping Assert.AreEqual(p.PropertyType.ValidationRegExp, pDto.ValidationRegExp); Assert.AreEqual(p.PropertyType.Description, pDto.Description); Assert.AreEqual(p.PropertyType.Name, pDto.Label); - Assert.AreEqual(ApplicationContext.Services.DataTypeService.GetDataTypeDefinitionById(p.PropertyType.DataTypeDefinitionId), pDto.DataType); + Assert.AreEqual(Current.Services.DataTypeService.GetDataTypeDefinitionById(p.PropertyType.DataTypeDefinitionId), pDto.DataType); Assert.AreEqual(Current.PropertyEditors[p.PropertyType.PropertyEditorAlias], pDto.PropertyEditor); } diff --git a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs index ef9c59b3c8..aebe87e40c 100644 --- a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs +++ b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs @@ -25,8 +25,11 @@ namespace Umbraco.Tests.Persistence private ILogger _logger; private SqlCeSyntaxProvider _sqlCeSyntaxProvider; private ISqlSyntaxProvider[] _sqlSyntaxProviders; + private IRuntimeState _runtime; + private IMigrationEntryService _migrationEntryService; - [SetUp] + + [SetUp] public void Setup() { // create the database factory and database context @@ -34,7 +37,9 @@ namespace Umbraco.Tests.Persistence _sqlSyntaxProviders = new[] { (ISqlSyntaxProvider) _sqlCeSyntaxProvider }; _logger = Mock.Of(); var dbFactory = new DefaultDatabaseFactory(Core.Configuration.GlobalSettings.UmbracoConnectionName, _sqlSyntaxProviders, _logger, new TestUmbracoDatabaseAccessor(), Mock.Of()); - _dbContext = new DatabaseContext(dbFactory, _logger); + _runtime = Mock.Of(); + _migrationEntryService = Mock.Of(); + _dbContext = new DatabaseContext(dbFactory, _logger, _runtime, _migrationEntryService); } [TearDown] @@ -85,18 +90,18 @@ namespace Umbraco.Tests.Persistence // re-create the database factory and database context with proper connection string var dbFactory = new DefaultDatabaseFactory(connString, Constants.DbProviderNames.SqlCe, _sqlSyntaxProviders, _logger, new TestUmbracoDatabaseAccessor(), Mock.Of()); - _dbContext = new DatabaseContext(dbFactory, _logger); + _dbContext = new DatabaseContext(dbFactory, _logger, _runtime, _migrationEntryService); // create application context - var appCtx = new ApplicationContext( - _dbContext, - new ServiceContext(migrationEntryService: Mock.Of()), - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // _dbContext, + // new ServiceContext(migrationEntryService: Mock.Of()), + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); // create the umbraco database var schemaHelper = new DatabaseSchemaHelper(_dbContext.Database, _logger); - schemaHelper.CreateDatabaseSchema(false, appCtx); + schemaHelper.CreateDatabaseSchema(_runtime, _migrationEntryService, false); var umbracoNodeTable = schemaHelper.TableExist("umbracoNode"); var umbracoUserTable = schemaHelper.TableExist("umbracoUser"); @@ -119,7 +124,7 @@ namespace Umbraco.Tests.Persistence [TestCase("tcp:MyServer.database.windows.net,1433", "MyDatabase", "MyUser@MyServer", "MyPassword")] public void Build_Azure_Connection_String_Regular(string server, string databaseName, string userName, string password) { - var connectionString = _dbContext.GetAzureConnectionString(server, databaseName, userName, password); + var connectionString = DatabaseContext.GetAzureConnectionString(server, databaseName, userName, password); Assert.AreEqual(connectionString, "Server=tcp:MyServer.database.windows.net,1433;Database=MyDatabase;User ID=MyUser@MyServer;Password=MyPassword"); } @@ -129,7 +134,7 @@ namespace Umbraco.Tests.Persistence [TestCase("tcp:kzeej5z8ty.ssmsawacluster4.windowsazure.mscds.com", "MyDatabase", "MyUser@kzeej5z8ty", "MyPassword")] public void Build_Azure_Connection_String_CustomServer(string server, string databaseName, string userName, string password) { - var connectionString = _dbContext.GetAzureConnectionString(server, databaseName, userName, password); + var connectionString = DatabaseContext.GetAzureConnectionString(server, databaseName, userName, password); Assert.AreEqual(connectionString, "Server=tcp:kzeej5z8ty.ssmsawacluster4.windowsazure.mscds.com,1433;Database=MyDatabase;User ID=MyUser@kzeej5z8ty;Password=MyPassword"); } } diff --git a/src/Umbraco.Tests/Persistence/Migrations/MigrationStartupHandlerTests.cs b/src/Umbraco.Tests/Persistence/Migrations/MigrationStartupHandlerTests.cs index 5ee9f041fa..240c93e696 100644 --- a/src/Umbraco.Tests/Persistence/Migrations/MigrationStartupHandlerTests.cs +++ b/src/Umbraco.Tests/Persistence/Migrations/MigrationStartupHandlerTests.cs @@ -33,7 +33,7 @@ namespace Umbraco.Tests.Persistence.Migrations var changed1 = new Args { CountExecuted = 0 }; var testHandler1 = new TestMigrationHandler(changed1); - testHandler1.OnApplicationStarting(Mock.Of(), new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(logger, Mock.Of()))); + testHandler1.OnApplicationStarting(Mock.Of()); var db = TestObjects.GetUmbracoSqlCeDatabase(logger); var migrationContext = new MigrationContext(db, logger); @@ -50,11 +50,11 @@ namespace Umbraco.Tests.Persistence.Migrations var changed1 = new Args { CountExecuted = 0}; var testHandler1 = new TestMigrationHandler("Test1", changed1); - testHandler1.OnApplicationStarting(Mock.Of(), new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(logger, Mock.Of()))); + testHandler1.OnApplicationStarting(Mock.Of()); var changed2 = new Args { CountExecuted = 0 }; var testHandler2 = new TestMigrationHandler("Test2", changed2); - testHandler2.OnApplicationStarting(Mock.Of(), new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(logger, Mock.Of()))); + testHandler2.OnApplicationStarting(Mock.Of()); var db = TestObjects.GetUmbracoSqlCeDatabase(logger); var migrationContext = new MigrationContext(db, logger); diff --git a/src/Umbraco.Tests/Plugins/TypeHelperTests.cs b/src/Umbraco.Tests/Plugins/TypeHelperTests.cs index 51166a46c0..93889555f4 100644 --- a/src/Umbraco.Tests/Plugins/TypeHelperTests.cs +++ b/src/Umbraco.Tests/Plugins/TypeHelperTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data.Odbc; @@ -9,11 +8,8 @@ using System.Linq; using System.Reflection; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Models; using Umbraco.Core.Plugins; -using Umbraco.Tests.DynamicsAndReflection; using Umbraco.Web.Cache; -using Umbraco.Web.Models; using Umbraco.Web.Scheduling; namespace Umbraco.Tests.Plugins @@ -81,7 +77,7 @@ namespace Umbraco.Tests.Plugins Assert.AreEqual(typeof(PropertyAliasDto), t5.Result); var t6 = TypeHelper.GetLowestBaseType(typeof (IApplicationEventHandler), - typeof (Scheduler), + typeof (SchedulerComponent), typeof(CacheRefresherEventHandler)); Assert.IsTrue(t6.Success); Assert.AreEqual(typeof(IApplicationEventHandler), t6.Result); diff --git a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs index a8509145db..d49af00e18 100644 --- a/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/MultiValuePropertyEditorTests.cs @@ -100,17 +100,17 @@ namespace Umbraco.Tests.PropertyEditors var logger = Mock.Of(); var textService = new Mock(); textService.Setup(x => x.Localize(It.IsAny(), It.IsAny(), It.IsAny>())).Returns("blah"); - var appContext = new ApplicationContext( - new DatabaseContext(TestObjects.GetIDatabaseFactoryMock(), logger), - new ServiceContext( - localizedTextService: textService.Object - ), - Mock.Of(), - new ProfilingLogger(logger, Mock.Of())) - { - IsReady = true - }; - Current.ApplicationContext = appContext; + //var appContext = new ApplicationContext( + // new DatabaseContext(TestObjects.GetIDatabaseFactoryMock(), logger, Mock.Of(), Mock.Of()), + // new ServiceContext( + // localizedTextService: textService.Object + // ), + // Mock.Of(), + // new ProfilingLogger(logger, Mock.Of())) + //{ + // //IsReady = true + //}; + //Current.ApplicationContext = appContext; var defaultVals = new Dictionary(); var persisted = new PreValueCollection(new Dictionary diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs index 31d2db1d89..c73cebe3f5 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentDataTableTests.cs @@ -72,7 +72,7 @@ namespace Umbraco.Tests.PublishedContent public void To_DataTable() { var doc = GetContent(true, 1); - var dt = doc.ChildrenAsTable(ApplicationContext.Services); + var dt = doc.ChildrenAsTable(Current.Services); Assert.AreEqual(11, dt.Columns.Count); Assert.AreEqual(3, dt.Rows.Count); @@ -94,7 +94,7 @@ namespace Umbraco.Tests.PublishedContent //change a doc type alias ((TestPublishedContent) doc.Children.ElementAt(0)).DocumentTypeAlias = "DontMatch"; - var dt = doc.ChildrenAsTable(ApplicationContext.Services, "Child"); + var dt = doc.ChildrenAsTable(Current.Services, "Child"); Assert.AreEqual(11, dt.Columns.Count); Assert.AreEqual(2, dt.Rows.Count); @@ -110,7 +110,7 @@ namespace Umbraco.Tests.PublishedContent public void To_DataTable_No_Rows() { var doc = GetContent(false, 1); - var dt = doc.ChildrenAsTable(ApplicationContext.Services); + var dt = doc.ChildrenAsTable(Current.Services); //will return an empty data table Assert.AreEqual(0, dt.Columns.Count); Assert.AreEqual(0, dt.Rows.Count); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentExtensionTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentExtensionTests.cs index e2e1b91087..982dc8f04f 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentExtensionTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentExtensionTests.cs @@ -72,7 +72,7 @@ namespace Umbraco.Tests.PublishedContent ctx = GetUmbracoContext("/", 1, null, true); if (createContentTypes) { - var contentTypeService = ctx.Application.Services.ContentTypeService; + var contentTypeService = Current.Services.ContentTypeService; var baseType = new ContentType(-1) {Alias = "base", Name = "Base"}; const string contentTypeAlias = "inherited"; var inheritedType = new ContentType(baseType, contentTypeAlias) {Alias = contentTypeAlias, Name = "Inherited"}; diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs index 678f11dca2..036b7c59b0 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs @@ -14,6 +14,7 @@ using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Core.DependencyInjection; +using Current = Umbraco.Core.DependencyInjection.Current; namespace Umbraco.Tests.PublishedContent { @@ -32,7 +33,7 @@ namespace Umbraco.Tests.PublishedContent base.Initialize(); // this is so the model factory looks into the test assembly - _pluginManager = PluginManager.Current; + _pluginManager = Current.PluginManager; Core.DependencyInjection.Current.PluginManager = new PluginManager(new NullCacheProvider(), ProfilingLogger, false) { AssembliesToScan = _pluginManager.AssembliesToScan @@ -46,7 +47,7 @@ namespace Umbraco.Tests.PublishedContent { PropertyValueConverterCollectionBuilder.Register(Container); - var types = PluginManager.Current.ResolveTypes(); + var types = Current.PluginManager.ResolveTypes(); Container.RegisterSingleton(_ => new PublishedContentModelFactory(types)); base.FreezeResolution(); @@ -63,9 +64,9 @@ namespace Umbraco.Tests.PublishedContent var httpContext = GetHttpContextFactory("http://umbraco.local/", routeData).HttpContext; var ctx = UmbracoContext.CreateContext( - httpContext, ApplicationContext, + httpContext, facadeService.Object, - new WebSecurity(httpContext, ApplicationContext), + new WebSecurity(httpContext, Current.Services.UserService), Mock.Of(), Enumerable.Empty()); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index 0073eb691b..5de34c6fc3 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -10,6 +10,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Core.DependencyInjection; +using Current = Umbraco.Core.DependencyInjection.Current; namespace Umbraco.Tests.PublishedContent { @@ -29,7 +30,7 @@ namespace Umbraco.Tests.PublishedContent base.Initialize(); // this is so the model factory looks into the test assembly - _pluginManager = PluginManager.Current; + _pluginManager = Current.PluginManager; Core.DependencyInjection.Current.PluginManager = new PluginManager(CacheHelper.RuntimeCache, ProfilingLogger, false) { AssembliesToScan = _pluginManager.AssembliesToScan @@ -65,7 +66,7 @@ namespace Umbraco.Tests.PublishedContent protected override void FreezeResolution() { - var types = PluginManager.Current.ResolveTypes(); + var types = Current.PluginManager.ResolveTypes(); Container.RegisterSingleton(_ => new PublishedContentModelFactory(types)); base.FreezeResolution(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index 955fd82e8c..07893050e4 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -2,7 +2,6 @@ using System.Web; using System.Xml.Linq; using System.Xml.XPath; using Lucene.Net.Store; -using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; @@ -10,18 +9,15 @@ using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.UmbracoExamine; using Umbraco.Web; -using Umbraco.Web.PublishedCache; using Umbraco.Web.PublishedCache.XmlPublishedCache; using System.Linq; using System.Xml; using Examine.Session; -using LightInject; using Umbraco.Core.Cache; -using Umbraco.Core.DependencyInjection; -using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Strings; using UmbracoExamine; +using Current = Umbraco.Web.Current; namespace Umbraco.Tests.PublishedContent { @@ -51,7 +47,7 @@ namespace Umbraco.Tests.PublishedContent /// internal IPublishedContent GetNode(int id, UmbracoContext umbracoContext) { - var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null), umbracoContext.Application.Services.MediaService, umbracoContext.Application.Services.UserService, new StaticCacheProvider(), ContentTypesCache); + var cache = new PublishedMediaCache(new XmlStore((XmlDocument)null), Current.Services.MediaService, Current.Services.UserService, new StaticCacheProvider(), ContentTypesCache); var doc = cache.GetById(id); Assert.IsNotNull(doc); return doc; diff --git a/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlAndTemplateTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlAndTemplateTests.cs index 6a4cbd1860..0512ac303e 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlAndTemplateTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByNiceUrlAndTemplateTests.cs @@ -5,6 +5,7 @@ using Umbraco.Tests.TestHelpers; using Umbraco.Web.Routing; using umbraco.BusinessLogic; using Umbraco.Core.Models; +using Current = Umbraco.Web.Current; namespace Umbraco.Tests.Routing { @@ -16,7 +17,7 @@ namespace Umbraco.Tests.Routing { var template = new Template(alias, alias); template.Content = ""; // else saving throws with a dirty internal error - ApplicationContext.Services.FileService.SaveTemplate(template); + Current.Services.FileService.SaveTemplate(template); return template; } diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 8d329a7a2a..2a448f4218 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -1,4 +1,6 @@ -using System.Web.Mvc; +using System; +using System.Linq; +using System.Web.Mvc; using System.Web.Routing; using LightInject; using Moq; @@ -13,7 +15,6 @@ using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Web.Routing; using Umbraco.Web.WebApi; -using Umbraco.Core.Plugins; using Umbraco.Core.Strings; using Umbraco.Core.DependencyInjection; using Current = Umbraco.Web.Current; @@ -25,21 +26,19 @@ namespace Umbraco.Tests.Routing public class RenderRouteHandlerTests : BaseRoutingTest { public override void Initialize() - { + { base.Initialize(); SettingsForTests.UmbracoPath = "~/umbraco"; - - var webBoot = new TestRuntime(new UmbracoApplication()); - //webBoot.Initialize(); - //webBoot.Startup(null); -> don't call startup, we don't want any other application event handlers to bind for this test. - //webBoot.Complete(null); - webBoot.CreateRoutes(); + + WebRuntimeComponent.CreateRoutes( + new SurfaceControllerTypeCollection(Enumerable.Empty()), + new UmbracoApiControllerTypeCollection(Enumerable.Empty())); } public class TestRuntime : WebRuntime { - public TestRuntime(UmbracoApplicationBase umbracoApplication) + public TestRuntime(UmbracoApplicationBase umbracoApplication) : base(umbracoApplication) { } @@ -61,10 +60,10 @@ namespace Umbraco.Tests.Routing // set the default RenderMvcController Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! - var surfaceControllerTypes = new SurfaceControllerTypeCollection(PluginManager.Current.ResolveSurfaceControllers()); + var surfaceControllerTypes = new SurfaceControllerTypeCollection(Current.PluginManager.ResolveSurfaceControllers()); Container.RegisterInstance(surfaceControllerTypes); - var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(PluginManager.Current.ResolveUmbracoApiControllers()); + var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(Current.PluginManager.ResolveUmbracoApiControllers()); Container.RegisterInstance(umbracoApiControllerTypes); Container.RegisterSingleton(_ => new DefaultShortStringHelper(SettingsForTests.GetDefault())); @@ -75,7 +74,7 @@ namespace Umbraco.Tests.Routing public override void TearDown() { base.TearDown(); - RouteTable.Routes.Clear(); + RouteTable.Routes.Clear(); } Template CreateTemplate(string alias) @@ -84,7 +83,7 @@ namespace Umbraco.Tests.Routing var name = "Template"; var template = new Template(name, alias); template.Content = ""; // else saving throws with a dirty internal error - ApplicationContext.Services.FileService.SaveTemplate(template); + Current.Services.FileService.SaveTemplate(template); return template; } @@ -106,7 +105,7 @@ namespace Umbraco.Tests.Routing }; var handler = new RenderRouteHandler( - new TestControllerFactory(routingContext.UmbracoContext, Mock.Of()), + new TestControllerFactory(routingContext.UmbracoContext, Mock.Of()), routingContext.UmbracoContext); handler.GetHandlerForRoute(routingContext.UmbracoContext.HttpContext.Request.RequestContext, docRequest); @@ -122,7 +121,7 @@ namespace Umbraco.Tests.Routing [TestCase("home-page")] [TestCase("home-page")] [TestCase("home-page")] - [TestCase("Home-Page")] + [TestCase("Home-Page")] [TestCase("HomePage")] [TestCase("homePage")] [TestCase("site1/template2")] @@ -139,12 +138,12 @@ namespace Umbraco.Tests.Routing var routingContext = GetRoutingContext("~/dummy-page", template.Id, routeData, true); var docRequest = new PublishedContentRequest(routingContext.UmbracoContext.CleanedUmbracoUrl, routingContext) { - PublishedContent = routingContext.UmbracoContext.ContentCache.GetById(1172), + PublishedContent = routingContext.UmbracoContext.ContentCache.GetById(1172), TemplateModel = template }; var handler = new RenderRouteHandler( - new TestControllerFactory(routingContext.UmbracoContext, Mock.Of()), + new TestControllerFactory(routingContext.UmbracoContext, Mock.Of()), routingContext.UmbracoContext); handler.GetHandlerForRoute(routingContext.UmbracoContext.HttpContext.Request.RequestContext, docRequest); @@ -181,11 +180,7 @@ namespace Umbraco.Tests.Routing /// public class CustomDocumentController : RenderMvcController { - public CustomDocumentController(UmbracoContext umbracoContext) : base(umbracoContext) - { - } - - public ActionResult HomePage(ContentModel model) + public ActionResult HomePage(ContentModel model) { return View(); } diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index 1bbf09f10d..946d524c69 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -21,7 +21,7 @@ namespace Umbraco.Tests.Routing //create the module _module = new UmbracoModule(); - SettingsForTests.ConfigurationStatus = UmbracoVersion.GetSemanticVersion().ToSemanticString(); + SettingsForTests.ConfigurationStatus = UmbracoVersion.SemanticVersion.ToSemanticString(); //SettingsForTests.ReservedPaths = "~/umbraco,~/install/"; //SettingsForTests.ReservedUrls = "~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd"; diff --git a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs index d9cfca4739..521a98238b 100644 --- a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs +++ b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs @@ -57,18 +57,18 @@ namespace Umbraco.Tests.Routing public const int LangNlId = 337; public const int LangDkId = 338; - protected override ApplicationContext CreateApplicationContext() - { - var settings = SettingsForTests.GetDefault(); - var databaseFactory = TestObjects.GetIDatabaseFactoryMock(); - return new ApplicationContext( - new DatabaseContext(databaseFactory, Logger), - GetServiceContext(settings, Logger), - CacheHelper, - ProfilingLogger) - { - IsReady = true - }; - } + //protected override ApplicationContext CreateApplicationContext() + //{ + // var settings = SettingsForTests.GetDefault(); + // var databaseFactory = TestObjects.GetIDatabaseFactoryMock(); + // return new ApplicationContext( + // new DatabaseContext(databaseFactory, Logger, Mock.Of(), Mock.Of()), + // GetServiceContext(settings, Logger), + // CacheHelper, + // ProfilingLogger) + // { + // //IsReady = true + // }; + //} } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 55cb5a330b..4128b4bd71 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using UmbracoExamine; @@ -92,7 +93,7 @@ namespace Umbraco.Tests.Runtimes container.Register(factory => SettingsForTests.GetDefault()); container.Register(factory => new DatabaseContext( factory.GetInstance(), - factory.GetInstance()), new PerContainerLifetime()); + factory.GetInstance(), Mock.Of(), Mock.Of()), new PerContainerLifetime()); container.RegisterSingleton(); Composed = true; @@ -132,17 +133,17 @@ namespace Umbraco.Tests.Runtimes public static bool Started; public static bool HasBeenDisposed; - public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication) { Initialized = true; } - public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication) { Starting = true; } - public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication) { Started = true; } diff --git a/src/Umbraco.Tests/Runtimes/WebRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/WebRuntimeTests.cs index 5bae96f92b..1472fd93a2 100644 --- a/src/Umbraco.Tests/Runtimes/WebRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/WebRuntimeTests.cs @@ -19,7 +19,7 @@ namespace Umbraco.Tests.Runtimes new PluginViewEngine() }; - WebRuntime.WrapViewEngines(engines); + WebRuntimeComponent.WrapViewEngines(engines); Assert.That(engines.Count, Is.EqualTo(2)); Assert.That(engines[0], Is.InstanceOf()); @@ -35,7 +35,7 @@ namespace Umbraco.Tests.Runtimes new PluginViewEngine() }; - WebRuntime.WrapViewEngines(engines); + WebRuntimeComponent.WrapViewEngines(engines); Assert.That(engines.Count, Is.EqualTo(2)); Assert.That(((ProfilingViewEngine)engines[0]).Inner, Is.InstanceOf()); @@ -52,7 +52,7 @@ namespace Umbraco.Tests.Runtimes profiledEngine }; - WebRuntime.WrapViewEngines(engines); + WebRuntimeComponent.WrapViewEngines(engines); Assert.That(engines[0], Is.SameAs(profiledEngine)); } @@ -61,7 +61,7 @@ namespace Umbraco.Tests.Runtimes public void WrapViewEngines_CollectionIsNull_DoesNotThrow() { IList engines = null; - Assert.DoesNotThrow(() => WebRuntime.WrapViewEngines(engines)); + Assert.DoesNotThrow(() => WebRuntimeComponent.WrapViewEngines(engines)); Assert.That(engines, Is.Null); } diff --git a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs index 5352002b73..75cb0a4576 100644 --- a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs +++ b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs @@ -31,21 +31,21 @@ namespace Umbraco.Tests.Security ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", ""); var databaseFactory = TestObjects.GetIDatabaseFactoryMock(false); - var dbCtx = new Mock(databaseFactory, Mock.Of()); + //var dbCtx = new Mock(databaseFactory, Mock.Of()); - var appCtx = new ApplicationContext( - dbCtx.Object, - TestObjects.GetServiceContextMock(), - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // dbCtx.Object, + // TestObjects.GetServiceContextMock(), + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.CreateContext( - Mock.Of(), appCtx, + Mock.Of(), Mock.Of(), - new WebSecurity(Mock.Of(), appCtx), + new WebSecurity(Mock.Of(), Current.Services.UserService), Mock.Of(), new List()); - var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.UmbracoContext == umbCtx)); + var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.UmbracoContext == umbCtx), Mock.Of()); var result = mgr.ShouldAuthenticateRequest(Mock.Of(), new Uri("http://localhost/umbraco")); @@ -58,19 +58,19 @@ namespace Umbraco.Tests.Security var databaseFactory = TestObjects.GetIDatabaseFactoryMock(); var dbCtx = new Mock(databaseFactory, Mock.Of()); - var appCtx = new ApplicationContext( - dbCtx.Object, - TestObjects.GetServiceContextMock(), - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // dbCtx.Object, + // TestObjects.GetServiceContextMock(), + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.CreateContext( - Mock.Of(), appCtx, + Mock.Of(), Mock.Of(), - new WebSecurity(Mock.Of(), appCtx), + new WebSecurity(Mock.Of(), Current.Services.UserService), Mock.Of(), new List()); - var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.UmbracoContext == umbCtx)); + var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.UmbracoContext == umbCtx), Mock.Of()); var request = new Mock(); request.Setup(owinRequest => owinRequest.Uri).Returns(new Uri("http://localhost/umbraco")); diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index c69efed5d8..59000afe14 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Models; using Umbraco.Core; using Umbraco.Core.Models.Rdbms; using Umbraco.Tests.TestHelpers; +using Current = Umbraco.Web.Current; namespace Umbraco.Tests.Services.Importing { @@ -317,7 +318,7 @@ namespace Umbraco.Tests.Services.Importing where (string)doc.Attribute("isDoc") == "" select doc).Count(); - var database = ApplicationContext.DatabaseContext.Database; + var database = Current.DatabaseContext.Database; var dtos = database.Fetch("WHERE datatypeNodeId = @Id", new { dataTypeDefinitions.First().Id }); int preValueId; int.TryParse(contents.First().GetValue("testList"), out preValueId); diff --git a/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs b/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs index 31e40228ff..4c4442a9f8 100644 --- a/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs +++ b/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs @@ -23,6 +23,7 @@ using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Core.Events; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; +using Current = Umbraco.Core.DependencyInjection.Current; namespace Umbraco.Tests.Services { @@ -32,6 +33,8 @@ namespace Umbraco.Tests.Services { private IDatabaseUnitOfWorkProvider _uowProvider; private PerThreadSqlCeDatabaseFactory _dbFactory; + private DatabaseContext _dbContext; + private ServiceContext _services; [SetUp] public override void Initialize() @@ -47,7 +50,7 @@ namespace Umbraco.Tests.Services _uowProvider = new NPocoUnitOfWorkProvider(_dbFactory, repositoryFactory); // overwrite the local object - ApplicationContext.DatabaseContext = new DatabaseContext(_dbFactory, Logger); + _dbContext = new DatabaseContext(_dbFactory, Logger, Mock.Of(), Mock.Of()); //disable cache var cacheHelper = CacheHelper.CreateDisabledCacheHelper(); @@ -56,7 +59,7 @@ namespace Umbraco.Tests.Services //global Database object but this is NOT how it should work in the web world or in any multi threaded scenario. //we need a new Database object for each thread. var evtMsgs = new TransientEventMessagesFactory(); - ApplicationContext.Services = TestObjects.GetServiceContext( + _services = TestObjects.GetServiceContext( repositoryFactory, _uowProvider, new FileUnitOfWorkProvider(), @@ -74,6 +77,9 @@ namespace Umbraco.Tests.Services //replace some services Container.Register(factory => _dbFactory); + + Container.Register(factory => _dbContext); + Container.Register(factory => _services); } [TearDown] diff --git a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs index 98f49a8b8c..48b9b65a72 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs @@ -54,7 +54,7 @@ namespace Umbraco.Tests.TestHelpers //Used to flag if its the first test in the current fixture private bool _isFirstTestInFixture; - private ApplicationContext _appContext; + //private ApplicationContext _appContext; private IFacadeService _facadeService; private IDatabaseUnitOfWorkProvider _uowProvider; @@ -86,7 +86,7 @@ namespace Umbraco.Tests.TestHelpers Container.Register(_ => manifestBuilder); PropertyEditorCollectionBuilder.Register(Container) - .AddProducer(() => PluginManager.Current.ResolvePropertyEditors()); + .AddProducer(() => Current.PluginManager.ResolvePropertyEditors()); } private CacheHelper _disabledCacheHelper; @@ -94,75 +94,75 @@ namespace Umbraco.Tests.TestHelpers protected IDatabaseUnitOfWorkProvider UowProvider => _uowProvider; - protected override ApplicationContext CreateApplicationContext() - { - var sqlSyntaxProviders = new[] { new SqlCeSyntaxProvider() }; + //protected override ApplicationContext CreateApplicationContext() + //{ + // var sqlSyntaxProviders = new[] { new SqlCeSyntaxProvider() }; - // create the database if required - // note: must do before instanciating the database factory else it will - // not find the database and will remain un-configured. - using (ProfilingLogger.TraceDuration("Create database.")) - { - //TODO make it faster - CreateSqlCeDatabase(); - } + // // create the database if required + // // note: must do before instanciating the database factory else it will + // // not find the database and will remain un-configured. + // using (ProfilingLogger.TraceDuration("Create database.")) + // { + // //TODO make it faster + // CreateSqlCeDatabase(); + // } - // ensure the configuration matches the current version for tests - SettingsForTests.ConfigurationStatus = UmbracoVersion.Current.ToString(3); + // // ensure the configuration matches the current version for tests + // SettingsForTests.ConfigurationStatus = UmbracoVersion.Current.ToString(3); - // create the database factory - if the test does not require an actual database, - // use a mock factory; otherwise use a real factory. - IDatabaseFactory databaseFactory; - if (DatabaseTestBehavior == DatabaseBehavior.NoDatabasePerFixture) - { - databaseFactory = TestObjects.GetIDatabaseFactoryMock(); - } - else - { - var f = new DefaultDatabaseFactory(GetDbConnectionString(), GetDbProviderName(), sqlSyntaxProviders, Logger, new TestUmbracoDatabaseAccessor(), Mappers); - f.ResetForTests(); - databaseFactory = f; - } + // // create the database factory - if the test does not require an actual database, + // // use a mock factory; otherwise use a real factory. + // IDatabaseFactory databaseFactory; + // if (DatabaseTestBehavior == DatabaseBehavior.NoDatabasePerFixture) + // { + // databaseFactory = TestObjects.GetIDatabaseFactoryMock(); + // } + // else + // { + // var f = new DefaultDatabaseFactory(GetDbConnectionString(), GetDbProviderName(), sqlSyntaxProviders, Logger, new TestUmbracoDatabaseAccessor(), Mappers); + // f.ResetForTests(); + // databaseFactory = f; + // } - // so, using the above code to create a mock IDatabaseFactory if we don't have a real database - // but, that will NOT prevent _appContext from NOT being configured, because it cannot connect - // to the database to check the migrations ;-( + // // so, using the above code to create a mock IDatabaseFactory if we don't have a real database + // // but, that will NOT prevent _appContext from NOT being configured, because it cannot connect + // // to the database to check the migrations ;-( - var evtMsgs = new TransientEventMessagesFactory(); - var databaseContext = new DatabaseContext(databaseFactory, Logger); - var repositoryFactory = Container.GetInstance(); - var serviceContext = TestObjects.GetServiceContext( - repositoryFactory, - _uowProvider = new NPocoUnitOfWorkProvider(databaseFactory, repositoryFactory), - new FileUnitOfWorkProvider(), - CacheHelper, - Logger, - evtMsgs, - Enumerable.Empty()); + // var evtMsgs = new TransientEventMessagesFactory(); + // var databaseContext = new DatabaseContext(databaseFactory, Logger, Mock.Of(), Mock.Of()); + // var repositoryFactory = Container.GetInstance(); + // var serviceContext = TestObjects.GetServiceContext( + // repositoryFactory, + // _uowProvider = new NPocoUnitOfWorkProvider(databaseFactory, repositoryFactory), + // new FileUnitOfWorkProvider(), + // CacheHelper, + // Logger, + // evtMsgs, + // Enumerable.Empty()); - // if the test does not require an actual database, or runs with an empty database, the application - // context will not be able to check the migration status in the database, so we have to force it - // to think it is configured. - var appContextMock = new Mock(databaseContext, serviceContext, CacheHelper, ProfilingLogger); - if (DatabaseTestBehavior == DatabaseBehavior.NoDatabasePerFixture // no db at all - || DatabaseTestBehavior == DatabaseBehavior.EmptyDbFilePerTest) // empty db - appContextMock.Setup(x => x.IsConfigured).Returns(true); - _appContext = appContextMock.Object; + // // if the test does not require an actual database, or runs with an empty database, the application + // // context will not be able to check the migration status in the database, so we have to force it + // // to think it is configured. + // var appContextMock = new Mock(databaseContext, serviceContext, CacheHelper, ProfilingLogger); + // //if (DatabaseTestBehavior == DatabaseBehavior.NoDatabasePerFixture // no db at all + // // || DatabaseTestBehavior == DatabaseBehavior.EmptyDbFilePerTest) // empty db + // // appContextMock.Setup(x => x.IsConfigured).Returns(true); + // _appContext = appContextMock.Object; - // initialize the database if required - // note: must do after creating the application context as - // it is using it - using (ProfilingLogger.TraceDuration("Initialize database.")) - { - // TODO make it faster - InitializeDatabase(_appContext); - } + // // initialize the database if required + // // note: must do after creating the application context as + // // it is using it + // using (ProfilingLogger.TraceDuration("Initialize database.")) + // { + // // TODO make it faster + // InitializeDatabase(_appContext); + // } - // application is ready - _appContext.IsReady = true; + // // application is ready + // //_appContext.IsReady = true; - return _appContext; - } + // return _appContext; + //} /// /// The database behavior to use for the test/fixture @@ -274,19 +274,19 @@ namespace Umbraco.Tests.TestHelpers var enableRepositoryEvents = behavior != null && behavior.EnableRepositoryEvents; ContentTypesCache = new PublishedContentTypeCache( - ApplicationContext.Services.ContentTypeService, - ApplicationContext.Services.MediaTypeService, - ApplicationContext.Services.MemberTypeService); + Current.Services.ContentTypeService, + Current.Services.MediaTypeService, + Current.Services.MemberTypeService); // testing=true so XmlStore will not use the file nor the database var facadeAccessor = new TestFacadeAccessor(); var service = new FacadeService( - ApplicationContext.Services, - _uowProvider, - cache, facadeAccessor, ContentTypesCache, true, enableRepositoryEvents); + Current.Services, + _uowProvider, + cache, facadeAccessor, ContentTypesCache, null, true, enableRepositoryEvents); // initialize PublishedCacheService content with an Xml source - service.XmlStore.GetXmlDocument = () => + service.XmlStore.GetXmlDocument = () => { var doc = new XmlDocument(); doc.LoadXml(GetXmlContent(0)); @@ -302,7 +302,7 @@ namespace Umbraco.Tests.TestHelpers /// /// Creates the tables and data for the database /// - protected virtual void InitializeDatabase(ApplicationContext appContext) + protected virtual void InitializeDatabase() { if (DatabaseTestBehavior == DatabaseBehavior.NoDatabasePerFixture || DatabaseTestBehavior == DatabaseBehavior.EmptyDbFilePerTest) return; @@ -317,10 +317,10 @@ namespace Umbraco.Tests.TestHelpers || DatabaseTestBehavior == DatabaseBehavior.NewDbFileAndSchemaPerTest || (_isFirstTestInFixture && DatabaseTestBehavior == DatabaseBehavior.NewDbFileAndSchemaPerFixture))) { - var database = appContext.DatabaseContext.Database; + var database = Current.DatabaseContext.Database; var schemaHelper = new DatabaseSchemaHelper(database, Logger); //Create the umbraco database and its base data - schemaHelper.CreateDatabaseSchema(appContext); + schemaHelper.CreateDatabaseSchema(Mock.Of(), Mock.Of()); //close the connections, we're gonna read this baby in as a byte array so we don't have to re-initialize the // damn db for each test @@ -333,7 +333,7 @@ namespace Umbraco.Tests.TestHelpers [TestFixtureTearDown] public void FixtureTearDown() { - RemoveDatabaseFile(ApplicationContext.Current?.DatabaseContext.Database); + RemoveDatabaseFile(Current.DatabaseContext.Database); } [TearDown] @@ -345,7 +345,7 @@ namespace Umbraco.Tests.TestHelpers if (DatabaseTestBehavior == DatabaseBehavior.NewDbFileAndSchemaPerTest) { - RemoveDatabaseFile(ApplicationContext.Current?.DatabaseContext.Database); + RemoveDatabaseFile(Current.DatabaseContext.Database); } AppDomain.CurrentDomain.SetData("DataDirectory", null); @@ -413,9 +413,9 @@ namespace Umbraco.Tests.TestHelpers } } - protected ServiceContext ServiceContext => ApplicationContext.Services; + protected ServiceContext ServiceContext => Current.Services; - protected DatabaseContext DatabaseContext => ApplicationContext.DatabaseContext; + protected DatabaseContext DatabaseContext => Current.DatabaseContext; protected UmbracoContext GetUmbracoContext(string url, int templateId, RouteData routeData = null, bool setSingleton = false) { @@ -435,9 +435,8 @@ namespace Umbraco.Tests.TestHelpers var httpContext = GetHttpContextFactory(url, routeData).HttpContext; var ctx = UmbracoContext.CreateContext( httpContext, - ApplicationContext, service, - new WebSecurity(httpContext, ApplicationContext), + new WebSecurity(httpContext, Current.Services.UserService), Mock.Of(), Enumerable.Empty()); diff --git a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs index ec7c682d35..559521e0c1 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs @@ -24,8 +24,10 @@ using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Events; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Plugins; +using Umbraco.Core.Services; using Umbraco.Web.DependencyInjection; using UmbracoExamine; +using Current = Umbraco.Web.Current; namespace Umbraco.Tests.TestHelpers { @@ -100,7 +102,8 @@ namespace Umbraco.Tests.TestHelpers Container.RegisterFrom(); Container.Register(factory => Container); - Container.Register(factory => PluginManager.Current); + var pluginManager = new PluginManager(CacheHelper.RuntimeCache, ProfilingLogger); //? + Container.RegisterInstance(pluginManager); //Default Datalayer/Repositories/SQL/Database/etc... Container.RegisterFrom(); @@ -166,7 +169,7 @@ namespace Umbraco.Tests.TestHelpers var mappers = Container.GetAllInstances(); foreach (var mapper in mappers) { - mapper.ConfigureMappings(configuration, ApplicationContext); + mapper.ConfigureMappings(configuration); } }); } @@ -205,41 +208,41 @@ namespace Umbraco.Tests.TestHelpers private void SetupApplicationContext() { - var applicationContext = CreateApplicationContext(); - Container.Register(_ => applicationContext); + //var applicationContext = CreateApplicationContext(); + //Container.Register(_ => applicationContext); } /// /// Inheritors can override this if they wish to create a custom application context /// - protected virtual ApplicationContext CreateApplicationContext() - { - var evtMsgs = new TransientEventMessagesFactory(); - var dbFactory = new DefaultDatabaseFactory( - Core.Configuration.GlobalSettings.UmbracoConnectionName, - TestObjects.GetDefaultSqlSyntaxProviders(Logger), - Logger, new TestUmbracoDatabaseAccessor(), - Mock.Of()); - dbFactory.ResetForTests(); - var applicationContext = new ApplicationContext( - // assign the db context - new DatabaseContext(dbFactory, Logger), - // assign the service context - TestObjects.GetServiceContext( - Container.GetInstance(), - TestObjects.GetDatabaseUnitOfWorkProvider(Logger), - new FileUnitOfWorkProvider(), - CacheHelper, - Logger, - evtMsgs, - Enumerable.Empty()), - CacheHelper, - ProfilingLogger) - { - IsReady = true - }; - return applicationContext; - } + //protected virtual ApplicationContext CreateApplicationContext() + //{ + // var evtMsgs = new TransientEventMessagesFactory(); + // var dbFactory = new DefaultDatabaseFactory( + // Core.Configuration.GlobalSettings.UmbracoConnectionName, + // TestObjects.GetDefaultSqlSyntaxProviders(Logger), + // Logger, new TestUmbracoDatabaseAccessor(), + // Mock.Of()); + // dbFactory.ResetForTests(); + // var applicationContext = new ApplicationContext( + // // assign the db context + // new DatabaseContext(dbFactory, Logger, Mock.Of(), Mock.Of()), + // // assign the service context + // TestObjects.GetServiceContext( + // Container.GetInstance(), + // TestObjects.GetDatabaseUnitOfWorkProvider(Logger), + // new FileUnitOfWorkProvider(), + // CacheHelper, + // Logger, + // evtMsgs, + // Enumerable.Empty()), + // CacheHelper, + // ProfilingLogger) + // { + // //IsReady = true + // }; + // return applicationContext; + //} /// /// Inheritors can override this if they wish to setup the plugin manager differenty (i.e. specify certain assemblies to load) @@ -269,8 +272,6 @@ namespace Umbraco.Tests.TestHelpers protected virtual void FreezeResolution() { } - protected ApplicationContext ApplicationContext => ApplicationContext.Current; - protected ILogger Logger => ProfilingLogger.Logger; protected ProfilingLogger ProfilingLogger { get; private set; } diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 060427fb16..d0eb6e06d1 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -44,9 +44,9 @@ namespace Umbraco.Tests.TestHelpers container.RegisterInstance(pluginManager); MapperCollectionBuilder.Register(container) - .AddProducer(() => PluginManager.Current.ResolveAssignedMapperTypes()); + .AddProducer(() => Current.PluginManager.ResolveAssignedMapperTypes()); Mappers = container.GetInstance(); - + var mappers = new NPoco.MapperCollection { new PocoMapper() }; var pocoDataFactory = new FluentPocoDataFactory((type, iPocoDataFactory) => new PocoDataBuilder(type, mappers).Init()); SqlContext = new SqlContext(sqlSyntax, pocoDataFactory, DatabaseType.SQLCe); diff --git a/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs b/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs index f31cd1a7a1..c27d714f9a 100644 --- a/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs +++ b/src/Umbraco.Tests/TreesAndSections/ApplicationTreeTest.cs @@ -5,6 +5,7 @@ using Umbraco.Tests.TestHelpers; using System; using System.Linq; using Umbraco.Web.Services; +using Current = Umbraco.Web.Current; namespace Umbraco.Tests.TreesAndSections { @@ -60,22 +61,22 @@ namespace Umbraco.Tests.TreesAndSections //create new app var appName = Guid.NewGuid().ToString("N"); var treeName = Guid.NewGuid().ToString("N"); - ApplicationContext.Services.SectionService.MakeNew(appName, appName, "icon.jpg"); + Current.Services.SectionService.MakeNew(appName, appName, "icon.jpg"); //check if it exists - var app = ApplicationContext.Services.SectionService.GetByAlias(appName); + var app = Current.Services.SectionService.GetByAlias(appName); Assert.IsNotNull(app); //create the new app tree assigned to the new app - ApplicationContext.Services.ApplicationTreeService.MakeNew(false, 0, app.Alias, treeName, treeName, "icon.jpg", "icon.jpg", "Umbraco.Web.Trees.ContentTreeController, umbraco"); - var tree = ApplicationContext.Services.ApplicationTreeService.GetByAlias(treeName); + Current.Services.ApplicationTreeService.MakeNew(false, 0, app.Alias, treeName, treeName, "icon.jpg", "icon.jpg", "Umbraco.Web.Trees.ContentTreeController, umbraco"); + var tree = Current.Services.ApplicationTreeService.GetByAlias(treeName); Assert.IsNotNull(tree); //now delete the app - ApplicationContext.Services.SectionService.DeleteSection(app); + Current.Services.SectionService.DeleteSection(app); //check that the tree is gone - Assert.AreEqual(0, ApplicationContext.Services.ApplicationTreeService.GetApplicationTrees(treeName).Count()); + Assert.AreEqual(0, Current.Services.ApplicationTreeService.GetApplicationTrees(treeName).Count()); } diff --git a/src/Umbraco.Tests/Web/Controllers/PluginControllerAreaTests.cs b/src/Umbraco.Tests/Web/Controllers/PluginControllerAreaTests.cs index ce88f32131..5105301b0d 100644 --- a/src/Umbraco.Tests/Web/Controllers/PluginControllerAreaTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/PluginControllerAreaTests.cs @@ -50,34 +50,35 @@ namespace Umbraco.Tests.Web.Controllers [PluginController("Area1")] public class Plugin1Controller : PluginController { - public Plugin1Controller(UmbracoContext umbracoContext) : base(umbracoContext) + public Plugin1Controller(UmbracoContext umbracoContext) { - } - } + UmbracoContext = umbracoContext; + } + } [PluginController("Area1")] public class Plugin2Controller : PluginController { public Plugin2Controller(UmbracoContext umbracoContext) - : base(umbracoContext) { - } - } + UmbracoContext = umbracoContext; + } + } [PluginController("Area2")] public class Plugin3Controller : PluginController { public Plugin3Controller(UmbracoContext umbracoContext) - : base(umbracoContext) { - } - } + UmbracoContext = umbracoContext; + } + } public class Plugin4Controller : PluginController { public Plugin4Controller(UmbracoContext umbracoContext) - : base(umbracoContext) { + UmbracoContext = umbracoContext; } } diff --git a/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs b/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs index 3c90bccb67..b4f4d41fb3 100644 --- a/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/RenderIndexActionSelectorAttributeTests.cs @@ -12,6 +12,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Profiling; +using Umbraco.Core.Services; using Umbraco.Web; using Umbraco.Web.Models; using Umbraco.Web.Mvc; @@ -54,17 +55,17 @@ namespace Umbraco.Tests.Web.Mvc { var attr = new RenderIndexActionSelectorAttribute(); var req = new RequestContext(); - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.EnsureContext( - Mock.Of(), appCtx, + Mock.Of(), Mock.Of(), new Mock(null, null).Object, Mock.Of(), Enumerable.Empty(), true); - var ctrl = new MatchesDefaultIndexController(umbCtx); + var ctrl = new MatchesDefaultIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); var result = attr.IsValidForRequest(controllerCtx, GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType())); @@ -77,17 +78,17 @@ namespace Umbraco.Tests.Web.Mvc { var attr = new RenderIndexActionSelectorAttribute(); var req = new RequestContext(); - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.EnsureContext( - Mock.Of(),appCtx, + Mock.Of(), Mock.Of(), new Mock(null, null).Object, Mock.Of(), Enumerable.Empty(), true); - var ctrl = new MatchesOverriddenIndexController(umbCtx); + var ctrl = new MatchesOverriddenIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); var result = attr.IsValidForRequest(controllerCtx, GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType())); @@ -100,17 +101,17 @@ namespace Umbraco.Tests.Web.Mvc { var attr = new RenderIndexActionSelectorAttribute(); var req = new RequestContext(); - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.EnsureContext( - Mock.Of(),appCtx, + Mock.Of(), Mock.Of(), new Mock(null, null).Object, Mock.Of(), Enumerable.Empty(), true); - var ctrl = new MatchesCustomIndexController(umbCtx); + var ctrl = new MatchesCustomIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); var result = attr.IsValidForRequest(controllerCtx, GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType())); @@ -123,17 +124,17 @@ namespace Umbraco.Tests.Web.Mvc { var attr = new RenderIndexActionSelectorAttribute(); var req = new RequestContext(); - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.EnsureContext( - Mock.Of(),appCtx, + Mock.Of(), Mock.Of(), new Mock(null, null).Object, Mock.Of(), Enumerable.Empty(), true); - var ctrl = new MatchesAsyncIndexController(umbCtx); + var ctrl = new MatchesAsyncIndexController { UmbracoContext = umbCtx }; var controllerCtx = new ControllerContext(req, ctrl); var result = attr.IsValidForRequest(controllerCtx, GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType())); @@ -142,18 +143,10 @@ namespace Umbraco.Tests.Web.Mvc } public class MatchesDefaultIndexController : RenderMvcController - { - public MatchesDefaultIndexController(UmbracoContext umbracoContext) : base(umbracoContext) - { - } - } + { } public class MatchesOverriddenIndexController : RenderMvcController { - public MatchesOverriddenIndexController(UmbracoContext umbracoContext) : base(umbracoContext) - { - } - public override ActionResult Index(ContentModel model) { return base.Index(model); @@ -162,10 +155,6 @@ namespace Umbraco.Tests.Web.Mvc public class MatchesCustomIndexController : RenderMvcController { - public MatchesCustomIndexController(UmbracoContext umbracoContext) : base(umbracoContext) - { - } - public ActionResult Index(ContentModel model, int page) { return base.Index(model); @@ -174,10 +163,6 @@ namespace Umbraco.Tests.Web.Mvc public class MatchesAsyncIndexController : RenderMvcController { - public MatchesAsyncIndexController(UmbracoContext umbracoContext) : base(umbracoContext) - { - } - public new async Task Index(ContentModel model) { return await Task.FromResult(base.Index(model)); diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index 6bf5747ad7..62404f3c39 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -45,19 +45,19 @@ namespace Umbraco.Tests.Web.Mvc [Test] public void Can_Construct_And_Get_Result() { - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.EnsureContext( - new Mock().Object, appCtx, + new Mock().Object, Mock.Of(), new Mock(null, null).Object, Mock.Of(), Enumerable.Empty(), true); - var ctrl = new TestSurfaceController(umbCtx); + var ctrl = new TestSurfaceController { UmbracoContext = umbCtx }; var result = ctrl.Index(); @@ -67,21 +67,21 @@ namespace Umbraco.Tests.Web.Mvc [Test] public void Umbraco_Context_Not_Null() { - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); - Current.ApplicationContext = appCtx; // FIXME horrible + //Current.ApplicationContext = appCtx; // FIXME horrible var umbCtx = UmbracoContext.EnsureContext( - new Mock().Object, appCtx, + new Mock().Object, Mock.Of(), new Mock(null, null).Object, Mock.Of(), Enumerable.Empty(), true); - var ctrl = new TestSurfaceController(umbCtx); + var ctrl = new TestSurfaceController { UmbracoContext = umbCtx }; Assert.IsNotNull(ctrl.UmbracoContext); } @@ -91,21 +91,21 @@ namespace Umbraco.Tests.Web.Mvc { var databaseFactory = TestObjects.GetIDatabaseFactoryMock(); - var appCtx = new ApplicationContext( - new DatabaseContext(databaseFactory, Mock.Of()), - TestObjects.GetServiceContextMock(), - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // new DatabaseContext(databaseFactory, Mock.Of(), Mock.Of(), Mock.Of()), + // TestObjects.GetServiceContextMock(), + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.EnsureContext( - new Mock().Object, appCtx, + new Mock().Object, Mock.Of(), new Mock(null, null).Object, Mock.Of(), Enumerable.Empty(), true); - var ctrl = new TestSurfaceController(umbCtx); + var ctrl = new TestSurfaceController { UmbracoContext = umbCtx }; Assert.IsNotNull(ctrl.Umbraco); } @@ -113,9 +113,9 @@ namespace Umbraco.Tests.Web.Mvc [Test] public void Can_Lookup_Content() { - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var facade = new Mock(); facade.Setup(x => x.MemberCache).Returns(Mock.Of()); @@ -123,7 +123,7 @@ namespace Umbraco.Tests.Web.Mvc facadeService.Setup(x => x.CreateFacade(It.IsAny())).Returns(facade.Object); var umbCtx = UmbracoContext.EnsureContext( - new Mock().Object, appCtx, + new Mock().Object, facadeService.Object, new Mock(null, null).Object, Mock.Of(section => section.WebRouting == Mock.Of(routingSection => routingSection.UrlProviderMode == "AutoLegacy")), @@ -134,16 +134,18 @@ namespace Umbraco.Tests.Web.Mvc umbCtx, Mock.Of(), Mock.Of(query => query.Content(It.IsAny()) == - //return mock of IPublishedContent for any call to GetById - Mock.Of(content => content.Id == 2)), + //return mock of IPublishedContent for any call to GetById + Mock.Of(content => content.Id == 2)), Mock.Of(), Mock.Of(), new UrlProvider(umbCtx, Enumerable.Empty()), Mock.Of(), Mock.Of(), - new MembershipHelper(umbCtx, Mock.Of(), Mock.Of())); + new MembershipHelper(umbCtx, Mock.Of(), Mock.Of()), + new ServiceContext(), + CacheHelper.CreateDisabledCacheHelper()); - var ctrl = new TestSurfaceController(umbCtx, helper); + var ctrl = new TestSurfaceController { UmbracoContext = umbCtx, Umbraco = helper }; var result = ctrl.GetContent(2) as PublishedContentResult; Assert.IsNotNull(result); @@ -153,14 +155,14 @@ namespace Umbraco.Tests.Web.Mvc [Test] public void Mock_Current_Page() { - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var webRoutingSettings = Mock.Of(section => section.UrlProviderMode == "AutoLegacy"); var umbCtx = UmbracoContext.EnsureContext( - new Mock().Object, appCtx, + new Mock().Object, Mock.Of(), new Mock(null, null).Object, Mock.Of(section => section.WebRouting == webRoutingSettings), @@ -184,9 +186,9 @@ namespace Umbraco.Tests.Web.Mvc }; var routeData = new RouteData(); - routeData.DataTokens.Add(Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken, routeDefinition); + routeData.DataTokens.Add(Core.Constants.Web.UmbracoRouteDefinitionDataToken, routeDefinition); - var ctrl = new TestSurfaceController(umbCtx, new UmbracoHelper()); + var ctrl = new TestSurfaceController { UmbracoContext = umbCtx, Umbraco = new UmbracoHelper() }; ctrl.ControllerContext = new ControllerContext(contextBase, routeData, ctrl); var result = ctrl.GetContentFromCurrentPage() as PublishedContentResult; @@ -196,27 +198,6 @@ namespace Umbraco.Tests.Web.Mvc public class TestSurfaceController : SurfaceController { - private readonly UmbracoHelper _umbracoHelper; - - public TestSurfaceController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - - public TestSurfaceController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) - : base(umbracoContext) - { - _umbracoHelper = umbracoHelper; - } - - /// - /// Returns an UmbracoHelper object - /// - public override UmbracoHelper Umbraco - { - get { return _umbracoHelper ?? base.Umbraco; } - } - public ActionResult Index() { return View(); diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index ecd88f2e87..d60f3f77a9 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -430,22 +430,22 @@ namespace Umbraco.Tests.Web.Mvc var databaseFactory = TestObjects.GetIDatabaseFactoryMock(); - var appCtx = new ApplicationContext( - new DatabaseContext(databaseFactory, logger), - svcCtx, - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(logger, Mock.Of())) { IsReady = true }; + //var appCtx = new ApplicationContext( + // new DatabaseContext(databaseFactory, logger, Mock.Of(), Mock.Of()), + // svcCtx, + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(logger, Mock.Of())) { /*IsReady = true*/ }; var cache = new NullCacheProvider(); var provider = new NPocoUnitOfWorkProvider(databaseFactory, new RepositoryFactory(Mock.Of())); - _service = new FacadeService(svcCtx, provider, cache, Enumerable.Empty(), null, true, false); // no events + _service = new FacadeService(svcCtx, provider, cache, Enumerable.Empty(), null, null, true, false); // no events var http = GetHttpContextFactory(url, routeData).HttpContext; var ctx = UmbracoContext.CreateContext( - GetHttpContextFactory(url, routeData).HttpContext, appCtx, + GetHttpContextFactory(url, routeData).HttpContext, _service, - new WebSecurity(http, appCtx), + new WebSecurity(http, Current.Services.UserService), Mock.Of(), Enumerable.Empty()); diff --git a/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs b/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs index 448742d3df..decf3fb5b7 100644 --- a/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs +++ b/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs @@ -35,13 +35,13 @@ namespace Umbraco.Tests.Web [Test] public void RouteDataExtensions_GetUmbracoContext() { - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.CreateContext( - Mock.Of(), appCtx, + Mock.Of(), Mock.Of(), - new WebSecurity(Mock.Of(), appCtx), + new WebSecurity(Mock.Of(), Current.Services.UserService), Mock.Of(), new List()); var r1 = new RouteData(); @@ -54,13 +54,13 @@ namespace Umbraco.Tests.Web [Test] public void ControllerContextExtensions_GetUmbracoContext_From_RouteValues() { - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.CreateContext( - Mock.Of(), appCtx, + Mock.Of(), Mock.Of(), - new WebSecurity(Mock.Of(), appCtx), + new WebSecurity(Mock.Of(), Current.Services.UserService), Mock.Of(), new List()); @@ -83,13 +83,13 @@ namespace Umbraco.Tests.Web [Test] public void ControllerContextExtensions_GetUmbracoContext_From_Current() { - var appCtx = new ApplicationContext( - CacheHelper.CreateDisabledCacheHelper(), - new ProfilingLogger(Mock.Of(), Mock.Of())); + //var appCtx = new ApplicationContext( + // CacheHelper.CreateDisabledCacheHelper(), + // new ProfilingLogger(Mock.Of(), Mock.Of())); var umbCtx = UmbracoContext.CreateContext( - Mock.Of(), appCtx, + Mock.Of(), Mock.Of(), - new WebSecurity(Mock.Of(), appCtx), + new WebSecurity(Mock.Of(), Current.Services.UserService), Mock.Of(), new List()); diff --git a/src/Umbraco.Web.UI/umbraco/create/PartialViewMacro.ascx.cs b/src/Umbraco.Web.UI/umbraco/create/PartialViewMacro.ascx.cs index 7e5418ba03..558aa91a9a 100644 --- a/src/Umbraco.Web.UI/umbraco/create/PartialViewMacro.ascx.cs +++ b/src/Umbraco.Web.UI/umbraco/create/PartialViewMacro.ascx.cs @@ -64,10 +64,10 @@ namespace Umbraco.Web.UI.Umbraco.Create var name = fileName.Contains(".") ? fileName.Substring(0, (fileName.LastIndexOf('.') + 1)).Trim('.') : fileName; - + name = name.SplitPascalCasing().ToFirstUpperInvariant(); - var macro = ApplicationContext.Current.Services.MacroService.GetByAlias(name); + var macro = Current.Services.MacroService.GetByAlias(name); if (macro != null) { args.IsValid = false; diff --git a/src/Umbraco.Web.UI/umbraco/settings/views/EditView.aspx.cs b/src/Umbraco.Web.UI/umbraco/settings/views/EditView.aspx.cs index a91414fd02..1c22a125c7 100644 --- a/src/Umbraco.Web.UI/umbraco/settings/views/EditView.aspx.cs +++ b/src/Umbraco.Web.UI/umbraco/settings/views/EditView.aspx.cs @@ -55,7 +55,7 @@ namespace Umbraco.Web.UI.Umbraco.Settings.Views } protected string TemplateTreeSyncPath { get; private set; } - + /// /// This view is shared between different trees so we'll look for the query string /// @@ -122,7 +122,7 @@ namespace Umbraco.Web.UI.Umbraco.Settings.Views //configure editor for editing a file.... NameTxt.Text = OriginalFileName; - var svce = ApplicationContext.Current.Services.FileService; + var svce = Current.Services.FileService; var file = EditorType == ViewEditorType.PartialView ? svce.GetPartialView(OriginalFileName) : svce.GetPartialViewMacro(OriginalFileName); @@ -132,9 +132,9 @@ namespace Umbraco.Web.UI.Umbraco.Settings.Views PathPrefix.Text = string.Format(prefixFormat, EditorType == ViewEditorType.PartialView ? "Partials/" : "MacroPartials/"); - } + } } - + ClientTools .SetActiveTreeType(CurrentTreeType) .SyncTree(TemplateTreeSyncPath, false); @@ -164,7 +164,7 @@ namespace Umbraco.Web.UI.Umbraco.Settings.Views { throw new InvalidOperationException("Cannot render the editor without a supplied templateId or a file"); } - + Panel1.hasMenu = true; var editor = Panel1.NewTabPage(Services.TextService.Localize("template")); editor.Controls.Add(Pane8); @@ -222,9 +222,9 @@ namespace Umbraco.Web.UI.Umbraco.Settings.Views } else { - InitializeEditorForTemplate(); + InitializeEditorForTemplate(); } - + } protected override void OnPreRender(EventArgs e) @@ -233,7 +233,7 @@ namespace Umbraco.Web.UI.Umbraco.Settings.Views ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/codeEditorSave.asmx")); ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/legacyAjaxCalls.asmx")); } - + /// /// Configure the editor for partial view editing /// diff --git a/src/Umbraco.Web/ApplicationContextExtensions.cs b/src/Umbraco.Web/ApplicationContextExtensions.cs deleted file mode 100644 index b91e73df0d..0000000000 --- a/src/Umbraco.Web/ApplicationContextExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading; -using System.Web; -using Umbraco.Core; - -namespace Umbraco.Web -{ - public static class ApplicationContextExtensions - { - /// - /// Restarts the application pool by unloading the application domain. - /// - /// - /// - public static void RestartApplicationPool(this ApplicationContext appContext, HttpContextBase http) - { - // we're going to put an application wide flag to show that the application is about to restart. - // we're doing this because if there is a script checking if the app pool is fully restarted, then - // it can check if this flag exists... if it does it means the app pool isn't restarted yet. - http.Application.Add("AppPoolRestarting", true); - - // unload app domain - we must null out all identities otherwise we get serialization errors - // http://www.zpqrtbnk.net/posts/custom-iidentity-serialization-issue - http.User = null; - if (HttpContext.Current != null) - HttpContext.Current.User = null; - Thread.CurrentPrincipal = null; - HttpRuntime.UnloadAppDomain(); - } - } -} diff --git a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs index 49635b7f52..2de10c1062 100644 --- a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs @@ -20,8 +20,10 @@ namespace Umbraco.Web /// public class BatchedDatabaseServerMessenger : DatabaseServerMessenger { - public BatchedDatabaseServerMessenger(ApplicationContext appContext, bool enableDistCalls, DatabaseServerMessengerOptions options) - : base(appContext, enableDistCalls, options) + public BatchedDatabaseServerMessenger( + IRuntimeState runtime, DatabaseContext dbContext, ILogger logger, ProfilingLogger proflog, + bool enableDistCalls, DatabaseServerMessengerOptions options) + : base(runtime, dbContext, logger, proflog, enableDistCalls, options) { } // invoked by BatchedDatabaseServerMessengerStartup which is an ApplicationEventHandler @@ -32,9 +34,9 @@ namespace Umbraco.Web UmbracoModule.EndRequest += UmbracoModule_EndRequest; UmbracoModule.RouteAttempt += UmbracoModule_RouteAttempt; - if (ApplicationContext.DatabaseContext.CanConnect == false) + if (DatabaseContext.CanConnect == false) { - ApplicationContext.ProfilingLogger.Logger.Warn( + Logger.Warn( "Cannot connect to the database, distributed calls will not be enabled for this server."); } else @@ -68,11 +70,11 @@ namespace Umbraco.Web protected override void DeliverRemote(IEnumerable servers, ICacheRefresher refresher, MessageType messageType, IEnumerable ids = null, string json = null) { - var idsA = ids == null ? null : ids.ToArray(); + var idsA = ids?.ToArray(); Type arrayType; if (GetArrayType(idsA, out arrayType) == false) - throw new ArgumentException("All items must be of the same type, either int or Guid.", "ids"); + throw new ArgumentException("All items must be of the same type, either int or Guid.", nameof(ids)); BatchMessage(servers, refresher, messageType, idsA, arrayType, json); } @@ -97,7 +99,7 @@ namespace Umbraco.Web OriginIdentity = LocalIdentity }; - ApplicationContext.DatabaseContext.Database.Insert(dto); + Database.Insert(dto); } protected ICollection GetBatch(bool create) diff --git a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs index 43388b54f5..e2743a5233 100644 --- a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs +++ b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Cache /// public class CacheRefresherEventHandler : ApplicationEventHandler { - protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication) { LogHelper.Info("Initializing Umbraco internal event handlers for cache refreshing."); AddHandlers(); diff --git a/src/Umbraco.Web/Cache/ContentCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentCacheRefresher.cs index d2a6f97018..fb68f6f696 100644 --- a/src/Umbraco.Web/Cache/ContentCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/ContentCacheRefresher.cs @@ -36,7 +36,7 @@ namespace Umbraco.Web.Cache public override void Refresh(JsonPayload[] payloads) { - var runtimeCache = ApplicationContext.Current.ApplicationCache.RuntimeCache; + var runtimeCache = Current.ApplicationCache.RuntimeCache; runtimeCache.ClearCacheObjectTypes(); foreach (var payload in payloads) { @@ -61,12 +61,12 @@ namespace Umbraco.Web.Cache if (payloads.Any(x => x.ChangeTypes.HasType(TreeChangeTypes.RefreshAll)) || publishedChanged) { // when a public version changes - ApplicationContext.Current.ApplicationCache.ClearPartialViewCache(); + Current.ApplicationCache.ClearPartialViewCache(); MacroCacheRefresher.ClearMacroContentCache(CacheHelper); // just the content ClearXsltCache(); - ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey); - ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey); + Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey); + Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey); } base.Refresh(payloads); @@ -142,7 +142,7 @@ namespace Umbraco.Web.Cache { // todo: document where this is coming from if (UmbracoConfig.For.UmbracoSettings().Content.UmbracoLibraryCacheDuration <= 0) return; - ApplicationContext.Current.ApplicationCache.ClearCacheObjectTypes("MS.Internal.Xml.XPath.XPathSelectionIterator"); + Current.ApplicationCache.ClearCacheObjectTypes("MS.Internal.Xml.XPath.XPathSelectionIterator"); } #endregion diff --git a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs index 99b1f04f87..7253bf751a 100644 --- a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs @@ -44,9 +44,9 @@ namespace Umbraco.Web.Cache { var mediaCache = CacheHelper.IsolatedRuntimeCache.GetCache(); - ApplicationContext.Current.ApplicationCache.ClearPartialViewCache(); - ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey); - ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey); + Current.ApplicationCache.ClearPartialViewCache(); + Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey); + Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey); foreach (var payload in payloads) { @@ -60,13 +60,13 @@ namespace Umbraco.Web.Cache // // this clears the non-deep xml for the current media // - ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch( + Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch( $"{CacheKeys.MediaCacheKey}_{payload.Id}_False"); // and then, for the entire path, we have to clear whatever might contain the media // bearing in mind there are probably nasty race conditions here - this is all legacy var k = $"{CacheKeys.MediaCacheKey}_{payload.Id}_"; - var x = ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem(k) + var x = Current.ApplicationCache.RuntimeCache.GetCacheItem(k) as Tuple; if (x == null) continue; var path = x.Item2; @@ -74,7 +74,7 @@ namespace Umbraco.Web.Cache foreach (var pathId in path.Split(',').Skip(1).Select(int.Parse)) { // this clears the deep xml for the medias in the path (skipping -1) - ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch( + Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch( $"{CacheKeys.MediaCacheKey}_{pathId}_True"); } diff --git a/src/Umbraco.Web/CanvasDesignerUtility.cs b/src/Umbraco.Web/CanvasDesignerUtility.cs index d4ad46a4aa..1cf236be33 100644 --- a/src/Umbraco.Web/CanvasDesignerUtility.cs +++ b/src/Umbraco.Web/CanvasDesignerUtility.cs @@ -34,7 +34,7 @@ namespace Umbraco.Web internal static string frontBasePath = HttpContext.Current.Server.MapPath(@"\css\canvasdesigner\"); // get style box by tag - internal static String GetStyleBlock(string source, string name) + internal static String GetStyleBlock(string source, string name) { string startTag = string.Format("/***start-{0}***/", name); @@ -55,7 +55,7 @@ namespace Umbraco.Web { // Load current page - var contentService = ApplicationContext.Current.Services.ContentService; + var contentService = Current.Services.ContentService; IContent content = contentService.GetById(pageId); // Get less file path from the page Id @@ -79,7 +79,7 @@ namespace Umbraco.Web } // Get inherited pageId with canvasdesigner - internal static int GetParentOrSelfTunedPageId(string[] path, bool preview) + internal static int GetParentOrSelfTunedPageId(string[] path, bool preview) { string styleCanvasdesigner = preview ? @"{0}{1}.less" : "{0}{1}.css"; @@ -116,7 +116,7 @@ namespace Umbraco.Web { // Load current page - var contentService = ApplicationContext.Current.Services.ContentService; + var contentService = Current.Services.ContentService; IContent content = contentService.GetById(pageId); // Get less file path from the page Id @@ -191,11 +191,11 @@ namespace Umbraco.Web } // Save and publish less style - internal static void SaveAndPublishStyle(string parameters, int pageId, bool inherited) + internal static void SaveAndPublishStyle(string parameters, int pageId, bool inherited) { // Get inherited tuned pageId and path - var contentService = ApplicationContext.Current.Services.ContentService; + var contentService = Current.Services.ContentService; IContent content = contentService.GetById(pageId); int inheritedTunedPageId = CanvasDesignerUtility.GetParentOrSelfTunedPageId(content.Path.Split(','), true); @@ -208,7 +208,7 @@ namespace Umbraco.Web // Update pageId if parameters have changed if (inherited) pageId = inheritedTunedPageId; - + // Create front directory if necesary if (!Directory.Exists(frontBasePath)) Directory.CreateDirectory(frontBasePath); @@ -253,7 +253,7 @@ namespace Umbraco.Web { // Get inherited tuned pageId and path - var contentService = ApplicationContext.Current.Services.ContentService; + var contentService = Current.Services.ContentService; IContent content = contentService.GetById(pageId); int inheritedTunedPageId = CanvasDesignerUtility.GetParentOrSelfTunedPageId(content.Path.Split(','), true); diff --git a/src/Umbraco.Web/Controllers/UmbLoginController.cs b/src/Umbraco.Web/Controllers/UmbLoginController.cs index e86e48a18b..42866786cf 100644 --- a/src/Umbraco.Web/Controllers/UmbLoginController.cs +++ b/src/Umbraco.Web/Controllers/UmbLoginController.cs @@ -1,7 +1,4 @@ -using System.Linq; -using System.Web.Mvc; -using System.Web.Security; -using umbraco.cms.businesslogic.member; +using System.Web.Mvc; using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Core; diff --git a/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs b/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs index 9bb8ae7c9a..08cd87eb44 100644 --- a/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs +++ b/src/Umbraco.Web/Controllers/UmbLoginStatusController.cs @@ -1,7 +1,5 @@ -using System.Linq; -using System.Web.Mvc; +using System.Web.Mvc; using System.Web.Security; -using umbraco.cms.businesslogic.member; using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Core; diff --git a/src/Umbraco.Web/Controllers/UmbProfileController.cs b/src/Umbraco.Web/Controllers/UmbProfileController.cs index b45723ed30..7ed9220086 100644 --- a/src/Umbraco.Web/Controllers/UmbProfileController.cs +++ b/src/Umbraco.Web/Controllers/UmbProfileController.cs @@ -1,9 +1,5 @@ using System; -using System.Linq; using System.Web.Mvc; -using System.Web.Security; -using System.Xml; -using umbraco.cms.businesslogic.member; using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Core.Security; @@ -17,7 +13,7 @@ namespace Umbraco.Web.Controllers [HttpPost] public ActionResult HandleUpdateProfile([Bind(Prefix = "profileModel")] ProfileModel model) { - var provider = global::Umbraco.Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); + var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); if (provider.IsUmbracoMembershipProvider() == false) { throw new NotSupportedException("Profile editing with the " + typeof(UmbProfileController) + " is not supported when not using the default Umbraco membership provider"); diff --git a/src/Umbraco.Web/Controllers/UmbRegisterController.cs b/src/Umbraco.Web/Controllers/UmbRegisterController.cs index f9665f713e..df50febbde 100644 --- a/src/Umbraco.Web/Controllers/UmbRegisterController.cs +++ b/src/Umbraco.Web/Controllers/UmbRegisterController.cs @@ -1,11 +1,7 @@ using System; -using System.Linq; using System.Web.Mvc; using System.Web.Security; -using umbraco.BusinessLogic; -using umbraco.cms.businesslogic.member; using Umbraco.Core; -using Umbraco.Core.Security; using Umbraco.Web.Models; using Umbraco.Web.Mvc; diff --git a/src/Umbraco.Web/Current.cs b/src/Umbraco.Web/Current.cs index c73b886c3b..1bba684c2f 100644 --- a/src/Umbraco.Web/Current.cs +++ b/src/Umbraco.Web/Current.cs @@ -1,4 +1,6 @@ using System; +using System.Threading; +using System.Web; using LightInject; using Umbraco.Core; using Umbraco.Core.Cache; @@ -10,6 +12,7 @@ using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Migrations; using Umbraco.Core.Plugins; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Sync; using Umbraco.Core._Legacy.PackageActions; @@ -195,11 +198,32 @@ namespace Umbraco.Web #endregion + #region Web Actions + + public static void RestartAppPool(HttpContextBase httpContext) + { + // we're going to put an application wide flag to show that the application is about to restart. + // we're doing this because if there is a script checking if the app pool is fully restarted, then + // it can check if this flag exists... if it does it means the app pool isn't restarted yet. + httpContext.Application.Add("AppPoolRestarting", true); + + // unload app domain - we must null out all identities otherwise we get serialization errors + // http://www.zpqrtbnk.net/posts/custom-iidentity-serialization-issue + httpContext.User = null; + if (HttpContext.Current != null) + HttpContext.Current.User = null; + Thread.CurrentPrincipal = null; + + HttpRuntime.UnloadAppDomain(); + } + + #endregion + #region Core Getters // proxy Core for convenience - public static ApplicationContext ApplicationContext => CoreCurrent.ApplicationContext; + public static IRuntimeState RuntimeState => CoreCurrent.RuntimeState; public static PluginManager PluginManager => CoreCurrent.PluginManager; @@ -233,6 +257,12 @@ namespace Umbraco.Web public static ProfilingLogger ProfilingLogger => CoreCurrent.ProfilingLogger; + public static CacheHelper ApplicationCache => CoreCurrent.ApplicationCache; + + public static ServiceContext Services => CoreCurrent.Services; + + public static DatabaseContext DatabaseContext => CoreCurrent.DatabaseContext; + #endregion } } diff --git a/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs b/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs index fdb4145160..90b93d4eff 100644 --- a/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs +++ b/src/Umbraco.Web/Dictionary/UmbracoCultureDictionary.cs @@ -30,7 +30,7 @@ namespace Umbraco.Web.Dictionary private readonly CultureInfo _specificCulture = null; public DefaultCultureDictionary() - : this(ApplicationContext.Current.Services.LocalizationService, ApplicationContext.Current.ApplicationCache.RequestCache) + : this(Current.Services.LocalizationService, Current.ApplicationCache.RequestCache) { } @@ -44,7 +44,7 @@ namespace Umbraco.Web.Dictionary } public DefaultCultureDictionary(CultureInfo specificCulture) - : this(ApplicationContext.Current.Services.LocalizationService, ApplicationContext.Current.ApplicationCache.RequestCache) + : this(Current.Services.LocalizationService, Current.ApplicationCache.RequestCache) { if (specificCulture == null) throw new ArgumentNullException("specificCulture"); _specificCulture = specificCulture; diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index 0b9b555287..7b66d900e0 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -36,7 +36,6 @@ namespace Umbraco.Web.Editors [IsBackOffice] public class AuthenticationController : UmbracoApiController { - private BackOfficeUserManager _userManager; private BackOfficeSignInManager _signInManager; @@ -74,7 +73,6 @@ namespace Umbraco.Web.Editors } } - [WebApi.UmbracoAuthorize] [ValidateAngularAntiForgeryToken] public async Task PostUnLinkLogin(UnLinkLoginModel unlinkLoginModel) @@ -107,11 +105,10 @@ namespace Umbraco.Web.Editors if (attempt == ValidateRequestAttempt.Success) { return true; - } + } return false; } - /// /// Returns the currently logged in Umbraco user /// @@ -166,7 +163,7 @@ namespace Umbraco.Web.Editors var userDetail = Mapper.Map(user); //update the userDetail and set their remaining seconds userDetail.SecondsUntilTimeout = TimeSpan.FromMinutes(GlobalSettings.TimeOutInMinutes).TotalSeconds; - + //create a response with the userDetail object var response = Request.CreateResponse(HttpStatusCode.OK, userDetail); @@ -182,7 +179,7 @@ namespace Umbraco.Web.Editors { throw new HttpResponseException( Request.CreateErrorResponse( - HttpStatusCode.BadRequest, + HttpStatusCode.BadRequest, "UserManager does not implement " + typeof(IUmbracoBackOfficeTwoFactorOptions))); } @@ -210,10 +207,10 @@ namespace Umbraco.Web.Editors case SignInStatus.LockedOut: case SignInStatus.Failure: default: - //return BadRequest (400), we don't want to return a 401 because that get's intercepted + //return BadRequest (400), we don't want to return a 401 because that get's intercepted // by our angular helper because it thinks that we need to re-perform the request once we are - // authorized and we don't want to return a 403 because angular will show a warning msg indicating - // that the user doesn't have access to perform this function, we just want to return a normal invalid msg. + // authorized and we don't want to return a 403 because angular will show a warning msg indicating + // that the user doesn't have access to perform this function, we just want to return a normal invalid msg. throw new HttpResponseException(HttpStatusCode.BadRequest); } } @@ -263,7 +260,7 @@ namespace Umbraco.Web.Editors var http = EnsureHttpContext(); var urlHelper = new UrlHelper(http.Request.RequestContext); - var action = urlHelper.Action("ValidatePasswordResetCode", "BackOffice", + var action = urlHelper.Action("ValidatePasswordResetCode", "BackOffice", new { area = GlobalSettings.UmbracoMvcArea, @@ -277,8 +274,8 @@ namespace Umbraco.Web.Editors http.Request.Url.Scheme, http.Request.Url.Host + (http.Request.Url.Port == 80 ? string.Empty : ":" + http.Request.Url.Port), action); - } - + } + /// /// Processes a set password request. Validates the request and sets a new password. /// diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index aaf6d0e1a4..c7c5d94495 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -4,8 +4,6 @@ using System.Configuration; using System.Globalization; using System.IO; using System.Linq; -using System.Net; -using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -25,9 +23,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Manifest; -using Umbraco.Core.Models; using Umbraco.Core.Models.Identity; -using Umbraco.Core.Plugins; using Umbraco.Core.Security; using Umbraco.Web.HealthCheck; using Umbraco.Web.Models; @@ -37,7 +33,6 @@ using Umbraco.Web.PropertyEditors; using Umbraco.Web.Security.Identity; using Umbraco.Web.Trees; using Umbraco.Web.UI.JavaScript; -using Umbraco.Web.WebApi.Filters; using Umbraco.Web.WebServices; using Umbraco.Core.Services; using Action = Umbraco.Web._Legacy.Actions.Action; @@ -51,12 +46,13 @@ namespace Umbraco.Web.Editors } /// - /// A controller to render out the default back office view and JS results + /// Represents a controller user to render out the default back office view and JS results. /// [UmbracoRequireHttps] [DisableClientCache] public class BackOfficeController : UmbracoController { + private readonly IRuntimeState _runtime; private BackOfficeUserManager _userManager; private BackOfficeSignInManager _signInManager; @@ -64,20 +60,16 @@ namespace Umbraco.Web.Editors private const string TokenPasswordResetCode = "PasswordResetCode"; private static readonly string[] TempDataTokenNames = { TokenExternalSignInError, TokenPasswordResetCode }; - protected BackOfficeSignInManager SignInManager + public BackOfficeController(IRuntimeState runtime) { - get { return _signInManager ?? (_signInManager = OwinContext.Get()); } + _runtime = runtime; } - protected BackOfficeUserManager UserManager - { - get { return _userManager ?? (_userManager = OwinContext.GetUserManager()); } - } + protected BackOfficeSignInManager SignInManager => _signInManager ?? (_signInManager = OwinContext.Get()); - protected IAuthenticationManager AuthenticationManager - { - get { return OwinContext.Authentication; } - } + protected BackOfficeUserManager UserManager => _userManager ?? (_userManager = OwinContext.GetUserManager()); + + protected IAuthenticationManager AuthenticationManager => OwinContext.Authentication; /// /// Render the default view @@ -91,10 +83,10 @@ namespace Umbraco.Web.Editors } /// - /// This Action is used by the installer when an upgrade is detected but the admin user is not logged in. We need to + /// This Action is used by the installer when an upgrade is detected but the admin user is not logged in. We need to /// ensure the user is authenticated before the install takes place so we redirect here to show the standard login screen. /// - /// + /// [HttpGet] public async Task AuthorizeUpgrade() { @@ -172,7 +164,7 @@ namespace Umbraco.Web.Editors //cache the result if debugging is disabled var result = HttpContext.IsDebuggingEnabled ? getResult() - : ApplicationContext.ApplicationCache.RuntimeCache.GetCacheItem( + : ApplicationCache.RuntimeCache.GetCacheItem( typeof(BackOfficeController) + "GetManifestAssetList", () => getResult(), new TimeSpan(0, 10, 0)); @@ -186,7 +178,7 @@ namespace Umbraco.Web.Editors { var gridConfig = UmbracoConfig.For.GridConfig( Logger, - ApplicationContext.ApplicationCache.RuntimeCache, + ApplicationCache.RuntimeCache, new DirectoryInfo(Server.MapPath(SystemDirectories.AppPlugins)), new DirectoryInfo(Server.MapPath(SystemDirectories.Config)), HttpContext.IsDebuggingEnabled); @@ -434,14 +426,14 @@ namespace Umbraco.Web.Editors //cache the result if debugging is disabled var result = HttpContext.IsDebuggingEnabled ? getResult() - : ApplicationContext.ApplicationCache.RuntimeCache.GetCacheItem( + : ApplicationCache.RuntimeCache.GetCacheItem( typeof(BackOfficeController) + "ServerVariables", () => getResult(), new TimeSpan(0, 10, 0)); return JavaScript(result); } - + [HttpPost] public ActionResult ExternalLogin(string provider, string redirectUrl = null) { @@ -512,17 +504,17 @@ namespace Umbraco.Web.Editors private ManifestParser GetManifestParser() { var plugins = new DirectoryInfo(Server.MapPath("~/App_Plugins")); - var parser = new ManifestParser(Logger, plugins, ApplicationContext.ApplicationCache.RuntimeCache); + var parser = new ManifestParser(Logger, plugins, ApplicationCache.RuntimeCache); return parser; } /// - /// Used by Default and AuthorizeUpgrade to render as per normal if there's no external login info, + /// Used by Default and AuthorizeUpgrade to render as per normal if there's no external login info, /// otherwise process the external login info. /// - /// + /// private async Task RenderDefaultOrProcessExternalLoginAsync( - Func defaultResponse, + Func defaultResponse, Func externalSignInResponse) { if (defaultResponse == null) throw new ArgumentNullException("defaultResponse"); @@ -532,7 +524,7 @@ namespace Umbraco.Web.Editors //check if there is the TempData with the any token name specified, if so, assign to view bag and render the view foreach (var tempDataTokenName in TempDataTokenNames) - { + { if (TempData[tempDataTokenName] != null) { ViewData[tempDataTokenName] = TempData[tempDataTokenName]; @@ -562,10 +554,10 @@ namespace Umbraco.Web.Editors var user = await UserManager.FindAsync(loginInfo.Login); if (user != null) { - //TODO: It might be worth keeping some of the claims associated with the ExternalLoginInfo, in which case we - // wouldn't necessarily sign the user in here with the standard login, instead we'd update the + //TODO: It might be worth keeping some of the claims associated with the ExternalLoginInfo, in which case we + // wouldn't necessarily sign the user in here with the standard login, instead we'd update the // UseUmbracoBackOfficeExternalCookieAuthentication extension method to have the correct provider and claims factory, - // ticket format, etc.. to create our back office user including the claims assigned and in this method we'd just ensure + // ticket format, etc.. to create our back office user including the claims assigned and in this method we'd just ensure // that the ticket is created and stored and that the user is logged in. //sign in @@ -591,9 +583,9 @@ namespace Umbraco.Web.Editors private async Task AutoLinkAndSignInExternalAccount(ExternalLoginInfo loginInfo) { //Here we can check if the provider associated with the request has been configured to allow - // new users (auto-linked external accounts). This would never be used with public providers such as + // new users (auto-linked external accounts). This would never be used with public providers such as // Google, unless you for some reason wanted anybody to be able to access the backend if they have a Google account - // .... not likely! + // .... not likely! var authType = OwinContext.Authentication.GetExternalAuthenticationTypes().FirstOrDefault(x => x.AuthenticationType == loginInfo.Login.LoginProvider); if (authType == null) @@ -695,31 +687,28 @@ namespace Umbraco.Web.Editors /// private Dictionary GetApplicationState() { - if (ApplicationContext.IsConfigured == false) + if (_runtime.Level != RuntimeLevel.Run) return null; - var app = new Dictionary - { - {"assemblyVersion", UmbracoVersion.AssemblyVersion} - }; - - var version = UmbracoVersion.GetSemanticVersion().ToSemanticString(); - - app.Add("version", version); - app.Add("cdf", ClientDependencySettings.Instance.Version); - //useful for dealing with virtual paths on the client side when hosted in virtual directories especially - app.Add("applicationPath", HttpContext.Request.ApplicationPath.EnsureEndsWith('/')); - - //add the server's GMT time offset in minutes - app.Add("serverTimeOffset", Convert.ToInt32(DateTimeOffset.Now.Offset.TotalMinutes)); - - return app; + return new Dictionary + { + // assembly version + { "assemblyVersion", UmbracoVersion.AssemblyVersion }, + // Umbraco version + { "version", _runtime.SemanticVersion.ToSemanticString() }, + // client dependency version, + { "cdf", ClientDependencySettings.Instance.Version }, + // for dealing with virtual paths on the client side when hosted in virtual directories + { "applicationPath", _runtime.ApplicationVirtualPath.EnsureEndsWith('/') }, + // server's GMT time offset in minutes + { "serverTimeOffset", Convert.ToInt32(DateTimeOffset.Now.Offset.TotalMinutes) } + }; } - + private IEnumerable> GetTreePluginsMetaData() { - var treeTypes = PluginManager.Current.ResolveAttributedTreeControllers(); + var treeTypes = Current.PluginManager.ResolveAttributedTreeControllers(); // fixme inject //get all plugin trees with their attributes var treesWithAttributes = treeTypes.Select(x => new { @@ -769,7 +758,7 @@ namespace Umbraco.Web.Editors //cache the result if debugging is disabled var result = HttpContext.IsDebuggingEnabled ? getResult() - : ApplicationContext.ApplicationCache.RuntimeCache.GetCacheItem( + : ApplicationCache.RuntimeCache.GetCacheItem( typeof(BackOfficeController) + "LegacyTreeJs", () => getResult(), new TimeSpan(0, 10, 0)); diff --git a/src/Umbraco.Web/Editors/BackOfficeNotificationsController.cs b/src/Umbraco.Web/Editors/BackOfficeNotificationsController.cs index f4350bc596..0199c4ba50 100644 --- a/src/Umbraco.Web/Editors/BackOfficeNotificationsController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeNotificationsController.cs @@ -3,19 +3,11 @@ using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Editors { /// - /// An abstract controller that automatically checks if any request is a non-GET and if the + /// An abstract controller that automatically checks if any request is a non-GET and if the /// resulting message is INotificationModel in which case it will append any Event Messages /// currently in the request. /// [AppendCurrentEventMessages] public abstract class BackOfficeNotificationsController : UmbracoAuthorizedJsonController - { - protected BackOfficeNotificationsController() - { - } - - protected BackOfficeNotificationsController(UmbracoContext umbracoContext) : base(umbracoContext) - { - } - } + { } } \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/CanvasDesignerController.cs b/src/Umbraco.Web/Editors/CanvasDesignerController.cs index 722167d18a..567c646328 100644 --- a/src/Umbraco.Web/Editors/CanvasDesignerController.cs +++ b/src/Umbraco.Web/Editors/CanvasDesignerController.cs @@ -1,29 +1,15 @@ using System.Collections.Generic; -using System.Net; using System.Net.Http; -using System.Text; using System.Web.Http; -using AutoMapper; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Mvc; -using umbraco; using Umbraco.Web.WebApi; using System; using System.Net.Http.Headers; using System.Web; -using System.IO; -using Umbraco.Core.Models; -using System.Text.RegularExpressions; -using System.Linq; -using Umbraco.Core; -using Umbraco.Core.Services; namespace Umbraco.Web.Editors { - public class CanvasDesignerController : UmbracoApiController { - [HttpGet] public HttpResponseMessage GetGoogleFont() { @@ -51,7 +37,7 @@ namespace Umbraco.Web.Editors public HttpResponseMessage Load() { - // Get style less url + // Get style less url var pageId = int.Parse(HttpContext.Current.Request["pageId"]); // Get all parameters @@ -59,7 +45,7 @@ namespace Umbraco.Web.Editors // Prepare string parameter result string[] paramLines = paramBlock.Trim().Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); - IList parameters = new List(); + IList parameters = new List(); foreach (var line in paramLines) { if (!line.Contains("@import")) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 61adeca8ba..488526fe19 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -40,14 +40,9 @@ namespace Umbraco.Web.Editors { private readonly IFacadeService _facadeService; - /// - /// Constructor - /// - /// - /// - public ContentController(UmbracoContext umbracoContext, IFacadeService facadeService) - : base(umbracoContext) + public ContentController(IFacadeService facadeService) { + if (facadeService == null) throw new ArgumentNullException(nameof(facadeService)); _facadeService = facadeService; } diff --git a/src/Umbraco.Web/Editors/ContentControllerBase.cs b/src/Umbraco.Web/Editors/ContentControllerBase.cs index 398136fb06..098388b547 100644 --- a/src/Umbraco.Web/Editors/ContentControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentControllerBase.cs @@ -22,23 +22,6 @@ namespace Umbraco.Web.Editors [OutgoingDateTimeFormat] public abstract class ContentControllerBase : BackOfficeNotificationsController { - /// - /// Constructor - /// - protected ContentControllerBase() - : this(UmbracoContext.Current) - { - } - - /// - /// Constructor - /// - /// - protected ContentControllerBase(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - protected HttpResponseMessage HandleContentNotFound(object id, bool throwException = true) { ModelState.AddModelError("id", string.Format("content with id: {0} was not found", id)); @@ -47,12 +30,12 @@ namespace Umbraco.Web.Editors ModelState); if (throwException) { - throw new HttpResponseException(errorResponse); + throw new HttpResponseException(errorResponse); } return errorResponse; } - protected void UpdateName(ContentBaseItemSave contentItem) + protected void UpdateName(ContentBaseItemSave contentItem) where TPersisted : IContentBase { //Don't update the name if it is empty @@ -100,7 +83,7 @@ namespace Umbraco.Web.Editors { d.Add("files", files); } - + var data = new ContentPropertyData(p.Value, p.PreValues, d); //get the deserialized value from the property editor @@ -113,7 +96,7 @@ namespace Umbraco.Web.Editors var valueEditor = p.PropertyEditor.ValueEditor; //don't persist any bound value if the editor is readonly if (valueEditor.IsReadOnly == false) - { + { var propVal = p.PropertyEditor.ValueEditor.ConvertEditorToDb(data, dboProperty.Value); var supportTagsAttribute = TagExtractor.GetAttribute(p.PropertyEditor); if (supportTagsAttribute != null) @@ -124,14 +107,14 @@ namespace Umbraco.Web.Editors { dboProperty.Value = propVal; } - } - + } + } } } - protected void HandleInvalidModelState(ContentItemDisplayBase display) - where TPersisted : IContentBase + protected void HandleInvalidModelState(ContentItemDisplayBase display) + where TPersisted : IContentBase where T : ContentPropertyBasic { //lasty, if it is not valid, add the modelstate to the outgoing object and throw a 403 @@ -160,7 +143,7 @@ namespace Umbraco.Web.Editors return Request.Properties.ContainsKey(typeof(TPersisted).ToString()) && Request.Properties[typeof(TPersisted).ToString()] != null ? (TPersisted) Request.Properties[typeof (TPersisted).ToString()] : getFromService(); - } + } /// /// Returns true if the action passed in means we need to create something new @@ -172,8 +155,8 @@ namespace Umbraco.Web.Editors return (action.ToString().EndsWith("New")); } - protected void AddCancelMessage(INotificationModel display, - string header = "speechBubbles/operationCancelledHeader", + protected void AddCancelMessage(INotificationModel display, + string header = "speechBubbles/operationCancelledHeader", string message = "speechBubbles/operationCancelledText", bool localizeHeader = true, bool localizeMessage = true) diff --git a/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs b/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs index c29146d45d..ca4554d199 100644 --- a/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs +++ b/src/Umbraco.Web/Editors/ContentPostValidateAttribute.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Editors private readonly IUserService _userService; public ContentPostValidateAttribute() - { + { } public ContentPostValidateAttribute(IContentService contentService, IUserService userService, WebSecurity security) @@ -39,7 +39,7 @@ namespace Umbraco.Web.Editors private IContentService ContentService { - get { return _contentService ?? ApplicationContext.Current.Services.ContentService; } + get { return _contentService ?? Current.Services.ContentService; } } private WebSecurity Security @@ -49,7 +49,7 @@ namespace Umbraco.Web.Editors private IUserService UserService { - get { return _userService ?? ApplicationContext.Current.Services.UserService; } + get { return _userService ?? Current.Services.UserService; } } public override bool AllowMultiple diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index d0e214a512..bd1a192c51 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Configuration; +using System.Collections.Generic; using System.Linq; using System.Net; using System.Web.Http; @@ -10,16 +8,11 @@ using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Constants = Umbraco.Core.Constants; using Umbraco.Core.Services; -using Umbraco.Core.PropertyEditors; using System.Net.Http; -using umbraco; using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Core.Strings; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Logging; -using Umbraco.Web.Models; namespace Umbraco.Web.Editors { @@ -36,23 +29,6 @@ namespace Umbraco.Web.Editors [EnableOverrideAuthorization] public class ContentTypeController : ContentTypeControllerBase { - /// - /// Constructor - /// - public ContentTypeController() - : this(UmbracoContext.Current) - { - } - - /// - /// Constructor - /// - /// - public ContentTypeController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - public int GetCount() { return Services.ContentTypeService.Count(); @@ -99,7 +75,7 @@ namespace Umbraco.Web.Editors Constants.Trees.MemberTypes, Constants.Trees.Members)] public IEnumerable GetAllPropertyTypeAliases() { - return ApplicationContext.Services.ContentTypeService.GetAllPropertyTypeAliases(); + return Services.ContentTypeService.GetAllPropertyTypeAliases(); } /// @@ -142,7 +118,7 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.NotFound); } - var preVals = UmbracoContext.Current.Application.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(id); + var preVals = Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(id); var editor = Current.PropertyEditors[dataTypeDiff.PropertyEditorAlias]; return new ContentPropertyDisplay() diff --git a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs index d19251346d..d9fc85394a 100644 --- a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs @@ -27,23 +27,6 @@ namespace Umbraco.Web.Editors { private ICultureDictionary _cultureDictionary; - /// - /// Constructor - /// - protected ContentTypeControllerBase() - : this(UmbracoContext.Current) - { - } - - /// - /// Constructor - /// - /// - protected ContentTypeControllerBase(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - /// /// Returns the available composite content types for a given content type /// @@ -355,7 +338,7 @@ namespace Umbraco.Web.Editors where TPropertyType : PropertyTypeBasic where TContentTypeDisplay : ContentTypeCompositionDisplay { - var service = ApplicationContext.Services.GetContentTypeService(); + var service = Services.GetContentTypeService(); var validateAttempt = service.ValidateComposition(composition); if (validateAttempt == false) { diff --git a/src/Umbraco.Web/Editors/CurrentUserController.cs b/src/Umbraco.Web/Editors/CurrentUserController.cs index 67bfd61fa6..19cc000f14 100644 --- a/src/Umbraco.Web/Editors/CurrentUserController.cs +++ b/src/Umbraco.Web/Editors/CurrentUserController.cs @@ -17,16 +17,15 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class CurrentUserController : UmbracoAuthorizedJsonController { - /// /// Returns the configuration for the backoffice user membership provider - used to configure the change password dialog /// /// public IDictionary GetMembershipProviderConfig() { - var provider = Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider(); + var provider = Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider(); return provider.GetConfiguration(); - } + } /// /// Changes the users password diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index 701cca0bb2..9b05232b17 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -4,16 +4,13 @@ using Umbraco.Core.Configuration; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using System.Linq; -using System.Xml; using Umbraco.Core.IO; namespace Umbraco.Web.Editors { - [PluginController("UmbracoApi")] public class DashboardController : UmbracoAuthorizedJsonController { - public IEnumerable> GetDashboard(string section) { var tabs = new List>(); diff --git a/src/Umbraco.Web/Editors/DataTypeController.cs b/src/Umbraco.Web/Editors/DataTypeController.cs index 892d7c2112..94ccfc2105 100644 --- a/src/Umbraco.Web/Editors/DataTypeController.cs +++ b/src/Umbraco.Web/Editors/DataTypeController.cs @@ -4,19 +4,15 @@ using System.Data; using System.Linq; using System.Net; using System.Web.Http; -using System.Web.Http.ModelBinding; using AutoMapper; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Models.Mapping; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; -using Umbraco.Web.WebApi.Binders; using Umbraco.Web.WebApi.Filters; -using umbraco; using Constants = Umbraco.Core.Constants; using System.Net.Http; using System.Text; @@ -75,7 +71,7 @@ namespace Umbraco.Web.Editors { throw new HttpResponseException(HttpStatusCode.NotFound); } - + Services.DataTypeService.Delete(foundType, Security.CurrentUser.Id); return Request.CreateResponse(HttpStatusCode.OK); @@ -111,7 +107,7 @@ namespace Umbraco.Web.Editors public DataTypeDisplay PostCreateCustomListView(string contentTypeAlias) { var dt = Services.DataTypeService.GetDataTypeDefinitionByName(Constants.Conventions.DataTypes.ListViewPrefix + contentTypeAlias); - + //if it doesnt exist yet, we will create it. if (dt == null) { @@ -120,7 +116,7 @@ namespace Umbraco.Web.Editors Services.DataTypeService.Save(dt); } - return Mapper.Map(dt); + return Mapper.Map(dt); } /// @@ -160,7 +156,7 @@ namespace Umbraco.Web.Editors } //these are new pre-values, so just return the field editors with default values - return Mapper.Map>(propEd); + return Mapper.Map>(propEd); } /// @@ -182,7 +178,7 @@ namespace Umbraco.Web.Editors var result = Services.DataTypeService.CreateContainer(parentId, name, Security.CurrentUser.Id); return result - ? Request.CreateResponse(HttpStatusCode.OK, result.Result) //return the id + ? Request.CreateResponse(HttpStatusCode.OK, result.Result) //return the id : Request.CreateNotificationValidationErrorResponse(result.Exception.Message); } @@ -197,9 +193,9 @@ namespace Umbraco.Web.Editors //If we've made it here, then everything has been wired up and validated by the attribute //finally we need to save the data type and it's pre-vals - var dtService = ApplicationContext.Services.DataTypeService; + var dtService = Services.DataTypeService; - //TODO: Check if the property editor has changed, if it has ensure we don't pass the + //TODO: Check if the property editor has changed, if it has ensure we don't pass the // existing values to the new property editor! //get the prevalues, current and new @@ -255,7 +251,7 @@ namespace Umbraco.Web.Editors case MoveOperationStatusType.FailedParentNotFound: return Request.CreateResponse(HttpStatusCode.NotFound); case MoveOperationStatusType.FailedCancelledByEvent: - //returning an object of INotificationModel will ensure that any pending + //returning an object of INotificationModel will ensure that any pending // notification messages are added to the response. return Request.CreateValidationErrorResponse(new SimpleNotificationModel()); case MoveOperationStatusType.FailedNotAllowedByPath: @@ -274,7 +270,7 @@ namespace Umbraco.Web.Editors /// /// /// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members - /// + /// [UmbracoApplicationAuthorize( Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members, Constants.Applications.Settings, Constants.Applications.Developer)] @@ -291,7 +287,7 @@ namespace Umbraco.Web.Editors /// /// /// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members - /// + /// [UmbracoTreeAuthorize( Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members, Constants.Applications.Settings, Constants.Applications.Developer)] @@ -324,14 +320,14 @@ namespace Umbraco.Web.Editors /// /// /// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members - /// + /// [UmbracoTreeAuthorize( Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members, Constants.Applications.Settings, Constants.Applications.Developer)] public IDictionary> GetGroupedPropertyEditors() { var datatypes = new List(); - + var propertyEditors = Current.PropertyEditors; foreach (var propertyEditor in propertyEditors) { @@ -355,7 +351,7 @@ namespace Umbraco.Web.Editors /// /// /// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members - /// + /// [UmbracoTreeAuthorize( Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members, Constants.Applications.Settings, Constants.Applications.Developer)] diff --git a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs index a1a1991f52..6d885a3863 100644 --- a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs +++ b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Editors private readonly IDataTypeService _dataTypeService; public DataTypeValidateAttribute() - { + { } public DataTypeValidateAttribute(IDataTypeService dataTypeService) @@ -35,7 +35,7 @@ namespace Umbraco.Web.Editors private IDataTypeService DataTypeService { - get { return _dataTypeService ?? ApplicationContext.Current.Services.DataTypeService; } + get { return _dataTypeService ?? Current.Services.DataTypeService; } } public override void OnActionExecuting(HttpActionContext actionContext) @@ -89,7 +89,7 @@ namespace Umbraco.Web.Editors foreach (var preVal in dataType.PreValues) { var postedValue = preVal.Value; - + foreach (var v in propertyEditor.PreValueEditor.Fields.Where(x => x.Key == preVal.Key).SelectMany(x => x.Validators)) { foreach (var result in v.Validate(postedValue, null, propertyEditor)) diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index da964c576f..4d83a3deab 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -4,28 +4,16 @@ using System.Globalization; using System.Net; using System.Text; using System.Web.Http; -using System.Web.Http.ModelBinding; using AutoMapper; -using ClientDependency.Core; using Examine.LuceneEngine; -using Examine.LuceneEngine.Providers; -using Newtonsoft.Json; using Umbraco.Core; -using Umbraco.Core.Logging; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using System.Linq; -using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models; -using Umbraco.Web.WebApi.Filters; -using umbraco.cms.businesslogic.packager; using Constants = Umbraco.Core.Constants; using Examine; -using Examine.LuceneEngine.SearchCriteria; -using Examine.SearchCriteria; -using umbraco; using System.Text.RegularExpressions; using Umbraco.Core.Xml; diff --git a/src/Umbraco.Web/Editors/GravatarController.cs b/src/Umbraco.Web/Editors/GravatarController.cs index f1e184dce7..2dda8a448a 100644 --- a/src/Umbraco.Web/Editors/GravatarController.cs +++ b/src/Umbraco.Web/Editors/GravatarController.cs @@ -17,7 +17,7 @@ namespace Umbraco.Web.Editors var user = userService.GetUserById(UmbracoContext.Security.CurrentUser.Id); var gravatarHash = user.Email.ToMd5(); var gravatarUrl = "https://www.gravatar.com/avatar/" + gravatarHash; - + // Test if we can reach this URL, will fail when there's network or firewall errors var request = (HttpWebRequest)WebRequest.Create(gravatarUrl); // Require response within 10 seconds diff --git a/src/Umbraco.Web/Editors/ImagesController.cs b/src/Umbraco.Web/Editors/ImagesController.cs index 416ffc2553..42497b9dae 100644 --- a/src/Umbraco.Web/Editors/ImagesController.cs +++ b/src/Umbraco.Web/Editors/ImagesController.cs @@ -1,16 +1,12 @@ using System; -using System.Drawing; using System.IO; using System.Net; using System.Net.Http; -using System.Net.Http.Headers; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; -using Umbraco.Core.Media; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; -using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Editors diff --git a/src/Umbraco.Web/Editors/LegacyController.cs b/src/Umbraco.Web/Editors/LegacyController.cs index e4af23bfd8..a55fca7678 100644 --- a/src/Umbraco.Web/Editors/LegacyController.cs +++ b/src/Umbraco.Web/Editors/LegacyController.cs @@ -3,10 +3,7 @@ using System.Net; using System.Net.Http; using System.Web; using System.Web.Http; -using Umbraco.Core; using Umbraco.Web.Mvc; -using Umbraco.Web.UI; -using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using Umbraco.Web._Legacy.UI; @@ -14,29 +11,11 @@ namespace Umbraco.Web.Editors { /// /// The API controller used for dealing with legacy content - /// + /// [PluginController("UmbracoApi")] [ValidationFilter] public class LegacyController : UmbracoAuthorizedJsonController { - - /// - /// Constructor - /// - public LegacyController() - : this(UmbracoContext.Current) - { - } - - /// - /// Constructor - /// - /// - internal LegacyController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - /// /// This will perform the delete operation for legacy items which include any item that /// has functionality included in the ui.xml structure. @@ -45,7 +24,7 @@ namespace Umbraco.Web.Editors [HttpPost] public HttpResponseMessage DeleteLegacyItem(string nodeId, string alias, string nodeType) { - //U4-2686 - alias is html encoded, make sure to decode + //U4-2686 - alias is html encoded, make sure to decode alias = HttpUtility.HtmlDecode(alias); //In order to process this request we MUST have an HttpContext available @@ -66,7 +45,7 @@ namespace Umbraco.Web.Editors return Request.CreateResponse(HttpStatusCode.OK); } - //the way this legacy stuff used to work is that if the node id didn't parse, we would + //the way this legacy stuff used to work is that if the node id didn't parse, we would //pass the node id as the alias with an id of zero = sure whatevs. LegacyDialogHandler.Delete(httpContextAttempt.Result, Security.CurrentUser, nodeType, 0, nodeId); return Request.CreateResponse(HttpStatusCode.OK); diff --git a/src/Umbraco.Web/Editors/LogController.cs b/src/Umbraco.Web/Editors/LogController.cs index df4bf924d7..e8898ff84d 100644 --- a/src/Umbraco.Web/Editors/LogController.cs +++ b/src/Umbraco.Web/Editors/LogController.cs @@ -1,13 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Web.Http; using AutoMapper; -using Umbraco.Core; using Umbraco.Web.Models.ContentEditing; -using umbraco.BusinessLogic; using Umbraco.Core.Models; using Umbraco.Web.Mvc; @@ -29,7 +23,7 @@ namespace Umbraco.Web.Editors { if (sinceDate == null) sinceDate = DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0, 0)); - + return Mapper.Map>( Services.AuditService.GetUserLogs(Security.CurrentUser.Id, logType, sinceDate.Value)); } diff --git a/src/Umbraco.Web/Editors/MacroController.cs b/src/Umbraco.Web/Editors/MacroController.cs index 9cdbc0e0df..c2b684b349 100644 --- a/src/Umbraco.Web/Editors/MacroController.cs +++ b/src/Umbraco.Web/Editors/MacroController.cs @@ -7,7 +7,6 @@ using System.Web.Http; using AutoMapper; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; -using umbraco; using Umbraco.Web.Macros; namespace Umbraco.Web.Editors @@ -18,14 +17,12 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class MacroController : UmbracoAuthorizedJsonController { - - /// /// Gets the macro parameters to be filled in for a particular macro /// /// /// - /// Note that ALL logged in users have access to this method because editors will need to isnert macros into rte (content/media/members) and it's used for + /// Note that ALL logged in users have access to this method because editors will need to isnert macros into rte (content/media/members) and it's used for /// inserting into templates/views/etc... it doesn't expose any sensitive data. /// public IEnumerable GetMacroParameters(int macroId) @@ -46,9 +43,9 @@ namespace Umbraco.Web.Editors /// /// /// To send a dictionary as a GET parameter the query should be structured like: - /// + /// /// ?macroAlias=Test&pageId=3634¯oParams[0].key=myKey¯oParams[0].value=myVal¯oParams[1].key=anotherKey¯oParams[1].value=anotherVal - /// + /// /// /// [HttpGet] diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index be2bb9ad7c..3a5735576b 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -4,10 +4,8 @@ using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Formatting; -using System.Security.AccessControl; using System.Text; using System.Threading.Tasks; -using System.Web; using System.Web.Http; using System.Web.Http.ModelBinding; using AutoMapper; @@ -15,23 +13,18 @@ using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Models.Editors; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Services; -using Umbraco.Web.Models; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Mapping; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; using System.Linq; -using System.Runtime.Serialization; using Umbraco.Web.WebApi.Binders; using Umbraco.Web.WebApi.Filters; -using umbraco; using Constants = Umbraco.Core.Constants; using Umbraco.Core.Configuration; -using Umbraco.Core.Persistence.FaultHandling; using Umbraco.Core.Persistence.Querying; using Umbraco.Web.UI; using Notification = Umbraco.Web.Models.ContentEditing.Notification; @@ -47,24 +40,7 @@ namespace Umbraco.Web.Editors public class MediaController : ContentControllerBase { /// - /// Constructor - /// - public MediaController() - : this(UmbracoContext.Current) - { - } - - /// - /// Constructor - /// - /// - public MediaController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - - /// - /// Gets an empty content item for the + /// Gets an empty content item for the /// /// /// @@ -189,7 +165,7 @@ namespace Umbraco.Web.Editors IQuery queryFilter = null; if (filter.IsNullOrWhiteSpace() == false) { - //add the default text filter + //add the default text filter queryFilter = DatabaseContext.QueryFactory.Create() .Where(x => x.Name.Contains(filter)); } @@ -223,7 +199,7 @@ namespace Umbraco.Web.Editors /// Moves an item to the recycle bin, if it is already there then it will permanently delete it /// /// - /// + /// [EnsureUserPermissionForMedia("id")] [HttpPost] public HttpResponseMessage DeleteById(int id) @@ -241,7 +217,7 @@ namespace Umbraco.Web.Editors var moveResult = Services.MediaService.WithResult().MoveToRecycleBin(foundMedia, (int)Security.CurrentUser.Id); if (moveResult == false) { - //returning an object of INotificationModel will ensure that any pending + //returning an object of INotificationModel will ensure that any pending // notification messages are added to the response. return Request.CreateValidationErrorResponse(new SimpleNotificationModel()); } @@ -251,7 +227,7 @@ namespace Umbraco.Web.Editors var deleteResult = Services.MediaService.WithResult().Delete(foundMedia, (int)Security.CurrentUser.Id); if (deleteResult == false) { - //returning an object of INotificationModel will ensure that any pending + //returning an object of INotificationModel will ensure that any pending // notification messages are added to the response. return Request.CreateValidationErrorResponse(new SimpleNotificationModel()); } @@ -280,7 +256,7 @@ namespace Umbraco.Web.Editors /// /// Saves content /// - /// + /// [FileUploadCleanupFilter] [MediaPostValidate] public MediaItemDisplay PostSave( @@ -300,7 +276,7 @@ namespace Umbraco.Web.Editors // * We still need to save the entity even if there are validation value errors // * Depending on if the entity is new, and if there are non property validation errors (i.e. the name is null) // then we cannot continue saving, we can only display errors - // * If there are validation errors and they were attempting to publish, we can only save, NOT publish and display + // * If there are validation errors and they were attempting to publish, we can only save, NOT publish and display // a message indicating this if (ModelState.IsValid == false) { @@ -324,7 +300,7 @@ namespace Umbraco.Web.Editors //lasty, if it is not valid, add the modelstate to the outgoing object and throw a 403 HandleInvalidModelState(display); - //put the correct msgs in + //put the correct msgs in switch (contentItem.Action) { case ContentSaveAction.Save: @@ -398,7 +374,7 @@ namespace Umbraco.Web.Editors return Request.CreateResponse(HttpStatusCode.OK); } - var mediaService = base.ApplicationContext.Services.MediaService; + var mediaService = Services.MediaService; var sortedMedia = new List(); try { @@ -422,7 +398,7 @@ namespace Umbraco.Web.Editors [EnsureUserPermissionForMedia("folder.ParentId")] public MediaItemDisplay PostAddFolder(EntityBasic folder) { - var mediaService = ApplicationContext.Services.MediaService; + var mediaService = Services.MediaService; var f = mediaService.CreateMedia(folder.Name, folder.ParentId, Constants.Conventions.MediaTypes.Folder); mediaService.Save(f, Security.CurrentUser.Id); @@ -479,7 +455,7 @@ namespace Umbraco.Web.Editors } var tempFiles = new PostedFiles(); - var mediaService = ApplicationContext.Services.MediaService; + var mediaService = Services.MediaService; //in case we pass a path with a folder in it, we will create it and upload media to it. @@ -544,7 +520,7 @@ namespace Umbraco.Web.Editors if (UmbracoConfig.For.UmbracoSettings().Content.ImageFileTypes.Contains(ext)) mediaType = Constants.Conventions.MediaTypes.Image; - //TODO: make the media item name "nice" since file names could be pretty ugly, we have + //TODO: make the media item name "nice" since file names could be pretty ugly, we have // string extensions to do much of this but we'll need: // * Pascalcase the name (use string extensions) // * strip the file extension @@ -605,7 +581,7 @@ namespace Umbraco.Web.Editors return Request.CreateResponse(HttpStatusCode.OK, tempFiles); } - + /// /// Ensures the item can be moved/copied to the new location /// @@ -664,7 +640,7 @@ namespace Umbraco.Web.Editors } /// - /// Performs a permissions check for the user to check if it has access to the node based on + /// Performs a permissions check for the user to check if it has access to the node based on /// start node and/or permissions for the node /// /// The storage to add the content item to so it can be reused @@ -678,7 +654,7 @@ namespace Umbraco.Web.Editors if (media == null && nodeId != Constants.System.Root && nodeId != Constants.System.RecycleBinMedia) { media = mediaService.GetById(nodeId); - //put the content item into storage so it can be retreived + //put the content item into storage so it can be retreived // in the controller (saves a lookup) storage[typeof(IMedia).ToString()] = media; } diff --git a/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs b/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs index ed26fcbc57..dc68445253 100644 --- a/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs +++ b/src/Umbraco.Web/Editors/MediaPostValidateAttribute.cs @@ -35,7 +35,7 @@ namespace Umbraco.Web.Editors private IMediaService MediaService { - get { return _mediaService ?? ApplicationContext.Current.Services.MediaService; } + get { return _mediaService ?? Current.Services.MediaService; } } private WebSecurity Security diff --git a/src/Umbraco.Web/Editors/MediaTypeController.cs b/src/Umbraco.Web/Editors/MediaTypeController.cs index bf5ea1c9e6..7d2dd14f44 100644 --- a/src/Umbraco.Web/Editors/MediaTypeController.cs +++ b/src/Umbraco.Web/Editors/MediaTypeController.cs @@ -1,24 +1,16 @@ using System.Collections.Generic; using System.Linq; -using System.Web.Security; using AutoMapper; -using Umbraco.Core; using Umbraco.Core.Models; -using Umbraco.Core.Security; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; using System.Web.Http; using System.Net; -using Umbraco.Core.PropertyEditors; -using System; using System.Net.Http; -using System.Text; using Umbraco.Web.WebApi; -using ContentType = System.Net.Mime.ContentType; using Umbraco.Core.Services; -using Umbraco.Web.Models; namespace Umbraco.Web.Editors { @@ -34,24 +26,6 @@ namespace Umbraco.Web.Editors [EnableOverrideAuthorization] public class MediaTypeController : ContentTypeControllerBase { - /// - /// Constructor - /// - public MediaTypeController() - : this(UmbracoContext.Current) - { - } - - /// - /// Constructor - /// - /// - public MediaTypeController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - - } - public int GetCount() { return Services.ContentTypeService.Count(); diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs index 9d9093486f..067e79cf25 100644 --- a/src/Umbraco.Web/Editors/MemberController.cs +++ b/src/Umbraco.Web/Editors/MemberController.cs @@ -1,24 +1,16 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Net; using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using System.Web; using System.Web.Http; using System.Web.Http.ModelBinding; using System.Web.Security; using AutoMapper; -using Examine.LuceneEngine.SearchCriteria; -using Examine.SearchCriteria; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Security; using Umbraco.Core.Services; @@ -28,9 +20,7 @@ using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Binders; using Umbraco.Web.WebApi.Filters; -using umbraco; using Constants = Umbraco.Core.Constants; -using Examine; namespace Umbraco.Web.Editors { @@ -43,26 +33,7 @@ namespace Umbraco.Web.Editors [OutgoingNoHyphenGuidFormat] public class MemberController : ContentControllerBase { - /// - /// Constructor - /// - public MemberController() - : this(UmbracoContext.Current) - { - _provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); - } - - /// - /// Constructor - /// - /// - public MemberController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - _provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); - } - - private readonly MembershipProvider _provider; + private readonly MembershipProvider _provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); /// /// Returns the currently configured membership scenario for members in umbraco @@ -213,7 +184,7 @@ namespace Umbraco.Web.Editors } /// - /// Gets an empty content item for the + /// Gets an empty content item for the /// /// /// @@ -253,7 +224,7 @@ namespace Umbraco.Web.Editors /// /// Saves member /// - /// + /// [FileUploadCleanupFilter] public MemberDisplay PostSave( [ModelBinder(typeof(MemberBinder))] @@ -297,7 +268,7 @@ namespace Umbraco.Web.Editors } //We're gonna look up the current roles now because the below code can cause - // events to be raised and developers could be manually adding roles to members in + // events to be raised and developers could be manually adding roles to members in // their handlers. If we don't look this up now there's a chance we'll just end up // removing the roles they've assigned. var currRoles = Roles.GetRolesForUser(contentItem.PersistedContent.Username); @@ -332,7 +303,7 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay)); } - //save the IMember - + //save the IMember - //TODO: When we support the CustomProviderWithUmbracoLink scenario, we'll need to save the custom properties for that here too if (MembershipScenario == MembershipScenario.NativeUmbraco) { @@ -360,7 +331,7 @@ namespace Umbraco.Web.Editors } //set the generated password (if there was one) - in order to do this we'll chuck the gen'd password into the - // additional data of the IUmbracoEntity of the persisted item - then we can retrieve this in the model mapper and set + // additional data of the IUmbracoEntity of the persisted item - then we can retrieve this in the model mapper and set // the value to be given to the UI. Hooray for AdditionalData :) contentItem.PersistedContent.AdditionalData["GeneratedPassword"] = generatedPassword; @@ -371,7 +342,7 @@ namespace Umbraco.Web.Editors HandleInvalidModelState(display); var localizedTextService = Services.TextService; - //put the correct msgs in + //put the correct msgs in switch (contentItem.Action) { case ContentSaveAction.Save: @@ -431,7 +402,7 @@ namespace Umbraco.Web.Editors if (requiredUpdating.Success) { - //re-map these values + //re-map these values shouldReFetchMember = true; } } @@ -471,10 +442,10 @@ namespace Umbraco.Web.Editors ModelState.AddModelError("custom", "An admin cannot lock a user"); } - //password changes ? + //password changes ? if (contentItem.Password == null) { - //If the provider has changed some values, these values need to be reflected in the member object + //If the provider has changed some values, these values need to be reflected in the member object //that will get mapped to the display object if (shouldReFetchMember) { @@ -488,7 +459,7 @@ namespace Umbraco.Web.Editors var passwordChangeResult = Members.ChangePassword(membershipUser.UserName, contentItem.Password, _provider); if (passwordChangeResult.Success) { - //If the provider has changed some values, these values need to be reflected in the member object + //If the provider has changed some values, these values need to be reflected in the member object //that will get mapped to the display object if (shouldReFetchMember) { @@ -566,7 +537,7 @@ namespace Umbraco.Web.Editors } /// - /// Following a refresh of member data called during an update if the membership provider has changed some underlying data, + /// Following a refresh of member data called during an update if the membership provider has changed some underlying data, /// we don't want to lose the provided, and potentiallly changed, username /// /// @@ -584,18 +555,18 @@ namespace Umbraco.Web.Editors /// /// /// Depending on if the Umbraco membership provider is active or not, the process differs slightly: - /// - /// * If the umbraco membership provider is used - we create the membership user first with the membership provider, since + /// + /// * If the umbraco membership provider is used - we create the membership user first with the membership provider, since /// it's the umbraco membership provider, this writes to the umbraco tables. When that is complete we re-fetch the IMember /// model data from the db. In this case we don't care what the provider user key is. - /// * If we're using a non-umbraco membership provider - we check if there is a 'Member' member type - if so + /// * If we're using a non-umbraco membership provider - we check if there is a 'Member' member type - if so /// we create an empty IMember instance first (of type 'Member'), this gives us a unique ID (GUID) - /// that we then use to create the member in the custom membership provider. This acts as the link between Umbraco data and + /// that we then use to create the member in the custom membership provider. This acts as the link between Umbraco data and /// the custom membership provider data. This gives us the ability to eventually have custom membership properties but still use /// a custom memberhip provider. If there is no 'Member' member type, then we will simply just create the membership provider member /// with no link to our data. - /// - /// If this is successful, it will go and re-fetch the IMember from the db because it will now have an ID because the Umbraco provider + /// + /// If this is successful, it will go and re-fetch the IMember from the db because it will now have an ID because the Umbraco provider /// uses the umbraco data store - then of course we need to re-map it to the saved property values. /// private MembershipUser CreateWithMembershipProvider(MemberSave contentItem, out MembershipCreateStatus status) @@ -619,7 +590,7 @@ namespace Umbraco.Web.Editors break; case MembershipScenario.CustomProviderWithUmbracoLink: //We are using a custom membership provider, we'll create an empty IMember first to get the unique id to use - // as the provider user key. + // as the provider user key. //create it - this persisted item has already been set in the MemberBinder based on the 'Member' member type: Services.MemberService.Save(contentItem.PersistedContent); @@ -731,7 +702,7 @@ namespace Umbraco.Web.Editors /// /// /// - /// + /// [HttpPost] public HttpResponseMessage DeleteByKey(Guid key) { diff --git a/src/Umbraco.Web/Editors/MemberGroupController.cs b/src/Umbraco.Web/Editors/MemberGroupController.cs index 1b74b77949..0c5e77eef0 100644 --- a/src/Umbraco.Web/Editors/MemberGroupController.cs +++ b/src/Umbraco.Web/Editors/MemberGroupController.cs @@ -19,22 +19,10 @@ namespace Umbraco.Web.Editors /// An API controller used for dealing with member groups /// [PluginController("UmbracoApi")] - [UmbracoTreeAuthorize(Constants.Trees.MemberGroups)] + [UmbracoTreeAuthorize(Constants.Trees.MemberGroups)] public class MemberGroupController : UmbracoAuthorizedJsonController { - public MemberGroupController() - : this(UmbracoContext.Current) - { - _provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); - } - - public MemberGroupController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - _provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); - } - - private readonly MembershipProvider _provider; + private readonly MembershipProvider _provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); public MemberGroupDisplay GetById(int id) { @@ -67,7 +55,7 @@ namespace Umbraco.Web.Editors if (_provider.IsUmbracoMembershipProvider()) { return Services.MemberGroupService.GetAll() - .Select(Mapper.Map); + .Select(Mapper.Map); } return Enumerable.Empty(); @@ -81,7 +69,7 @@ namespace Umbraco.Web.Editors public MemberGroupDisplay PostSave(MemberGroupSave saveModel) { - var service = ApplicationContext.Services.MemberGroupService; + var service = Services.MemberGroupService; var id = int.Parse(saveModel.Id.ToString()); var memberGroup = id > 0 ? service.GetById(id) : new MemberGroup(); diff --git a/src/Umbraco.Web/Editors/MemberTypeController.cs b/src/Umbraco.Web/Editors/MemberTypeController.cs index 49dcf8c522..46370ff1a3 100644 --- a/src/Umbraco.Web/Editors/MemberTypeController.cs +++ b/src/Umbraco.Web/Editors/MemberTypeController.cs @@ -15,34 +15,15 @@ using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Editors { - + /// /// An API controller used for dealing with member types /// [PluginController("UmbracoApi")] - [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)] + [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)] public class MemberTypeController : ContentTypeControllerBase { - /// - /// Constructor - /// - public MemberTypeController() - : this(UmbracoContext.Current) - { - _provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); - } - - /// - /// Constructor - /// - /// - public MemberTypeController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - _provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); - } - - private readonly MembershipProvider _provider; + private readonly MembershipProvider _provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); public MemberTypeDisplay GetById(int id) { @@ -111,7 +92,7 @@ namespace Umbraco.Web.Editors return dto; } - + /// /// Returns all member types /// @@ -120,7 +101,7 @@ namespace Umbraco.Web.Editors if (_provider.IsUmbracoMembershipProvider()) { return Services.MemberTypeService.GetAll() - .Select(Mapper.Map); + .Select(Mapper.Map); } return Enumerable.Empty(); } diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index ad4d94a667..86b763b63b 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -2,24 +2,16 @@ using System.Collections.Generic; using System.Globalization; using System.IO; -using System.IO.Compression; using System.Linq; using System.Net; using System.Net.Http; -using System.Text; using System.Threading.Tasks; using System.Web.Http; -using System.Web.UI.WebControls; using System.Xml; -using System.Xml.Linq; -using umbraco; -using umbraco.BusinessLogic; using umbraco.cms.businesslogic.packager; using umbraco.cms.businesslogic.packager.repositories; -using umbraco.cms.businesslogic.web; using umbraco.cms.presentation.Trees; using umbraco.presentation.developer.packages; -using umbraco.webservices; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; @@ -34,7 +26,6 @@ using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using File = System.IO.File; using Notification = Umbraco.Web.Models.ContentEditing.Notification; -using Settings = umbraco.cms.businesslogic.packager.Settings; using Version = System.Version; namespace Umbraco.Web.Editors @@ -97,9 +88,7 @@ namespace Umbraco.Web.Editors if (int.TryParse(item, out nId) == false) continue; var found = Services.FileService.GetTemplate(nId); if (found != null) - { - ApplicationContext.Services.FileService.DeleteTemplate(found.Alias, Security.GetUserId()); - } + Services.FileService.DeleteTemplate(found.Alias, Security.GetUserId()); pack.Data.Templates.Remove(nId.ToString()); } @@ -541,7 +530,7 @@ namespace Umbraco.Web.Editors ins.LoadConfig(IOHelper.MapPath(model.TemporaryDirectoryPath)); ins.InstallCleanUp(model.Id, IOHelper.MapPath(model.TemporaryDirectoryPath)); - var clientDependencyConfig = new Umbraco.Core.Configuration.ClientDependencyConfiguration(ApplicationContext.ProfilingLogger.Logger); + var clientDependencyConfig = new Umbraco.Core.Configuration.ClientDependencyConfiguration(Logger); var clientDependencyUpdated = clientDependencyConfig.IncreaseVersionNumber(); //clear the tree cache - we'll do this here even though the browser will reload, but just in case it doesn't can't hurt. diff --git a/src/Umbraco.Web/Editors/RelationController.cs b/src/Umbraco.Web/Editors/RelationController.cs index 099d5b5c13..39eeb87b7e 100644 --- a/src/Umbraco.Web/Editors/RelationController.cs +++ b/src/Umbraco.Web/Editors/RelationController.cs @@ -17,16 +17,6 @@ namespace Umbraco.Web.Editors [UmbracoApplicationAuthorizeAttribute(Constants.Applications.Content)] public class RelationController : UmbracoAuthorizedJsonController { - public RelationController() - : this(UmbracoContext.Current) - { - } - - public RelationController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - public Relation GetById(int id) { return Mapper.Map(Services.RelationService.GetById(id)); diff --git a/src/Umbraco.Web/Editors/SectionController.cs b/src/Umbraco.Web/Editors/SectionController.cs index fa876759ab..c74d5e7430 100644 --- a/src/Umbraco.Web/Editors/SectionController.cs +++ b/src/Umbraco.Web/Editors/SectionController.cs @@ -1,9 +1,7 @@ using System.Collections.Generic; using AutoMapper; -using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi; using System.Linq; namespace Umbraco.Web.Editors @@ -18,6 +16,6 @@ namespace Umbraco.Web.Editors { var sections = Services.SectionService.GetAllowedSections(Security.GetUserId()); return sections.Select(Mapper.Map); - } + } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/StylesheetController.cs b/src/Umbraco.Web/Editors/StylesheetController.cs index 535351a14f..83832c2544 100644 --- a/src/Umbraco.Web/Editors/StylesheetController.cs +++ b/src/Umbraco.Web/Editors/StylesheetController.cs @@ -1,40 +1,27 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using System.Web.Http; -using System.Web.Services.Description; -using Newtonsoft.Json.Linq; -using umbraco.cms.businesslogic.web; using Umbraco.Core; -using Umbraco.Core.IO; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Editors { /// /// The API controller used for retrieving available stylesheets /// - [PluginController("UmbracoApi")] + [PluginController("UmbracoApi")] public class StylesheetController : UmbracoAuthorizedJsonController { public IEnumerable GetAll() { return Services.FileService.GetStylesheets() - .Select(x => + .Select(x => new Stylesheet() { Name = x.Alias, Path = x.VirtualPath }); } - + public IEnumerable GetRulesByName(string name) { var css = Services.FileService.GetStylesheetByName(name.EnsureEndsWith(".css")); diff --git a/src/Umbraco.Web/Editors/TemplateQueryController.cs b/src/Umbraco.Web/Editors/TemplateQueryController.cs index 913684da0e..3f0bd39904 100644 --- a/src/Umbraco.Web/Editors/TemplateQueryController.cs +++ b/src/Umbraco.Web/Editors/TemplateQueryController.cs @@ -1,9 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Umbraco.Core.Models; using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; using Umbraco.Web.WebApi; using System; using System.Diagnostics; @@ -12,7 +10,7 @@ using Umbraco.Web.Models.TemplateQuery; namespace Umbraco.Web.Editors { - + /// /// The API controller used for building content queries within the template @@ -21,14 +19,6 @@ namespace Umbraco.Web.Editors [JsonCamelCaseFormatter] public class TemplateQueryController : UmbracoAuthorizedJsonController { - public TemplateQueryController() - { } - - public TemplateQueryController(UmbracoContext umbracoContext) - :base(umbracoContext) - { } - - private static readonly IEnumerable Terms = new List() { new OperathorTerm("is", Operathor.Equals, new [] {"string"}), @@ -59,16 +49,16 @@ namespace Umbraco.Web.Editors public QueryResultModel PostTemplateQuery(QueryModel model) { - var umbraco = new UmbracoHelper(UmbracoContext); + var umbraco = new UmbracoHelper(UmbracoContext, Services, ApplicationCache); var queryResult = new QueryResultModel(); var sb = new StringBuilder(); - + sb.Append("CurrentPage.Site()"); - + var timer = new Stopwatch(); - + timer.Start(); var currentPage = umbraco.ContentAtRoot().FirstOrDefault(); @@ -108,8 +98,8 @@ namespace Umbraco.Web.Editors } } } - - // TYPE to return if filtered by type + + // TYPE to return if filtered by type IEnumerable contents; if (model != null && string.IsNullOrEmpty(model.ContentType.Alias) == false) { @@ -142,7 +132,7 @@ namespace Umbraco.Web.Editors { if(string.IsNullOrEmpty( condition.ConstraintValue)) continue; - + var operation = condition.BuildCondition(token); @@ -167,7 +157,7 @@ namespace Umbraco.Web.Editors timer.Stop(); clause = string.Format("\"Visible && {0}\",{1}", clause, - string.Join(",", model.Filters.Select(x => x.Property.Type == "string" ? + string.Join(",", model.Filters.Select(x => x.Property.Type == "string" ? string.Format("\"{0}\"", x.ConstraintValue) : x.ConstraintValue).ToArray())); sb.AppendFormat(".Where({0})", clause); @@ -245,12 +235,12 @@ namespace Umbraco.Web.Editors ? contents.OrderBy(x => x.Id) : contents.OrderByDescending(x => x.Id); case "createDate" : - + return sortExpression.Direction == "ascending" ? contents.OrderBy(x => x.CreateDate) : contents.OrderByDescending(x => x.CreateDate); case "publishDate": - + return sortExpression.Direction == "ascending" ? contents.OrderBy(x => x.UpdateDate) : contents.OrderByDescending(x => x.UpdateDate); @@ -266,11 +256,11 @@ namespace Umbraco.Web.Editors } } - + private IEnumerable GetChildContentTypeAliases(IPublishedContent targetNode, IPublishedContent current) { var aliases = new List(); - + if (targetNode.Id == current.Id) return aliases; if (targetNode.Id != current.Id) { @@ -289,11 +279,10 @@ namespace Umbraco.Web.Editors /// public IEnumerable GetContentTypes() { - var contentTypes = - ApplicationContext.Services.ContentTypeService.GetAll() - .Select(x => new ContentTypeModel() { Alias = x.Alias, Name = x.Name }) - .OrderBy(x => x.Name).ToList(); - contentTypes.Insert(0, new ContentTypeModel() { Alias = string.Empty, Name = "Everything" }); + var contentTypes = Services.ContentTypeService.GetAll() + .Select(x => new ContentTypeModel { Alias = x.Alias, Name = x.Name }) + .OrderBy(x => x.Name).ToList(); + contentTypes.Insert(0, new ContentTypeModel { Alias = string.Empty, Name = "Everything" }); return contentTypes; } diff --git a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs index 16001057be..25d5905954 100644 --- a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs +++ b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs @@ -1,5 +1,4 @@ -using System.Web.Http.Controllers; -using Umbraco.Web.WebApi; +using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Editors @@ -8,20 +7,11 @@ namespace Umbraco.Web.Editors /// An abstract API controller that only supports JSON and all requests must contain the correct csrf header /// /// - /// Inheriting from this controller means that ALL of your methods are JSON methods that are called by Angular, + /// Inheriting from this controller means that ALL of your methods are JSON methods that are called by Angular, /// methods that are not called by Angular or don't contain a valid csrf header will NOT work. /// [ValidateAngularAntiForgeryToken] - [AngularJsonOnlyConfiguration] + [AngularJsonOnlyConfiguration] public abstract class UmbracoAuthorizedJsonController : UmbracoAuthorizedApiController - { - protected UmbracoAuthorizedJsonController() - { - } - - protected UmbracoAuthorizedJsonController(UmbracoContext umbracoContext) : base(umbracoContext) - { - } - - } + { } } \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/UpdateCheckController.cs b/src/Umbraco.Web/Editors/UpdateCheckController.cs index 8f159d308d..2d8965865a 100644 --- a/src/Umbraco.Web/Editors/UpdateCheckController.cs +++ b/src/Umbraco.Web/Editors/UpdateCheckController.cs @@ -1,10 +1,7 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; -using System.Text; -using System.Threading.Tasks; using System.Web.Http.Filters; using Umbraco.Core.Configuration; using Umbraco.Web.Models; @@ -19,7 +16,7 @@ namespace Umbraco.Web.Editors public UpgradeCheckResponse GetCheck() { var updChkCookie = Request.Headers.GetCookies("UMB_UPDCHK").FirstOrDefault(); - var updateCheckCookie = updChkCookie != null ? updChkCookie["UMB_UPDCHK"].Value : ""; + var updateCheckCookie = updChkCookie != null ? updChkCookie["UMB_UPDCHK"].Value : ""; if (GlobalSettings.VersionCheckPeriod > 0 && string.IsNullOrEmpty(updateCheckCookie) && Security.CurrentUser.UserType.Alias == "admin") { try diff --git a/src/Umbraco.Web/Editors/UserController.cs b/src/Umbraco.Web/Editors/UserController.cs index 363940b924..6dd70bfddc 100644 --- a/src/Umbraco.Web/Editors/UserController.cs +++ b/src/Umbraco.Web/Editors/UserController.cs @@ -10,23 +10,6 @@ namespace Umbraco.Web.Editors [UmbracoApplicationAuthorize(Constants.Applications.Users)] public class UserController : UmbracoAuthorizedJsonController { - /// - /// Constructor - /// - public UserController() - : this(UmbracoContext.Current) - { - } - - /// - /// Constructor - /// - /// - public UserController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - /// /// Disables the user with the given user id /// diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs index 001bd4e3e8..05d735d066 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs @@ -11,7 +11,8 @@ namespace Umbraco.Web.HealthCheck.Checks.Config public abstract class AbstractConfigCheck : HealthCheck { private readonly ConfigurationService _configurationService; - private readonly ILocalizedTextService _textService; + + protected ILocalizedTextService TextService { get; } /// /// Gets the config file path. @@ -43,27 +44,21 @@ namespace Umbraco.Web.HealthCheck.Checks.Config /// public abstract ValueComparisonType ValueComparisonType { get; } - protected AbstractConfigCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) + protected AbstractConfigCheck(ILocalizedTextService textService) { - _textService = healthCheckContext.ApplicationContext.Services.TextService; + TextService = textService; _configurationService = new ConfigurationService(AbsoluteFilePath, XPath); } /// /// Gets the name of the file. /// - private string FileName - { - get { return Path.GetFileName(FilePath); } - } + private string FileName => Path.GetFileName(FilePath); /// /// Gets the absolute file path. /// - private string AbsoluteFilePath - { - get { return IOHelper.MapPath(FilePath); } - } + private string AbsoluteFilePath => IOHelper.MapPath(FilePath); /// /// Gets the message for when the check has succeeded. @@ -72,7 +67,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config { get { - return _textService.Localize("healthcheck/checkSuccessMessage", + return TextService.Localize("healthcheck/checkSuccessMessage", new[] { CurrentValue, Values.First(v => v.IsRecommended).Value, XPath, AbsoluteFilePath }); } } @@ -85,9 +80,9 @@ namespace Umbraco.Web.HealthCheck.Checks.Config get { return ValueComparisonType == ValueComparisonType.ShouldEqual - ? _textService.Localize("healthcheck/checkErrorMessageDifferentExpectedValue", + ? TextService.Localize("healthcheck/checkErrorMessageDifferentExpectedValue", new[] { CurrentValue, Values.First(v => v.IsRecommended).Value, XPath, AbsoluteFilePath }) - : _textService.Localize("healthcheck/checkErrorMessageUnexpectedValue", + : TextService.Localize("healthcheck/checkErrorMessageUnexpectedValue", new[] { CurrentValue, Values.First(v => v.IsRecommended).Value, XPath, AbsoluteFilePath }); } } @@ -103,7 +98,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config var rectifiedValue = recommendedValue != null ? recommendedValue.Value : ProvidedValue; - return _textService.Localize("healthcheck/rectifySuccessMessage", + return TextService.Localize("healthcheck/rectifySuccessMessage", new[] { CurrentValue, @@ -117,18 +112,12 @@ namespace Umbraco.Web.HealthCheck.Checks.Config /// /// Gets a value indicating whether this check can be rectified automatically. /// - public virtual bool CanRectify - { - get { return ValueComparisonType == ValueComparisonType.ShouldEqual; } - } + public virtual bool CanRectify => ValueComparisonType == ValueComparisonType.ShouldEqual; /// /// Gets a value indicating whether this check can be rectified automatically if a value is provided. /// - public virtual bool CanRectifyWithValue - { - get { return ValueComparisonType == ValueComparisonType.ShouldNotEqual; } - } + public virtual bool CanRectifyWithValue => ValueComparisonType == ValueComparisonType.ShouldNotEqual; public override IEnumerable GetStatus() { @@ -151,7 +140,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config // Declare the action for rectifying the config value var rectifyAction = new HealthCheckAction("rectify", Id) { - Name = _textService.Localize("healthcheck/rectifyButton"), + Name = TextService.Localize("healthcheck/rectifyButton"), ValueRequired = CanRectifyWithValue, }; @@ -173,7 +162,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config public virtual HealthCheckStatus Rectify() { if (ValueComparisonType == ValueComparisonType.ShouldNotEqual) - throw new InvalidOperationException(_textService.Localize("healthcheck/cannotRectifyShouldNotEqual")); + throw new InvalidOperationException(TextService.Localize("healthcheck/cannotRectifyShouldNotEqual")); var recommendedValue = Values.First(v => v.IsRecommended).Value; return UpdateConfigurationValue(recommendedValue); @@ -187,10 +176,10 @@ namespace Umbraco.Web.HealthCheck.Checks.Config public virtual HealthCheckStatus Rectify(string value) { if (ValueComparisonType == ValueComparisonType.ShouldEqual) - throw new InvalidOperationException(_textService.Localize("healthcheck/cannotRectifyShouldEqualWithValue")); + throw new InvalidOperationException(TextService.Localize("healthcheck/cannotRectifyShouldEqualWithValue")); if (string.IsNullOrWhiteSpace(value)) - throw new InvalidOperationException(_textService.Localize("healthcheck/valueToRectifyNotProvided")); + throw new InvalidOperationException(TextService.Localize("healthcheck/valueToRectifyNotProvided")); // Need to track provided value in order to correctly put together the rectify message ProvidedValue = value; diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/CompilationDebugCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/CompilationDebugCheck.cs index 989046b464..c8ee3534c5 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Config/CompilationDebugCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Config/CompilationDebugCheck.cs @@ -8,52 +8,25 @@ namespace Umbraco.Web.HealthCheck.Checks.Config Group = "Live Environment")] public class CompilationDebugCheck : AbstractConfigCheck { - private readonly ILocalizedTextService _textService; + public CompilationDebugCheck(ILocalizedTextService textService) + : base(textService) + { } - public CompilationDebugCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) - { - _textService = healthCheckContext.ApplicationContext.Services.TextService; - } + public override string FilePath => "~/Web.config"; - public override string FilePath - { - get { return "~/Web.config"; } - } + public override string XPath => "/configuration/system.web/compilation/@debug"; - public override string XPath - { - get { return "/configuration/system.web/compilation/@debug"; } - } + public override ValueComparisonType ValueComparisonType => ValueComparisonType.ShouldEqual; - public override ValueComparisonType ValueComparisonType + public override IEnumerable Values => new List { - get { return ValueComparisonType.ShouldEqual; } - } + new AcceptableConfiguration { IsRecommended = true, Value = bool.FalseString.ToLower() } + }; - public override IEnumerable Values - { - get - { - return new List - { - new AcceptableConfiguration { IsRecommended = true, Value = bool.FalseString.ToLower() } - }; - } - } - - public override string CheckSuccessMessage - { - get { return _textService.Localize("healthcheck/compilationDebugCheckSuccessMessage"); } - } + public override string CheckSuccessMessage => TextService.Localize("healthcheck/compilationDebugCheckSuccessMessage"); - public override string CheckErrorMessage - { - get { return _textService.Localize("healthcheck/compilationDebugCheckErrorMessage"); } - } + public override string CheckErrorMessage => TextService.Localize("healthcheck/compilationDebugCheckErrorMessage"); - public override string RectifySuccessMessage - { - get { return _textService.Localize("healthcheck/compilationDebugCheckRectifySuccessMessage"); } - } + public override string RectifySuccessMessage => TextService.Localize("healthcheck/compilationDebugCheckRectifySuccessMessage"); } } \ No newline at end of file diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/ConfigurationService.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/ConfigurationService.cs index dd92cfa5ec..fc3ae2b2bd 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Config/ConfigurationService.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Config/ConfigurationService.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config { _configFilePath = configFilePath; _xPath = xPath; - _textService = UmbracoContext.Current.Application.Services.TextService; + _textService = Current.Services.TextService; } /// diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/CustomErrorsCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/CustomErrorsCheck.cs index f6e47103e7..1bb91ba075 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Config/CustomErrorsCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Config/CustomErrorsCheck.cs @@ -10,45 +10,27 @@ namespace Umbraco.Web.HealthCheck.Checks.Config Group = "Live Environment")] public class CustomErrorsCheck : AbstractConfigCheck { - private readonly ILocalizedTextService _textService; + public CustomErrorsCheck(ILocalizedTextService textService) + : base(textService) + { } - public CustomErrorsCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) - { - _textService = healthCheckContext.ApplicationContext.Services.TextService; - } + public override string FilePath => "~/Web.config"; - public override string FilePath - { - get { return "~/Web.config"; } - } + public override string XPath => "/configuration/system.web/customErrors/@mode"; - public override string XPath - { - get { return "/configuration/system.web/customErrors/@mode"; } - } + public override ValueComparisonType ValueComparisonType => ValueComparisonType.ShouldEqual; - public override ValueComparisonType ValueComparisonType + public override IEnumerable Values => new List { - get { return ValueComparisonType.ShouldEqual; } - } - - public override IEnumerable Values - { - get - { - return new List - { - new AcceptableConfiguration { IsRecommended = true, Value = CustomErrorsMode.RemoteOnly.ToString() }, - new AcceptableConfiguration { IsRecommended = false, Value = "On" } - }; - } - } + new AcceptableConfiguration { IsRecommended = true, Value = CustomErrorsMode.RemoteOnly.ToString() }, + new AcceptableConfiguration { IsRecommended = false, Value = "On" } + }; public override string CheckSuccessMessage { get { - return _textService.Localize("healthcheck/customErrorsCheckSuccessMessage", + return TextService.Localize("healthcheck/customErrorsCheckSuccessMessage", new[] { CurrentValue, Values.First(v => v.IsRecommended).Value }); } } @@ -57,7 +39,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config { get { - return _textService.Localize("healthcheck/customErrorsCheckErrorMessage", + return TextService.Localize("healthcheck/customErrorsCheckErrorMessage", new[] { CurrentValue, Values.First(v => v.IsRecommended).Value }); } } @@ -66,7 +48,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config { get { - return _textService.Localize("healthcheck/customErrorsCheckRectifySuccessMessage", + return TextService.Localize("healthcheck/customErrorsCheckRectifySuccessMessage", new[] { Values.First(v => v.IsRecommended).Value }); } } diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/MacroErrorsCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/MacroErrorsCheck.cs index 0fe37e11e9..68a2c5ce42 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Config/MacroErrorsCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Config/MacroErrorsCheck.cs @@ -9,27 +9,15 @@ namespace Umbraco.Web.HealthCheck.Checks.Config Group = "Configuration")] public class MacroErrorsCheck : AbstractConfigCheck { - private readonly ILocalizedTextService _textService; + public MacroErrorsCheck(ILocalizedTextService textService) + : base(textService) + { } - public MacroErrorsCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) - { - _textService = healthCheckContext.ApplicationContext.Services.TextService; - } + public override string FilePath => "~/Config/umbracoSettings.config"; - public override string FilePath - { - get { return "~/Config/umbracoSettings.config"; } - } + public override string XPath => "/settings/content/MacroErrors"; - public override string XPath - { - get { return "/settings/content/MacroErrors"; } - } - - public override ValueComparisonType ValueComparisonType - { - get { return ValueComparisonType.ShouldEqual; } - } + public override ValueComparisonType ValueComparisonType => ValueComparisonType.ShouldEqual; public override IEnumerable Values { @@ -52,12 +40,12 @@ namespace Umbraco.Web.HealthCheck.Checks.Config return values; } } - + public override string CheckSuccessMessage { get { - return _textService.Localize("healthcheck/macroErrorModeCheckSuccessMessage", + return TextService.Localize("healthcheck/macroErrorModeCheckSuccessMessage", new[] { CurrentValue, Values.First(v => v.IsRecommended).Value }); } } @@ -66,7 +54,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config { get { - return _textService.Localize("healthcheck/macroErrorModeCheckErrorMessage", + return TextService.Localize("healthcheck/macroErrorModeCheckErrorMessage", new[] { CurrentValue, Values.First(v => v.IsRecommended).Value }); } } @@ -75,7 +63,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config { get { - return _textService.Localize("healthcheck/macroErrorModeCheckRectifySuccessMessage", + return TextService.Localize("healthcheck/macroErrorModeCheckRectifySuccessMessage", new[] { Values.First(v => v.IsRecommended).Value }); } } diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/NotificationEmailCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/NotificationEmailCheck.cs index bcdb0ebc24..4c5f005f14 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Config/NotificationEmailCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Config/NotificationEmailCheck.cs @@ -8,48 +8,25 @@ namespace Umbraco.Web.HealthCheck.Checks.Config Group = "Configuration")] public class NotificationEmailCheck : AbstractConfigCheck { - private readonly ILocalizedTextService _textService; private const string DefaultFromEmail = "your@email.here"; - public NotificationEmailCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) - { - _textService = healthCheckContext.ApplicationContext.Services.TextService; - } + public NotificationEmailCheck(ILocalizedTextService textService) + : base(textService) + { } - public override string FilePath - { - get { return "~/Config/umbracoSettings.config"; } - } + public override string FilePath => "~/Config/umbracoSettings.config"; - public override string XPath - { - get { return "/settings/content/notifications/email"; } - } + public override string XPath => "/settings/content/notifications/email"; - public override ValueComparisonType ValueComparisonType - { - get { return ValueComparisonType.ShouldNotEqual; } - } + public override ValueComparisonType ValueComparisonType => ValueComparisonType.ShouldNotEqual; - public override IEnumerable Values + public override IEnumerable Values => new List { - get - { - return new List - { - new AcceptableConfiguration { IsRecommended = false, Value = DefaultFromEmail } - }; - } - } + new AcceptableConfiguration { IsRecommended = false, Value = DefaultFromEmail } + }; - public override string CheckSuccessMessage - { - get { return _textService.Localize("healthcheck/notificationEmailsCheckSuccessMessage", new [] { CurrentValue } ); } - } + public override string CheckSuccessMessage => TextService.Localize("healthcheck/notificationEmailsCheckSuccessMessage", new [] { CurrentValue } ); - public override string CheckErrorMessage - { - get { return _textService.Localize("healthcheck/notificationEmailsCheckErrorMessage", new[] { DefaultFromEmail }); } - } + public override string CheckErrorMessage => TextService.Localize("healthcheck/notificationEmailsCheckErrorMessage", new[] { DefaultFromEmail }); } } \ No newline at end of file diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/TraceCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/TraceCheck.cs index d0e38815da..6a1256af5e 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Config/TraceCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Config/TraceCheck.cs @@ -8,52 +8,26 @@ namespace Umbraco.Web.HealthCheck.Checks.Config Group = "Live Environment")] public class TraceCheck : AbstractConfigCheck { - private readonly ILocalizedTextService _textService; - public TraceCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) - { - _textService = healthCheckContext.ApplicationContext.Services.TextService; - } + public TraceCheck(ILocalizedTextService textService) + : base(textService) + { } - public override string FilePath - { - get { return "~/Web.config"; } - } + public override string FilePath => "~/Web.config"; - public override string XPath - { - get { return "/configuration/system.web/trace/@enabled"; } - } + public override string XPath => "/configuration/system.web/trace/@enabled"; - public override ValueComparisonType ValueComparisonType - { - get { return ValueComparisonType.ShouldEqual; } - } + public override ValueComparisonType ValueComparisonType => ValueComparisonType.ShouldEqual; - public override IEnumerable Values + public override IEnumerable Values => new List { - get - { - return new List - { - new AcceptableConfiguration { IsRecommended = true, Value = bool.FalseString.ToLower() } - }; - } - } + new AcceptableConfiguration { IsRecommended = true, Value = bool.FalseString.ToLower() } + }; - public override string CheckSuccessMessage - { - get { return _textService.Localize("healthcheck/traceModeCheckSuccessMessage"); } - } + public override string CheckSuccessMessage => TextService.Localize("healthcheck/traceModeCheckSuccessMessage"); - public override string CheckErrorMessage - { - get { return _textService.Localize("healthcheck/traceModeCheckErrorMessage"); } - } + public override string CheckErrorMessage => TextService.Localize("healthcheck/traceModeCheckErrorMessage"); - public override string RectifySuccessMessage - { - get { return _textService.Localize("healthcheck/traceModeCheckRectifySuccessMessage"); } - } + public override string RectifySuccessMessage => TextService.Localize("healthcheck/traceModeCheckRectifySuccessMessage"); } } \ No newline at end of file diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/TrySkipIisCustomErrorsCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/TrySkipIisCustomErrorsCheck.cs index 654d7dd209..30eaa2666e 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Config/TrySkipIisCustomErrorsCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Config/TrySkipIisCustomErrorsCheck.cs @@ -12,27 +12,16 @@ namespace Umbraco.Web.HealthCheck.Checks.Config public class TrySkipIisCustomErrorsCheck : AbstractConfigCheck { private readonly Version _serverVersion = HttpRuntime.IISVersion; - private readonly ILocalizedTextService _textService; - public TrySkipIisCustomErrorsCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) - { - _textService = healthCheckContext.ApplicationContext.Services.TextService; - } + public TrySkipIisCustomErrorsCheck(ILocalizedTextService textService) + : base(textService) + { } - public override string FilePath - { - get { return "~/Config/umbracoSettings.config"; } - } + public override string FilePath => "~/Config/umbracoSettings.config"; - public override string XPath - { - get { return "/settings/web.routing/@trySkipIisCustomErrors"; } - } + public override string XPath => "/settings/web.routing/@trySkipIisCustomErrors"; - public override ValueComparisonType ValueComparisonType - { - get { return ValueComparisonType.ShouldEqual; } - } + public override ValueComparisonType ValueComparisonType => ValueComparisonType.ShouldEqual; public override IEnumerable Values { @@ -49,7 +38,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config { get { - return _textService.Localize("healthcheck/trySkipIisCustomErrorsCheckSuccessMessage", + return TextService.Localize("healthcheck/trySkipIisCustomErrorsCheckSuccessMessage", new[] { CurrentValue, Values.First(v => v.IsRecommended).Value, _serverVersion.ToString() }); } } @@ -58,7 +47,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config { get { - return _textService.Localize("healthcheck/trySkipIisCustomErrorsCheckErrorMessage", + return TextService.Localize("healthcheck/trySkipIisCustomErrorsCheckErrorMessage", new[] { CurrentValue, Values.First(v => v.IsRecommended).Value, _serverVersion.ToString() }); } } @@ -67,7 +56,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config { get { - return _textService.Localize("healthcheck/trySkipIisCustomErrorsCheckRectifySuccessMessage", + return TextService.Localize("healthcheck/trySkipIisCustomErrorsCheckRectifySuccessMessage", new[] { Values.First(v => v.IsRecommended).Value, _serverVersion.ToString() }); } } diff --git a/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/XmlDataIntegrityHealthCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/XmlDataIntegrityHealthCheck.cs index 4ece3a6557..0264f2b3fc 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/XmlDataIntegrityHealthCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/XmlDataIntegrityHealthCheck.cs @@ -22,10 +22,9 @@ namespace Umbraco.Web.HealthCheck.Checks.DataIntegrity private const string CheckMediaXmlTableAction = "checkMediaXmlTable"; private const string CheckMembersXmlTableAction = "checkMembersXmlTable"; - public XmlDataIntegrityHealthCheck(HealthCheckContext healthCheckContext, IFacadeService facadeService) - : base(healthCheckContext) + public XmlDataIntegrityHealthCheck(ILocalizedTextService textService, IFacadeService facadeService) { - _textService = healthCheckContext.ApplicationContext.Services.TextService; + _textService = textService; _facadeService = facadeService as PublishedCache.XmlPublishedCache.FacadeService; if (_facadeService == null) diff --git a/src/Umbraco.Web/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs index e87e5551a0..cd45d9cd8a 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs @@ -28,9 +28,9 @@ namespace Umbraco.Web.HealthCheck.Checks.Permissions { private readonly ILocalizedTextService _textService; - public FolderAndFilePermissionsCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) + public FolderAndFilePermissionsCheck(ILocalizedTextService textService) { - _textService = healthCheckContext.ApplicationContext.Services.TextService; + _textService = textService; } /// diff --git a/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs index 2a57b4be0a..3f1633c764 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs @@ -6,6 +6,7 @@ using System.Net; using System.Text.RegularExpressions; using System.Xml.Linq; using System.Xml.XPath; +using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Services; @@ -19,15 +20,17 @@ namespace Umbraco.Web.HealthCheck.Checks.Security public class ClickJackingCheck : HealthCheck { private readonly ILocalizedTextService _textService; + private readonly IRuntimeState _runtime; private const string SetFrameOptionsHeaderInConfigActiobn = "setFrameOptionsHeaderInConfig"; private const string XFrameOptionsHeader = "X-Frame-Options"; private const string XFrameOptionsValue = "sameorigin"; // Note can't use "deny" as that would prevent Umbraco itself using IFRAMEs - public ClickJackingCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) + public ClickJackingCheck(ILocalizedTextService textService, IRuntimeState runtime) { - _textService = healthCheckContext.ApplicationContext.Services.TextService; + _textService = textService; + _runtime = runtime; } /// @@ -60,7 +63,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security { var message = string.Empty; var success = false; - var url = HealthCheckContext.HttpContext.Request.Url; + var url = _runtime.ApplicationUrl; // Access the site home page and check for the click-jack protection header or meta tag var address = string.Format("http://{0}:{1}", url.Host.ToLower(), url.Port); diff --git a/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs index af1b15818a..6a6a3eaf11 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Web; +using Umbraco.Core; using Umbraco.Core.Services; namespace Umbraco.Web.HealthCheck.Checks.Security @@ -15,10 +16,12 @@ namespace Umbraco.Web.HealthCheck.Checks.Security public class ExcessiveHeadersCheck : HealthCheck { private readonly ILocalizedTextService _textService; + private readonly IRuntimeState _runtime; - public ExcessiveHeadersCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) + public ExcessiveHeadersCheck(ILocalizedTextService textService, IRuntimeState runtime) { - _textService = healthCheckContext.ApplicationContext.Services.TextService; + _textService = textService; + _runtime = runtime; } /// @@ -45,7 +48,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security { var message = string.Empty; var success = false; - var url = HealthCheckContext.HttpContext.Request.Url; + var url = _runtime.ApplicationUrl; // Access the site home page and check for the headers var address = string.Format("http://{0}:{1}", url.Host.ToLower(), url.Port); diff --git a/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs index 80853c01d8..9d19d10c16 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Net; using System.Web; +using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Services; using Umbraco.Web.HealthCheck.Checks.Config; @@ -16,12 +17,14 @@ namespace Umbraco.Web.HealthCheck.Checks.Security public class HttpsCheck : HealthCheck { private readonly ILocalizedTextService _textService; + private readonly IRuntimeState _runtime; private const string FixHttpsSettingAction = "fixHttpsSetting"; - public HttpsCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) + public HttpsCheck(ILocalizedTextService textService, IRuntimeState runtime) { - _textService = healthCheckContext.ApplicationContext.Services.TextService; + _textService = textService; + _runtime = runtime; } /// @@ -54,9 +57,9 @@ namespace Umbraco.Web.HealthCheck.Checks.Security { var message = string.Empty; var success = false; - var url = HealthCheckContext.HttpContext.Request.Url; + var url = _runtime.ApplicationUrl; - // Attempt to access the site over HTTPS to see if it HTTPS is supported + // Attempt to access the site over HTTPS to see if it HTTPS is supported // and a valid certificate has been configured var address = string.Format("https://{0}:{1}", url.Host.ToLower(), url.Port); var request = (HttpWebRequest)WebRequest.Create(address); @@ -133,7 +136,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security new[] {httpsSettingEnabled.ToString(), httpsSettingEnabled ? string.Empty : "not"}); resultType = httpsSettingEnabled ? StatusResultType.Success: StatusResultType.Error; } - + return new HealthCheckStatus(resultMessage) { diff --git a/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs index a1f085865c..4c0652632c 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs @@ -4,6 +4,7 @@ using System.IO; using System.Net.Configuration; using System.Net.Sockets; using System.Web.Configuration; +using Umbraco.Core; using Umbraco.Core.Services; namespace Umbraco.Web.HealthCheck.Checks.Services @@ -16,10 +17,12 @@ namespace Umbraco.Web.HealthCheck.Checks.Services public class SmtpCheck : HealthCheck { private readonly ILocalizedTextService _textService; + private readonly IRuntimeState _runtime; - public SmtpCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) + public SmtpCheck(ILocalizedTextService textService, IRuntimeState runtime) { - _textService = healthCheckContext.ApplicationContext.Services.TextService; + _textService = textService; + _runtime = runtime; } /// @@ -48,7 +51,9 @@ namespace Umbraco.Web.HealthCheck.Checks.Services var message = string.Empty; var success = false; - var config = WebConfigurationManager.OpenWebConfiguration(HealthCheckContext.HttpContext.Request.ApplicationPath); + // appPath is the virtual application root path on the server + var appPath = ""; + var config = WebConfigurationManager.OpenWebConfiguration(_runtime.ApplicationVirtualPath); var settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings"); if (settings == null) { diff --git a/src/Umbraco.Web/HealthCheck/HealthCheck.cs b/src/Umbraco.Web/HealthCheck/HealthCheck.cs index b90cfc5c82..968a255c54 100644 --- a/src/Umbraco.Web/HealthCheck/HealthCheck.cs +++ b/src/Umbraco.Web/HealthCheck/HealthCheck.cs @@ -6,16 +6,13 @@ using Umbraco.Core; namespace Umbraco.Web.HealthCheck { /// - /// The abstract health check class + /// Provides a base class for health checks. /// [DataContract(Name = "healtCheck", Namespace = "")] public abstract class HealthCheck { - protected HealthCheck(HealthCheckContext healthCheckContext) + protected HealthCheck() { - if (healthCheckContext == null) throw new ArgumentNullException(nameof(healthCheckContext)); - HealthCheckContext = healthCheckContext; - //Fill in the metadata var thisType = GetType(); var meta = thisType.GetCustomAttribute(false); @@ -27,9 +24,6 @@ namespace Umbraco.Web.HealthCheck Id = meta.Id; } - [IgnoreDataMember] - public HealthCheckContext HealthCheckContext { get; private set; } - [DataMember(Name = "id")] public Guid Id { get; private set; } diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckAction.cs b/src/Umbraco.Web/HealthCheck/HealthCheckAction.cs index 526ca0ece3..25d2b208ca 100644 --- a/src/Umbraco.Web/HealthCheck/HealthCheckAction.cs +++ b/src/Umbraco.Web/HealthCheck/HealthCheckAction.cs @@ -51,7 +51,7 @@ namespace Umbraco.Web.HealthCheck /// The name of the action - this is used to name the fix button /// [DataMember(Name = "name")] - private string _name = UmbracoContext.Current.Application.Services.TextService.Localize("healthcheck/rectifyButton"); + private string _name = Current.Services.TextService.Localize("healthcheck/rectifyButton"); public string Name { get { return _name; } diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckContext.cs b/src/Umbraco.Web/HealthCheck/HealthCheckContext.cs deleted file mode 100644 index f554b812e8..0000000000 --- a/src/Umbraco.Web/HealthCheck/HealthCheckContext.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Web; -using Umbraco.Core; - -namespace Umbraco.Web.HealthCheck -{ - /// - /// Context exposing all services that could be required for health check classes to perform and/or fix their checks - /// - public class HealthCheckContext - { - public HealthCheckContext(HttpContextBase httpContext, UmbracoContext umbracoContext) - { - if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); - if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); - - HttpContext = httpContext; - UmbracoContext = umbracoContext; - } - - public HttpContextBase HttpContext { get; } - public UmbracoContext UmbracoContext { get; } - public ApplicationContext ApplicationContext => UmbracoContext.Application; - - //TODO: Do we need any more info/service exposed here? - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckController.cs b/src/Umbraco.Web/HealthCheck/HealthCheckController.cs index 886fe7f4a3..9bb9ae512b 100644 --- a/src/Umbraco.Web/HealthCheck/HealthCheckController.cs +++ b/src/Umbraco.Web/HealthCheck/HealthCheckController.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Web; using System.Web.Http; using Umbraco.Web.Editors; @@ -12,16 +11,12 @@ namespace Umbraco.Web.HealthCheck /// public class HealthCheckController : UmbracoAuthorizedJsonController { - private readonly HealthCheckCollectionBuilder _builder; + private readonly HealthCheckCollection _checks; - public HealthCheckController() + public HealthCheckController(HealthCheckCollection checks) { - _builder = Current.HealthCheckCollectionBuilder; - } - - public HealthCheckController(HealthCheckCollectionBuilder builder) - { - _builder = builder; + if (checks == null) throw new ArgumentNullException(nameof(checks)); + _checks = checks; } /// @@ -30,8 +25,7 @@ namespace Umbraco.Web.HealthCheck /// Returns a collection of anonymous objects representing each group. public object GetAllHealthChecks() { - var context = new HealthCheckContext(new HttpContextWrapper(HttpContext.Current), UmbracoContext.Current); - var groups = _builder.CreateCollection(context) + var groups = _checks .GroupBy(x => x.Group) .OrderBy(x => x.Key); var healthCheckGroups = new List(); @@ -52,8 +46,7 @@ namespace Umbraco.Web.HealthCheck public object GetStatus(Guid id) { - var context = new HealthCheckContext(new HttpContextWrapper(HttpContext.Current), UmbracoContext.Current); - var check = _builder.CreateCollection(context).FirstOrDefault(x => x.Id == id); + var check = _checks.FirstOrDefault(x => x.Id == id); if (check == null) throw new InvalidOperationException("No health check found with ID " + id); return check.GetStatus(); @@ -62,8 +55,7 @@ namespace Umbraco.Web.HealthCheck [HttpPost] public HealthCheckStatus ExecuteAction(HealthCheckAction action) { - var context = new HealthCheckContext(new HttpContextWrapper(HttpContext.Current), UmbracoContext.Current); - var check = _builder.CreateCollection(context).FirstOrDefault(x => x.Id == action.HealthCheckId); + var check = _checks.FirstOrDefault(x => x.Id == action.HealthCheckId); if (check == null) throw new InvalidOperationException("No health check found with id " + action.HealthCheckId); return check.ExecuteAction(action); diff --git a/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs b/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs index 891231e4d0..cf82b0ee6d 100644 --- a/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs +++ b/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs @@ -7,30 +7,10 @@ namespace Umbraco.Web.HealthCheck { public HealthCheckCollectionBuilder(IServiceContainer container) : base(container) - { - // because collection builders are "per container" this ctor should run only once per container. - // - // note: constructor dependencies do NOT work with lifetimes other than transient - // see https://github.com/seesharper/LightInject/issues/294 - // - // resolve ctor dependency from GetInstance() runtimeArguments, if possible - 'factory' is - // the container, 'info' describes the ctor argument, and 'args' contains the args that - // were passed to GetInstance() - use first arg if it is the right type. - // - // for HealthCheckContext - container.RegisterConstructorDependency((factory, info, args) => args.Length > 0 ? args[0] as HealthCheckContext : null); - } + { } protected override HealthCheckCollectionBuilder This => this; - protected override void Initialize() - { - // nothing - do not register the collection - } - - public HealthCheckCollection CreateCollection(HealthCheckContext context) - { - return new HealthCheckCollection(CreateItems(context)); - } + protected override ILifetime CollectionLifetime => null; // transient! } } diff --git a/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs b/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs index 71fc3be8f1..ce3ab0ea85 100644 --- a/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs @@ -36,7 +36,7 @@ namespace Umbraco.Web /// public static IHtmlString BareMinimumServerVariablesScript(this HtmlHelper html, UrlHelper uri, string externalLoginsUrl) { - var version = UmbracoVersion.GetSemanticVersion().ToSemanticString(); + var version = UmbracoVersion.SemanticVersion.ToSemanticString(); var str = @"" + @@ -930,11 +930,11 @@ namespace Umbraco.Web if (umbCtx.InPreviewMode) { - canvasdesignerConfigPath = string.IsNullOrEmpty(canvasdesignerConfigPath) == false - ? canvasdesignerConfigPath + canvasdesignerConfigPath = string.IsNullOrEmpty(canvasdesignerConfigPath) == false + ? canvasdesignerConfigPath : string.Format("{0}/js/canvasdesigner.config.js", umbracoPath); - canvasdesignerPalettesPath = string.IsNullOrEmpty(canvasdesignerPalettesPath) == false - ? canvasdesignerPalettesPath + canvasdesignerPalettesPath = string.IsNullOrEmpty(canvasdesignerPalettesPath) == false + ? canvasdesignerPalettesPath : string.Format("{0}/js/canvasdesigner.palettes.js", umbracoPath); if (string.IsNullOrEmpty(cssPath) == false) diff --git a/src/Umbraco.Web/HtmlStringUtilities.cs b/src/Umbraco.Web/HtmlStringUtilities.cs index 4189226937..421a4c025b 100644 --- a/src/Umbraco.Web/HtmlStringUtilities.cs +++ b/src/Umbraco.Web/HtmlStringUtilities.cs @@ -9,11 +9,8 @@ using HtmlAgilityPack; namespace Umbraco.Web { /// - /// Utility class for working with strings and HTML in views + /// Provides utility methods for UmbracoHelper for working with strings and html in views. /// - /// - /// The UmbracoHelper uses this class for it's string methods - /// public sealed class HtmlStringUtilities { /// diff --git a/src/Umbraco.Web/HybridAccessorBase.cs b/src/Umbraco.Web/HybridAccessorBase.cs index 10c1a22464..5bb5f8babb 100644 --- a/src/Umbraco.Web/HybridAccessorBase.cs +++ b/src/Umbraco.Web/HybridAccessorBase.cs @@ -2,6 +2,7 @@ using System; namespace Umbraco.Web { + // fixme - must ensure that the ThreadStatic value is properly cleared! internal abstract class HybridAccessorBase { private readonly IHttpContextAccessor _httpContextAccessor; @@ -21,14 +22,14 @@ namespace Umbraco.Web get { var httpContext = _httpContextAccessor.HttpContext; - if (httpContext == null) return _value; //throw new Exception("oops:httpContext"); + if (httpContext == null) return _value; return (T) httpContext.Items[HttpContextItemKey]; } set { var httpContext = _httpContextAccessor.HttpContext; - if (httpContext == null) //throw new Exception("oops:httpContext"); + if (httpContext == null) { _value = value; return; diff --git a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs index 1f0c371d43..1d5a277f50 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallApiController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallApiController.cs @@ -3,12 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Web.Http; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core; -using Umbraco.Core.Configuration; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Umbraco.Web.Install.Models; using Umbraco.Web.WebApi; @@ -18,48 +15,40 @@ namespace Umbraco.Web.Install.Controllers [HttpInstallAuthorize] public class InstallApiController : ApiController { - public InstallApiController() - : this(UmbracoContext.Current) - { + private readonly DatabaseContext _databaseContext; + private readonly ProfilingLogger _proflog; + private readonly ILogger _logger; + private InstallHelper _helper; - } - - public InstallApiController(UmbracoContext umbracoContext) + public InstallApiController(UmbracoContext umbracoContext, DatabaseContext databaseContext, ILogger logger, ProfilingLogger proflog) { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); + if (databaseContext == null) throw new ArgumentNullException(nameof(databaseContext)); + if (proflog == null) throw new ArgumentNullException(nameof(proflog)); + if (logger == null) throw new ArgumentNullException(nameof(logger)); UmbracoContext = umbracoContext; + _databaseContext = databaseContext; + _logger = logger; + _proflog = proflog; } /// - /// Returns the current UmbracoContext + /// Gets the Umbraco context. /// - public UmbracoContext UmbracoContext { get; private set; } + public UmbracoContext UmbracoContext { get; } - public ApplicationContext ApplicationContext - { - get { return UmbracoContext.Application; } - } - - private InstallHelper _helper; - internal InstallHelper InstallHelper - { - get - { - return _helper ?? (_helper = new InstallHelper(UmbracoContext)); - } - } + internal InstallHelper InstallHelper => _helper ?? (_helper = new InstallHelper(UmbracoContext, _databaseContext, _logger)); public bool PostValidateDatabaseConnection(DatabaseModel model) { var dbHelper = new DatabaseHelper(); - var canConnect = dbHelper.CheckConnection(ApplicationContext.DatabaseContext, model); + var canConnect = dbHelper.CheckConnection(model); return canConnect; } /// - /// Gets the install setup + /// Gets the install setup. /// - /// public InstallSetup GetSetup() { var setup = new InstallSetup(); @@ -78,21 +67,20 @@ namespace Umbraco.Web.Install.Controllers return setup; } - + public IEnumerable GetPackages() { - var installHelper = new InstallHelper(UmbracoContext); + var installHelper = new InstallHelper(UmbracoContext, _databaseContext, _logger); var starterKits = installHelper.GetStarterKits(); return starterKits; } /// - /// Does the install + /// Installs. /// - /// public InstallProgressResultModel PostPerformInstall(InstallInstructions installModel) { - if (installModel == null) throw new ArgumentNullException("installModel"); + if (installModel == null) throw new ArgumentNullException(nameof(installModel)); var status = InstallStatusTracker.GetStatus().ToArray(); //there won't be any statuses returned if the app pool has restarted so we need to re-read from file. @@ -105,22 +93,18 @@ namespace Umbraco.Web.Install.Controllers var queue = new Queue(status.Where(x => x.IsComplete == false)); while (queue.Count > 0) { - var stepStatus = queue.Dequeue(); - - var step = InstallHelper.GetAllSteps().Single(x => x.Name == stepStatus.Name); + var item = queue.Dequeue(); + var step = InstallHelper.GetAllSteps().Single(x => x.Name == item.Name); - JToken instruction = null; - //If this step has any instructions then extract them - if (installModel.Instructions.Any(x => x.Key == step.Name)) - { - instruction = installModel.Instructions[step.Name]; - } - - //If this step doesn't require execution then continue to the next one, this is just a fail-safe check. + // if this step has any instructions then extract them + JToken instruction; + installModel.Instructions.TryGetValue(item.Name, out instruction); // else null + + // if this step doesn't require execution then continue to the next one, this is just a fail-safe check. if (StepRequiresExecution(step, instruction) == false) { - //set this as complete and continue - InstallStatusTracker.SetComplete(installModel.InstallId, stepStatus.Name, null); + // set this as complete and continue + InstallStatusTracker.SetComplete(installModel.InstallId, item.Name); continue; } @@ -128,13 +112,13 @@ namespace Umbraco.Web.Install.Controllers { var setupData = ExecuteStep(step, instruction); - //update the status - InstallStatusTracker.SetComplete(installModel.InstallId, step.Name, setupData != null ? setupData.SavedStepData : null); + // update the status + InstallStatusTracker.SetComplete(installModel.InstallId, step.Name, setupData?.SavedStepData); - //Determine's the next step in the queue and dequeue's any items that don't need to execute - var nextStep = IterateNextRequiredStep(step, queue, installModel.InstallId, installModel); - - //check if there's a custom view to return for this step + // determine's the next step in the queue and dequeue's any items that don't need to execute + var nextStep = IterateSteps(step, queue, installModel.InstallId, installModel); + + // check if there's a custom view to return for this step if (setupData != null && setupData.View.IsNullOrWhiteSpace() == false) { return new InstallProgressResultModel(false, step.Name, nextStep, setupData.View, setupData.ViewModel); @@ -185,65 +169,53 @@ namespace Umbraco.Web.Install.Controllers /// /// /// - private string IterateNextRequiredStep(InstallSetupStep current, Queue queue, Guid installId, InstallInstructions installModel) + private string IterateSteps(InstallSetupStep current, Queue queue, Guid installId, InstallInstructions installModel) { - if (queue.Count > 0) + while (queue.Count > 0) { - var next = queue.Peek(); - var step = InstallHelper.GetAllSteps().Single(x => x.Name == next.Name); + var item = queue.Peek(); - //If the current step restarts the app pool then we must simply return the next one in the queue, - // we cannot peek ahead as the next step might rely on the app restart and therefore RequiresExecution - // will rely on that too. + // if the current step restarts the app pool then we must simply return the next one in the queue, + // we cannot peek ahead as the next step might rely on the app restart and therefore RequiresExecution + // will rely on that too. if (current.PerformsAppRestart) - { - return step.Name; - } + return item.Name; - JToken instruction = null; - //If this step has any instructions then extract them - if (installModel.Instructions.Any(x => x.Key == step.Name)) - { - instruction = installModel.Instructions[step.Name]; - } + var step = InstallHelper.GetAllSteps().Single(x => x.Name == item.Name); - //if the step requires execution then return it's name + // if this step has any instructions then extract them + JToken instruction; + installModel.Instructions.TryGetValue(item.Name, out instruction); // else null + + // if the step requires execution then return its name if (StepRequiresExecution(step, instruction)) - { return step.Name; - } - //this step no longer requires execution, this could be due to a new config change during installation, - // so we'll dequeue this one from the queue and recurse + // no longer requires execution, could be due to a new config change during installation + // dequeue queue.Dequeue(); - //set this as complete - InstallStatusTracker.SetComplete(installId, step.Name, null); + // complete + InstallStatusTracker.SetComplete(installId, step.Name); - //recurse - return IterateNextRequiredStep(step, queue, installId, installModel); + // and continue + current = step; } - //there is no more steps return string.Empty; } - /// - /// Check if the step requires execution - /// - /// - /// - /// + // determines whether the step requires execution internal bool StepRequiresExecution(InstallSetupStep step, JToken instruction) { - var model = instruction == null ? null : instruction.ToObject(step.StepType); + var model = instruction?.ToObject(step.StepType); var genericStepType = typeof(InstallSetupStep<>); Type[] typeArgs = { step.StepType }; var typedStepType = genericStepType.MakeGenericType(typeArgs); try { var method = typedStepType.GetMethods().Single(x => x.Name == "RequiresExecution"); - return (bool)method.Invoke(step, new object[] { model }); + return (bool) method.Invoke(step, new[] { model }); } catch (Exception ex) { @@ -252,18 +224,19 @@ namespace Umbraco.Web.Install.Controllers } } + // executes the step internal InstallSetupResult ExecuteStep(InstallSetupStep step, JToken instruction) { - using (ApplicationContext.ProfilingLogger.TraceDuration("Executing installation step: " + step.Name, "Step completed")) + using (_proflog.TraceDuration("Executing installation step: " + step.Name, "Step completed")) { - var model = instruction == null ? null : instruction.ToObject(step.StepType); + var model = instruction?.ToObject(step.StepType); var genericStepType = typeof(InstallSetupStep<>); Type[] typeArgs = { step.StepType }; var typedStepType = genericStepType.MakeGenericType(typeArgs); try { var method = typedStepType.GetMethods().Single(x => x.Name == "Execute"); - return (InstallSetupResult)method.Invoke(step, new object[] { model }); + return (InstallSetupResult) method.Invoke(step, new[] { model }); } catch (Exception ex) { diff --git a/src/Umbraco.Web/Install/Controllers/InstallController.cs b/src/Umbraco.Web/Install/Controllers/InstallController.cs index 572bd0a192..03a18a6977 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallController.cs @@ -1,12 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Web.Mvc; +using System.Web.Mvc; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Web.Security; namespace Umbraco.Web.Install.Controllers @@ -17,32 +13,30 @@ namespace Umbraco.Web.Install.Controllers /// /// NOTE: All views must have their full paths as we do not have a custom view engine for the installation views! /// - [InstallAuthorizeAttribute] + [InstallAuthorize] public class InstallController : Controller { + private readonly DatabaseContext _databaseContext; private readonly UmbracoContext _umbracoContext; + private readonly IRuntimeState _runtime; + private readonly ILogger _logger; - public InstallController() - : this(UmbracoContext.Current) - { - - } - - public InstallController(UmbracoContext umbracoContext) + public InstallController(UmbracoContext umbracoContext, DatabaseContext databaseContext, IRuntimeState runtime, ILogger logger) { _umbracoContext = umbracoContext; + _databaseContext = databaseContext; + _runtime = runtime; + _logger = logger; } [HttpGet] public ActionResult Index() { - if (ApplicationContext.Current.IsConfigured) - { - return Redirect(SystemDirectories.Umbraco.EnsureEndsWith('/')); - } + if (_runtime.Level == RuntimeLevel.Run) + return Redirect(SystemDirectories.Umbraco.EnsureEndsWith('/')); - if (ApplicationContext.Current.IsUpgrading) + if (_runtime.Level == RuntimeLevel.Upgrade) { var result = _umbracoContext.Security.ValidateCurrentUser(false); @@ -53,20 +47,18 @@ namespace Umbraco.Web.Install.Controllers return Redirect(SystemDirectories.Umbraco + "/AuthorizeUpgrade?redir=" + Server.UrlEncode(Request.RawUrl)); } } - - //gen the install base url + // gen the install base url ViewBag.InstallApiBaseUrl = Url.GetUmbracoApiService("GetSetup", "InstallApi", "UmbracoInstall").TrimEnd("GetSetup"); - - //get the base umbraco folder + + // get the base umbraco folder ViewBag.UmbracoBaseFolder = IOHelper.ResolveUrl(SystemDirectories.Umbraco); - InstallHelper ih = new InstallHelper(_umbracoContext); + var ih = new InstallHelper(_umbracoContext, _databaseContext, _logger); ih.InstallStatus(false, ""); - //always ensure full path (see NOTE in the class remarks) + // always ensure full path (see NOTE in the class remarks) return View(GlobalSettings.Path.EnsureEndsWith('/') + "install/views/index.cshtml"); } - } } diff --git a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs index e117740b55..4da86749f5 100644 --- a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs +++ b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs @@ -26,18 +26,8 @@ namespace Umbraco.Web.Install.Controllers [Obsolete("This is only used for the legacy way of installing starter kits in the back office")] public class InstallPackageController : ApiController { - private readonly ApplicationContext _applicationContext; - public InstallPackageController() - : this(ApplicationContext.Current) - { - - } - - public InstallPackageController(ApplicationContext applicationContext) - { - _applicationContext = applicationContext; - } + { } private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; @@ -115,7 +105,7 @@ namespace Umbraco.Web.Install.Controllers [HttpPost] public HttpResponseMessage RestartAppPool() { - _applicationContext.RestartApplicationPool(Request.TryGetHttpContext().Result); + Current.RestartAppPool(Request.TryGetHttpContext().Result); return Json(new { success = true, @@ -137,7 +127,7 @@ namespace Umbraco.Web.Install.Controllers } return Json(new - { + { percentage = 30, success = true, }, HttpStatusCode.OK); diff --git a/src/Umbraco.Web/Install/DatabaseHelper.cs b/src/Umbraco.Web/Install/DatabaseHelper.cs index 84535675a3..8e8805dbbb 100644 --- a/src/Umbraco.Web/Install/DatabaseHelper.cs +++ b/src/Umbraco.Web/Install/DatabaseHelper.cs @@ -4,9 +4,13 @@ using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install { + // that class was originally created by Per - tests the db connection for install + // fixed by Shannon to not-ignore the provider + // fixed by Stephan as part of the v8 persistence cleanup, now using provider names + SqlCe exception + internal class DatabaseHelper { - internal bool CheckConnection(DatabaseContext context, DatabaseModel model) + internal bool CheckConnection(DatabaseModel model) { // we do not test SqlCE connection if (model.DatabaseType == DatabaseType.SqlCe) @@ -24,11 +28,11 @@ namespace Umbraco.Web.Install { // has to be Sql Server providerName = Constants.DbProviderNames.SqlServer; - connectionString = context.GetIntegratedSecurityDatabaseConnectionString(model.Server, model.DatabaseName); + connectionString = DatabaseContext.GetIntegratedSecurityDatabaseConnectionString(model.Server, model.DatabaseName); } else { - connectionString = context.GetDatabaseConnectionString( + connectionString = DatabaseContext.GetDatabaseConnectionString( model.Server, model.DatabaseName, model.Login, model.Password, model.DatabaseType.ToString(), out providerName); } diff --git a/src/Umbraco.Web/Install/HttpInstallAuthorizeAttribute.cs b/src/Umbraco.Web/Install/HttpInstallAuthorizeAttribute.cs index bed38b8829..5cb0d5cc9b 100644 --- a/src/Umbraco.Web/Install/HttpInstallAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Install/HttpInstallAuthorizeAttribute.cs @@ -7,64 +7,58 @@ using Umbraco.Core.Logging; namespace Umbraco.Web.Install { /// - /// Ensures authorization occurs for the installer if it has already completed. If install has not yet occured - /// then the authorization is successful + /// Ensures authorization occurs for the installer if it has already completed. + /// If install has not yet occured then the authorization is successful. /// internal class HttpInstallAuthorizeAttribute : AuthorizeAttribute { - private readonly ApplicationContext _applicationContext; + // todo - cannot inject UmbracoContext nor RuntimeState in the attribute, read: + // http://stackoverflow.com/questions/30096903/dependency-injection-inside-a-filterattribute-in-asp-net-mvc-6 + // https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=98 - don't do it! + // http://blog.ploeh.dk/2014/06/13/passive-attributes/ - passive attributes + // http://xunitpatterns.com/Humble%20Object.html - humble objects + // + // so... either access them via Current service locator, OR use an action filter alongside this attribute (see articles). + // the second solution is nicer BUT for the time being, let's use the first (simpler). + private readonly UmbracoContext _umbracoContext; + private readonly IRuntimeState _runtimeState; - private ApplicationContext GetApplicationContext() - { - return _applicationContext ?? ApplicationContext.Current; - } + private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private UmbracoContext GetUmbracoContext() - { - return _umbracoContext ?? UmbracoContext.Current; - } + private UmbracoContext UmbracoContext => _umbracoContext ?? Current.UmbracoContext; - /// - /// THIS SHOULD BE ONLY USED FOR UNIT TESTS - /// - /// - public HttpInstallAuthorizeAttribute(UmbracoContext umbracoContext) + /// + /// THIS SHOULD BE ONLY USED FOR UNIT TESTS + /// + /// + /// + public HttpInstallAuthorizeAttribute(UmbracoContext umbracoContext, IRuntimeState runtimeState) { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); + if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); _umbracoContext = umbracoContext; - _applicationContext = _umbracoContext.Application; + _runtimeState = runtimeState; } public HttpInstallAuthorizeAttribute() - { - } + { } protected override bool IsAuthorized(HttpActionContext actionContext) { try { - //if its not configured then we can continue - if (GetApplicationContext().IsConfigured == false) - { - return true; - } - var umbCtx = GetUmbracoContext(); - - //otherwise we need to ensure that a user is logged in - var isLoggedIn = GetUmbracoContext().Security.ValidateCurrentUser(); - if (isLoggedIn) - { - return true; - } - return false; + // if not configured (install or upgrade) then we can continue + // otherwise we need to ensure that a user is logged in + return RuntimeState.Level == RuntimeLevel.Install + || RuntimeState.Level == RuntimeLevel.Upgrade + || UmbracoContext.Security.ValidateCurrentUser(); } catch (Exception ex) { - LogHelper.Error("An error occurred determining authorization", ex); + Current.Logger.Error("An error occurred determining authorization", ex); return false; } } - } } \ No newline at end of file diff --git a/src/Umbraco.Web/Install/InstallAuthorizeAttribute.cs b/src/Umbraco.Web/Install/InstallAuthorizeAttribute.cs index 762a26d811..787b69a654 100644 --- a/src/Umbraco.Web/Install/InstallAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Install/InstallAuthorizeAttribute.cs @@ -7,38 +7,34 @@ using Umbraco.Core.IO; namespace Umbraco.Web.Install { /// - /// Ensures authorization occurs for the installer if it has already completed. If install has not yet occured - /// then the authorization is successful + /// Ensures authorization occurs for the installer if it has already completed. + /// If install has not yet occured then the authorization is successful /// internal class InstallAuthorizeAttribute : AuthorizeAttribute { - private readonly ApplicationContext _applicationContext; + // see note in HttpInstallAuthorizeAttribute private readonly UmbracoContext _umbracoContext; + private readonly IRuntimeState _runtimeState; - private ApplicationContext GetApplicationContext() - { - return _applicationContext ?? ApplicationContext.Current; - } + private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private UmbracoContext GetUmbracoContext() - { - return _umbracoContext ?? UmbracoContext.Current; - } + private UmbracoContext UmbracoContext => _umbracoContext ?? Current.UmbracoContext; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS /// /// - public InstallAuthorizeAttribute(UmbracoContext umbracoContext) + /// + public InstallAuthorizeAttribute(UmbracoContext umbracoContext, IRuntimeState runtimeState) { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); + if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); _umbracoContext = umbracoContext; - _applicationContext = _umbracoContext.Application; + _runtimeState = runtimeState; } public InstallAuthorizeAttribute() - { - } + { } /// /// Ensures that the user must be logged in or that the application is not configured just yet. @@ -47,24 +43,15 @@ namespace Umbraco.Web.Install /// protected override bool AuthorizeCore(HttpContextBase httpContext) { - if (httpContext == null) throw new ArgumentNullException("httpContext"); + if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); try { - //if its not configured then we can continue - if (!GetApplicationContext().IsConfigured) - { - return true; - } - var umbCtx = GetUmbracoContext(); - //otherwise we need to ensure that a user is logged in - var isLoggedIn = GetUmbracoContext().Security.ValidateCurrentUser(); - if (isLoggedIn) - { - return true; - } - - return false; + // if not configured (install or upgrade) then we can continue + // otherwise we need to ensure that a user is logged in + return RuntimeState.Level == RuntimeLevel.Install + || RuntimeState.Level == RuntimeLevel.Upgrade + || UmbracoContext.Security.ValidateCurrentUser(); } catch (Exception) { @@ -78,8 +65,7 @@ namespace Umbraco.Web.Install /// protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { - filterContext.Result = new RedirectResult(SystemDirectories.Umbraco.EnsureEndsWith('/')); + filterContext.Result = new RedirectResult(SystemDirectories.Umbraco.EnsureEndsWith('/')); } - } } \ No newline at end of file diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs index 25ff4cde39..3cfcf5acc4 100644 --- a/src/Umbraco.Web/Install/InstallHelper.cs +++ b/src/Umbraco.Web/Install/InstallHelper.cs @@ -1,38 +1,36 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Net.Http; using System.Web; -using System.Web.Script.Serialization; -using System.Web.UI; -using umbraco.BusinessLogic; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Web.Install.InstallSteps; using Umbraco.Web.Install.Models; -using Umbraco.Web; - namespace Umbraco.Web.Install { internal class InstallHelper { - private readonly UmbracoContext _umbContext; + private readonly UmbracoContext _umbracoContext; + private readonly DatabaseContext _databaseContext; + private readonly HttpContextBase _httpContext; + private readonly ILogger _logger; private InstallationType? _installationType; - internal InstallHelper(UmbracoContext umbContext) + internal InstallHelper(UmbracoContext umbracoContext, DatabaseContext databaseContext, ILogger logger) { - _umbContext = umbContext; + _umbracoContext = umbracoContext; + _httpContext = umbracoContext.HttpContext; + _logger = logger; + _databaseContext = databaseContext; } - /// /// Get the installer steps /// @@ -42,20 +40,21 @@ namespace Umbraco.Web.Install /// public IEnumerable GetAllSteps() { + // fixme - should NOT use current everywhere here - inject! return new List { - new NewInstallStep(_umbContext.HttpContext, _umbContext.Application), + new NewInstallStep(_httpContext, Current.Services.UserService, Current.DatabaseContext), new UpgradeStep(), new FilePermissionsStep(), - new MajorVersion7UpgradeReport(_umbContext.Application), - new Version73FileCleanup(_umbContext.HttpContext, _umbContext.Application.ProfilingLogger.Logger), - new DatabaseConfigureStep(_umbContext.Application), - new DatabaseInstallStep(_umbContext.Application), - new DatabaseUpgradeStep(_umbContext.Application), - new StarterKitDownloadStep(_umbContext.Application), - new StarterKitInstallStep(_umbContext.Application, _umbContext.HttpContext), - new StarterKitCleanupStep(_umbContext.Application), - new SetUmbracoVersionStep(_umbContext.Application, _umbContext.HttpContext), + new MajorVersion7UpgradeReport(Current.DatabaseContext, Current.RuntimeState), + new Version73FileCleanup(_httpContext, _logger), + new DatabaseConfigureStep(Current.DatabaseContext), + new DatabaseInstallStep(Current.DatabaseContext, Current.RuntimeState), + new DatabaseUpgradeStep(Current.DatabaseContext, Current.Services.MigrationEntryService, Current.RuntimeState, Current.MigrationCollectionBuilder), + new StarterKitDownloadStep(Current.Services.ContentService, this), + new StarterKitInstallStep(_httpContext), + new StarterKitCleanupStep(), + new SetUmbracoVersionStep(_httpContext, _logger, this) }; } @@ -102,12 +101,12 @@ namespace Umbraco.Web.Install { try { - string userAgent = _umbContext.HttpContext.Request.UserAgent; + var userAgent = _httpContext.Request.UserAgent; // Check for current install Id var installId = Guid.NewGuid(); - var installCookie = _umbContext.HttpContext.Request.GetPreviewCookieValue(); + var installCookie = _httpContext.Request.GetPreviewCookieValue(); if (string.IsNullOrEmpty(installCookie) == false) { if (Guid.TryParse(installCookie, out installId)) @@ -117,17 +116,17 @@ namespace Umbraco.Web.Install installId = Guid.NewGuid(); } } - _umbContext.HttpContext.Response.Cookies.Set(new HttpCookie("umb_installId", "1")); + _httpContext.Response.Cookies.Set(new HttpCookie("umb_installId", "1")); - string dbProvider = string.Empty; + var dbProvider = string.Empty; if (IsBrandNewInstall == false) { // we don't have DatabaseProvider anymore... doing it differently //dbProvider = ApplicationContext.Current.DatabaseContext.DatabaseProvider.ToString(); - dbProvider = GetDbProviderString(ApplicationContext.Current.DatabaseContext); + dbProvider = GetDbProviderString(Current.DatabaseContext); } - org.umbraco.update.CheckForUpgrade check = new org.umbraco.update.CheckForUpgrade(); + var check = new org.umbraco.update.CheckForUpgrade(); check.Install(installId, IsBrandNewInstall == false, isCompleted, @@ -174,7 +173,7 @@ namespace Umbraco.Web.Install { var databaseSettings = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName]; if (GlobalSettings.ConfigurationStatus.IsNullOrWhiteSpace() - && _umbContext.Application.DatabaseContext.IsConnectionStringConfigured(databaseSettings) == false) + && _databaseContext.IsConnectionStringConfigured(databaseSettings) == false) { //no version or conn string configured, must be a brand new install return true; @@ -182,20 +181,20 @@ namespace Umbraco.Web.Install //now we have to check if this is really a new install, the db might be configured and might contain data - if (_umbContext.Application.DatabaseContext.IsConnectionStringConfigured(databaseSettings) == false - || _umbContext.Application.DatabaseContext.IsDatabaseConfigured == false) + if (_databaseContext.IsConnectionStringConfigured(databaseSettings) == false + || _databaseContext.IsDatabaseConfigured == false) { return true; } //check if we have the default user configured already - var result = _umbContext.Application.DatabaseContext.Database.ExecuteScalar( + var result = _databaseContext.Database.ExecuteScalar( "SELECT COUNT(*) FROM umbracoUser WHERE id=0 AND userPassword='default'"); if (result == 1) { //the user has not been configured //this is always true on UaaS, need to check if there's multiple users too - var usersResult = _umbContext.Application.DatabaseContext.Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoUser"); + var usersResult = _databaseContext.Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoUser"); return usersResult == 1; } @@ -220,8 +219,7 @@ namespace Umbraco.Web.Install try { - var requestUri = string.Format("http://our.umbraco.org/webapi/StarterKit/Get/?umbracoVersion={0}", - UmbracoVersion.Current); + var requestUri = $"http://our.umbraco.org/webapi/StarterKit/Get/?umbracoVersion={UmbracoVersion.Current}"; using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri)) using (var httpClient = new HttpClient()) diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs index 9ededd00d0..28b8a53371 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs @@ -1,14 +1,7 @@ using System; -using System.Collections.Generic; using System.Configuration; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Persistence; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps @@ -18,11 +11,11 @@ namespace Umbraco.Web.Install.InstallSteps PerformsAppRestart = true)] internal class DatabaseConfigureStep : InstallSetupStep { - private readonly ApplicationContext _applicationContext; + private readonly DatabaseContext _databaseContext; - public DatabaseConfigureStep(ApplicationContext applicationContext) + public DatabaseConfigureStep(DatabaseContext databaseContext) { - _applicationContext = applicationContext; + _databaseContext = databaseContext; } public override InstallSetupResult Execute(DatabaseModel database) @@ -35,7 +28,7 @@ namespace Umbraco.Web.Install.InstallSteps var dbHelper = new DatabaseHelper(); - if (dbHelper.CheckConnection(_applicationContext.DatabaseContext, database) == false) + if (dbHelper.CheckConnection(database) == false) { throw new InstallException("Could not connect to the database"); } @@ -45,18 +38,17 @@ namespace Umbraco.Web.Install.InstallSteps private void ConfigureConnection(DatabaseModel database) { - var dbContext = _applicationContext.DatabaseContext; if (database.ConnectionString.IsNullOrWhiteSpace() == false) { - dbContext.ConfigureDatabaseConnection(database.ConnectionString); + _databaseContext.ConfigureDatabaseConnection(database.ConnectionString); } else if (database.DatabaseType == DatabaseType.SqlCe) { - dbContext.ConfigureEmbeddedDatabaseConnection(); + _databaseContext.ConfigureEmbeddedDatabaseConnection(); } else if (database.IntegratedAuth) { - dbContext.ConfigureIntegratedSecurityDatabaseConnection( + _databaseContext.ConfigureIntegratedSecurityDatabaseConnection( database.Server, database.DatabaseName); } else @@ -64,7 +56,7 @@ namespace Umbraco.Web.Install.InstallSteps var password = string.Format("'{0}'", database.Password); password = password.Replace("&", "&").Replace(">", ">").Replace("<", "<").Replace("\"", """).Replace("'", "''"); - dbContext.ConfigureDatabaseConnection( + _databaseContext.ConfigureDatabaseConnection( database.Server, database.DatabaseName, database.Login, password, database.DatabaseType.ToString()); } @@ -85,12 +77,12 @@ namespace Umbraco.Web.Install.InstallSteps //If the connection string is already present in web.config we don't need to show the settings page and we jump to installing/upgrading. var databaseSettings = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName]; - if (_applicationContext.DatabaseContext.IsConnectionStringConfigured(databaseSettings)) + if (_databaseContext.IsConnectionStringConfigured(databaseSettings)) { try { //Since a connection string was present we verify the db can connect and query - var result = _applicationContext.DatabaseContext.ValidateDatabaseSchema(); + var result = _databaseContext.ValidateDatabaseSchema(); result.DetermineInstalledVersion(); return false; } diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs index f89dc39367..161341ce75 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs @@ -12,19 +12,21 @@ namespace Umbraco.Web.Install.InstallSteps "DatabaseInstall", 11, "")] internal class DatabaseInstallStep : InstallSetupStep { - private readonly ApplicationContext _applicationContext; + private readonly DatabaseContext _databaseContext; + private readonly IRuntimeState _runtime; - public DatabaseInstallStep(ApplicationContext applicationContext) + public DatabaseInstallStep(DatabaseContext databaseContext, IRuntimeState runtime) { - _applicationContext = applicationContext; + _databaseContext = databaseContext; + _runtime = runtime; } public override InstallSetupResult Execute(object model) { - if (_applicationContext.IsConfigured) + if (_runtime.Level == RuntimeLevel.Run) throw new Exception("Umbraco is already configured!"); - var result = _applicationContext.DatabaseContext.CreateDatabaseSchemaAndData(_applicationContext); + var result = _databaseContext.CreateDatabaseSchemaAndData(); if (result.Success == false) { diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs index da2b9bbdaf..f7d7a2b692 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs @@ -6,6 +6,7 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Migrations; +using Umbraco.Core.Services; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps @@ -14,11 +15,17 @@ namespace Umbraco.Web.Install.InstallSteps "DatabaseUpgrade", 12, "")] internal class DatabaseUpgradeStep : InstallSetupStep { - private readonly ApplicationContext _applicationContext; - - public DatabaseUpgradeStep(ApplicationContext applicationContext) + private readonly DatabaseContext _databaseContext; + private readonly IMigrationEntryService _migrationEntryService; + private readonly IRuntimeState _runtime; + private readonly MigrationCollectionBuilder _migrationCollectionBuilder; + + public DatabaseUpgradeStep(DatabaseContext databaseContext, IMigrationEntryService migrationEntryService, IRuntimeState runtime, MigrationCollectionBuilder migrationCollectionBuilder) { - _applicationContext = applicationContext; + _databaseContext = databaseContext; + _migrationEntryService = migrationEntryService; + _runtime = runtime; + _migrationCollectionBuilder = migrationCollectionBuilder; } public override InstallSetupResult Execute(object model) @@ -31,9 +38,7 @@ namespace Umbraco.Web.Install.InstallSteps { LogHelper.Info("Running 'Upgrade' service"); - var result = _applicationContext.DatabaseContext.UpgradeSchemaAndData( - _applicationContext.Services.MigrationEntryService, - Current.MigrationCollectionBuilder); + var result = _databaseContext.UpgradeSchemaAndData(_migrationEntryService, _migrationCollectionBuilder); if (result.Success == false) { @@ -49,10 +54,8 @@ namespace Umbraco.Web.Install.InstallSteps public override bool RequiresExecution(object model) { //if it's properly configured (i.e. the versions match) then no upgrade necessary - if (_applicationContext.IsConfigured) - { + if (_runtime.Level == RuntimeLevel.Run) return false; - } var installSteps = InstallStatusTracker.GetStatus().ToArray(); //this step relies on the previous one completed - because it has stored some information we need @@ -63,10 +66,10 @@ namespace Umbraco.Web.Install.InstallSteps var databaseSettings = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName]; - if (_applicationContext.DatabaseContext.IsConnectionStringConfigured(databaseSettings)) + if (_databaseContext.IsConnectionStringConfigured(databaseSettings)) { //Since a connection string was present we verify whether this is an upgrade or an empty db - var result = _applicationContext.DatabaseContext.ValidateDatabaseSchema(); + var result = _databaseContext.ValidateDatabaseSchema(); var determinedVersion = result.DetermineInstalledVersion(); if (determinedVersion.Equals(new Version(0, 0, 0))) diff --git a/src/Umbraco.Web/Install/InstallSteps/MajorVersion7UpgradeReport.cs b/src/Umbraco.Web/Install/InstallSteps/MajorVersion7UpgradeReport.cs index 45e5fc4846..6b2a16997e 100644 --- a/src/Umbraco.Web/Install/InstallSteps/MajorVersion7UpgradeReport.cs +++ b/src/Umbraco.Web/Install/InstallSteps/MajorVersion7UpgradeReport.cs @@ -4,7 +4,6 @@ using System.Linq; using NPoco; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.PropertyEditors; using Umbraco.Web.Install.Models; @@ -15,22 +14,24 @@ namespace Umbraco.Web.Install.InstallSteps "MajorVersion7UpgradeReport", 1, "")] internal class MajorVersion7UpgradeReport : InstallSetupStep { - private readonly ApplicationContext _applicationContext; + private readonly DatabaseContext _databaseContext; + private readonly IRuntimeState _runtime; - public MajorVersion7UpgradeReport(ApplicationContext applicationContext) + public MajorVersion7UpgradeReport(DatabaseContext databaseContext, IRuntimeState runtime) { - _applicationContext = applicationContext; + _databaseContext = databaseContext; + _runtime = runtime; } public override InstallSetupResult Execute(object model) { //we cannot run this step if the db is not configured. - if (_applicationContext.DatabaseContext.IsDatabaseConfigured == false) + if (_databaseContext.IsDatabaseConfigured == false) { return null; } - var result = _applicationContext.DatabaseContext.ValidateDatabaseSchema(); + var result = _databaseContext.ValidateDatabaseSchema(); var determinedVersion = result.DetermineInstalledVersion(); return new InstallSetupResult("version7upgradereport", @@ -45,15 +46,13 @@ namespace Umbraco.Web.Install.InstallSteps public override bool RequiresExecution(object model) { //if it's configured, then no need to run - if (_applicationContext.IsConfigured) - { + if (_runtime.Level == RuntimeLevel.Run) return false; - } try { //we cannot run this step if the db is not configured. - if (_applicationContext.DatabaseContext.IsDatabaseConfigured == false) + if (_databaseContext.IsDatabaseConfigured == false) { return false; } @@ -64,7 +63,7 @@ namespace Umbraco.Web.Install.InstallSteps return false; } - var result = _applicationContext.DatabaseContext.ValidateDatabaseSchema(); + var result = _databaseContext.ValidateDatabaseSchema(); var determinedVersion = result.DetermineInstalledVersion(); if ((string.IsNullOrWhiteSpace(GlobalSettings.ConfigurationStatus) == false || determinedVersion.Equals(new Version(0, 0, 0)) == false) && UmbracoVersion.Current.Major > determinedVersion.Major) @@ -82,7 +81,7 @@ namespace Umbraco.Web.Install.InstallSteps { var errorReport = new List(); - var sqlSyntax = _applicationContext.DatabaseContext.SqlSyntax; + var sqlSyntax = _databaseContext.SqlSyntax; var sql = new Sql(); sql @@ -95,7 +94,7 @@ namespace Umbraco.Web.Install.InstallSteps sqlSyntax.GetQuotedColumn("cmsDataType", "nodeId") + " = " + sqlSyntax.GetQuotedColumn("umbracoNode", "id")); - var list = _applicationContext.DatabaseContext.Database.Fetch(sql); + var list = _databaseContext.Database.Fetch(sql); foreach (var item in list) { Guid legacyId = item.controlId; diff --git a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs index 4d8e9c5a4b..ef473c3db2 100644 --- a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs @@ -7,6 +7,7 @@ using System.Web.Security; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Persistence; +using Umbraco.Core.Services; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps @@ -24,12 +25,14 @@ namespace Umbraco.Web.Install.InstallSteps internal class NewInstallStep : InstallSetupStep { private readonly HttpContextBase _http; - private readonly ApplicationContext _applicationContext; + private readonly IUserService _userService; + private readonly DatabaseContext _databaseContext; - public NewInstallStep(HttpContextBase http, ApplicationContext applicationContext) + public NewInstallStep(HttpContextBase http, IUserService userService, DatabaseContext databaseContext) { _http = http; - _applicationContext = applicationContext; + _userService = userService; + _databaseContext = databaseContext; } private MembershipProvider CurrentProvider @@ -43,7 +46,7 @@ namespace Umbraco.Web.Install.InstallSteps public override InstallSetupResult Execute(UserModel user) { - var admin = _applicationContext.Services.UserService.GetUserById(0); + var admin = _userService.GetUserById(0); if (admin == null) { throw new InvalidOperationException("Could not find the admi user!"); @@ -72,7 +75,7 @@ namespace Umbraco.Web.Install.InstallSteps admin.Name = user.Name.Trim(); admin.Username = user.Email.Trim(); - _applicationContext.Services.UserService.Save(admin); + _userService.Save(admin); if (user.SubscribeToNewsLetter) @@ -124,11 +127,11 @@ namespace Umbraco.Web.Install.InstallSteps // left a version number in there but cleared out their db conn string, in that case, it's really a new install. if (GlobalSettings.ConfigurationStatus.IsNullOrWhiteSpace() == false && databaseSettings != null) return false; - if (_applicationContext.DatabaseContext.IsConnectionStringConfigured(databaseSettings) - && _applicationContext.DatabaseContext.IsDatabaseConfigured) + if (_databaseContext.IsConnectionStringConfigured(databaseSettings) + && _databaseContext.IsDatabaseConfigured) { //check if we have the default user configured already - var result = _applicationContext.DatabaseContext.Database.ExecuteScalar( + var result = _databaseContext.Database.ExecuteScalar( "SELECT COUNT(*) FROM umbracoUser WHERE id=0 AND userPassword='default'"); if (result == 1) { diff --git a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs index aa8a00ddf3..51e1ec5bcf 100644 --- a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections.Generic; using System.Web; using Umbraco.Core; using Umbraco.Core.Configuration; @@ -16,23 +14,23 @@ namespace Umbraco.Web.Install.InstallSteps PerformsAppRestart = true)] internal class SetUmbracoVersionStep : InstallSetupStep { - private readonly ApplicationContext _applicationContext; private readonly HttpContextBase _httpContext; + private readonly ILogger _logger; + private readonly InstallHelper _installHelper; - public SetUmbracoVersionStep(ApplicationContext applicationContext, HttpContextBase httpContext) + public SetUmbracoVersionStep(HttpContextBase httpContext, ILogger logger, InstallHelper installHelper) { - _applicationContext = applicationContext; _httpContext = httpContext; + _logger = logger; + _installHelper = installHelper; } public override InstallSetupResult Execute(object model) { - var ih = new InstallHelper(UmbracoContext.Current); - //During a new install we'll log the default user in (which is id = 0). // During an upgrade, the user will already need to be logged in in order to run the installer. - var security = new WebSecurity(_httpContext, _applicationContext); + var security = new WebSecurity(_httpContext, Current.Services.UserService); //we do this check here because for upgrades the user will already be logged in, for brand new installs, // they will not be logged in, however we cannot check the current installation status because it will tell // us that it is in 'upgrade' because we already have a database conn configured and a database. @@ -47,14 +45,14 @@ namespace Umbraco.Web.Install.InstallSteps DistributedCache.Instance.RefreshAllFacade(); // Update configurationStatus - GlobalSettings.ConfigurationStatus = UmbracoVersion.GetSemanticVersion().ToSemanticString(); + GlobalSettings.ConfigurationStatus = UmbracoVersion.SemanticVersion.ToSemanticString(); // Update ClientDependency version - var clientDependencyConfig = new ClientDependencyConfiguration(_applicationContext.ProfilingLogger.Logger); + var clientDependencyConfig = new ClientDependencyConfiguration(_logger); var clientDependencyUpdated = clientDependencyConfig.IncreaseVersionNumber(); - - //reports the ended install - ih.InstallStatus(true, ""); + + //reports the ended install + _installHelper.InstallStatus(true, ""); return null; } diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs index 87717101f9..73944fe718 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs @@ -1,10 +1,7 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Web; -using umbraco; using umbraco.cms.businesslogic.packager; -using Umbraco.Core; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps @@ -13,13 +10,6 @@ namespace Umbraco.Web.Install.InstallSteps "StarterKitCleanup", 32, "Almost done")] internal class StarterKitCleanupStep : InstallSetupStep { - private readonly ApplicationContext _applicationContext; - - public StarterKitCleanupStep(ApplicationContext applicationContext) - { - _applicationContext = applicationContext; - } - public override InstallSetupResult Execute(object model) { var installSteps = InstallStatusTracker.GetStatus().ToArray(); diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs index e8397136a9..a94e7ba61c 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Web; using umbraco.cms.businesslogic.packager; -using Umbraco.Core; +using Umbraco.Core.Services; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps @@ -12,11 +12,13 @@ namespace Umbraco.Web.Install.InstallSteps "StarterKitDownload", "starterKit", 30, "Adding a simple website to Umbraco, will make it easier for you to get started")] internal class StarterKitDownloadStep : InstallSetupStep { - private readonly ApplicationContext _applicationContext; + private readonly InstallHelper _installHelper; + private readonly IContentService _contentService; - public StarterKitDownloadStep(ApplicationContext applicationContext) + public StarterKitDownloadStep(IContentService contentService, InstallHelper installHelper) { - _applicationContext = applicationContext; + _installHelper = installHelper; + _contentService = contentService; } private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; @@ -26,8 +28,7 @@ namespace Umbraco.Web.Install.InstallSteps //if there is no value assigned then use the default starter kit if (starterKitId.HasValue == false) { - var installHelper = new InstallHelper(UmbracoContext.Current); - var starterKits = installHelper.GetStarterKits().FirstOrDefault(); + var starterKits = _installHelper.GetStarterKits().FirstOrDefault(); if (starterKits != null) starterKitId = starterKits.Id; else @@ -96,7 +97,7 @@ namespace Umbraco.Web.Install.InstallSteps if (InstalledPackage.GetAllInstalledPackages().Count > 0) return false; - if (_applicationContext.Services.ContentService.GetRootContent().Any()) + if (_contentService.GetRootContent().Any()) return false; return true; diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs index e206ed559a..acbb80de96 100644 --- a/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs @@ -1,9 +1,7 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Web; using umbraco.cms.businesslogic.packager; -using Umbraco.Core; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps @@ -13,26 +11,24 @@ namespace Umbraco.Web.Install.InstallSteps PerformsAppRestart = true)] internal class StarterKitInstallStep : InstallSetupStep { - private readonly ApplicationContext _applicationContext; private readonly HttpContextBase _httContext; - public StarterKitInstallStep(ApplicationContext applicationContext, HttpContextBase httContext) + public StarterKitInstallStep(HttpContextBase httContext) { - _applicationContext = applicationContext; _httContext = httContext; } public override InstallSetupResult Execute(object model) { - var installSteps = InstallStatusTracker.GetStatus().ToArray(); + var installSteps = InstallStatusTracker.GetStatus().ToArray(); var previousStep = installSteps.Single(x => x.Name == "StarterKitDownload"); var manifestId = Convert.ToInt32(previousStep.AdditionalData["manifestId"]); var packageFile = (string)previousStep.AdditionalData["packageFile"]; InstallBusinessLogic(manifestId, packageFile); - _applicationContext.RestartApplicationPool(_httContext); + Current.RestartAppPool(_httContext); return null; } @@ -42,11 +38,11 @@ namespace Umbraco.Web.Install.InstallSteps packageFile = HttpUtility.UrlDecode(packageFile); var installer = new Installer(); installer.LoadConfig(packageFile); - installer.InstallBusinessLogic(manifestId, packageFile); + installer.InstallBusinessLogic(manifestId, packageFile); } public override bool RequiresExecution(object model) - { + { var installSteps = InstallStatusTracker.GetStatus().ToArray(); //this step relies on the preious one completed - because it has stored some information we need if (installSteps.Any(x => x.Name == "StarterKitDownload" && x.AdditionalData.ContainsKey("manifestId")) == false) diff --git a/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs b/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs index 42bca03498..2c733ec883 100644 --- a/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/UpgradeStep.cs @@ -51,9 +51,9 @@ namespace Umbraco.Web.Install.InstallSteps var version = new SemVersion(0); //If we have a db context available, if we don't then we are not installed anyways - if (ApplicationContext.Current.DatabaseContext.IsDatabaseConfigured && ApplicationContext.Current.DatabaseContext.CanConnect) + if (Current.DatabaseContext.IsDatabaseConfigured && Current.DatabaseContext.CanConnect) { - version = ApplicationContext.Current.DatabaseContext.ValidateDatabaseSchema().DetermineInstalledVersionByMigrations(ApplicationContext.Current.Services.MigrationEntryService); + version = Current.DatabaseContext.ValidateDatabaseSchema().DetermineInstalledVersionByMigrations(Current.Services.MigrationEntryService); } return version; diff --git a/src/Umbraco.Web/Macros/MacroRenderer.cs b/src/Umbraco.Web/Macros/MacroRenderer.cs index dd5912230d..5ae5ec2bb8 100644 --- a/src/Umbraco.Web/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web/Macros/MacroRenderer.cs @@ -95,7 +95,7 @@ namespace Umbraco.Web.Macros // only if cache is enabled if (UmbracoContext.Current.InPreviewMode || model.CacheDuration <= 0) return null; - var cache = ApplicationContext.Current.ApplicationCache.RuntimeCache; + var cache = Current.ApplicationCache.RuntimeCache; var macroContent = cache.GetCacheItem(CacheKeys.MacroContentCacheKey + model.CacheIdentifier); if (macroContent == null) return null; @@ -157,7 +157,7 @@ namespace Umbraco.Web.Macros // remember when we cache the content macroContent.Date = DateTime.Now; - var cache = ApplicationContext.Current.ApplicationCache.RuntimeCache; + var cache = Current.ApplicationCache.RuntimeCache; cache.InsertCacheItem( CacheKeys.MacroContentCacheKey + model.CacheIdentifier, () => macroContent, @@ -370,7 +370,7 @@ namespace Umbraco.Web.Macros || UmbracoContext.Current.PublishedContentRequest.HasPublishedContent == false) return Attempt.Fail(new MacroContent { Text = "[macro]" }); - var textService = ApplicationContext.Current.Services.TextService; + var textService = Current.Services.TextService; switch (model.MacroType) { diff --git a/src/Umbraco.Web/Macros/XsltMacroEngine.cs b/src/Umbraco.Web/Macros/XsltMacroEngine.cs index 3bd8ea3998..6b682c266f 100644 --- a/src/Umbraco.Web/Macros/XsltMacroEngine.cs +++ b/src/Umbraco.Web/Macros/XsltMacroEngine.cs @@ -525,7 +525,7 @@ namespace Umbraco.Web.Macros { //TODO: SD: Do we really need to cache this?? var filepath = IOHelper.MapPath(SystemDirectories.Xslt.EnsureEndsWith('/') + filename); - return ApplicationContext.Current.ApplicationCache.GetCacheItem( + return Current.ApplicationCache.GetCacheItem( CacheKeys.MacroXsltCacheKey + filename, CacheItemPriority.Default, new CacheDependency(filepath), diff --git a/src/Umbraco.Web/ManifestWatcherComponent.cs b/src/Umbraco.Web/ManifestWatcherComponent.cs index a7e0e5a032..7bf9c27aab 100644 --- a/src/Umbraco.Web/ManifestWatcherComponent.cs +++ b/src/Umbraco.Web/ManifestWatcherComponent.cs @@ -6,24 +6,17 @@ using Umbraco.Core.Manifest; namespace Umbraco.Web { - //[RequireComponent(typeof(object))] // fixme - the one that ensures that runtime.Something is ok public class ManifestWatcherComponent : UmbracoComponentBase, IUmbracoCoreComponent { // if configured and in debug mode, a ManifestWatcher watches App_Plugins folders for // package.manifest chances and restarts the application on any change private ManifestWatcher _mw; - public void Initialize(RuntimeState runtime) + public void Initialize(IRuntimeState runtime) { - // fixme - // if this is a core component it cannot depend on UmbracoCoreComponent - indicates that everything is OK - // so what-if UmbracoCoreComponent ... aha ... need another one? UmbracoRuntimeComponent? - // or should we have it in IRuntime AND inject IRuntime? IRuntimeInternal vs IRuntime? - - // runtime should be INJECTED! aha! // BUT how can we tell that runtime is "ready enough"? need to depend on some sort of UmbracoRuntimeComponent? // and... will this kind of dependency issue be repro everywhere?! - if (runtime.Something < RuntimeSomething.Run || runtime.Debug == false) return; + if (runtime.Level < RuntimeLevel.Run || runtime.Debug == false) return; //if (ApplicationContext.Current.IsConfigured == false || GlobalSettings.DebugMode == false) // return; diff --git a/src/Umbraco.Web/Media/ImageUrl.cs b/src/Umbraco.Web/Media/ImageUrl.cs index 3b7ee2b884..f857f00a6c 100644 --- a/src/Umbraco.Web/Media/ImageUrl.cs +++ b/src/Umbraco.Web/Media/ImageUrl.cs @@ -87,8 +87,8 @@ namespace Umbraco.Web.Media private static object GetContentFromCache(int nodeIdInt, string field) { - var content = ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem( - string.Format("{0}{1}_{2}", CacheKeys.ContentItemCacheKey, nodeIdInt.ToString(CultureInfo.InvariantCulture), field)); + var content = Current.ApplicationCache.RuntimeCache.GetCacheItem( + string.Format("{0}{1}_{2}", CacheKeys.ContentItemCacheKey, nodeIdInt.ToString(CultureInfo.InvariantCulture), field)); return content; } } diff --git a/src/Umbraco.Web/Models/ContentExtensions.cs b/src/Umbraco.Web/Models/ContentExtensions.cs index 6f7aeb8070..256d8e9cd7 100644 --- a/src/Umbraco.Web/Models/ContentExtensions.cs +++ b/src/Umbraco.Web/Models/ContentExtensions.cs @@ -22,9 +22,9 @@ namespace Umbraco.Web.Models public static CultureInfo GetCulture(this IContent content, Uri current = null) { return GetCulture(UmbracoContext.Current, - ApplicationContext.Current.Services.DomainService, - ApplicationContext.Current.Services.LocalizationService, - ApplicationContext.Current.Services.ContentService, + Current.Services.DomainService, + Current.Services.LocalizationService, + Current.Services.ContentService, content.Id, content.Path, current); } diff --git a/src/Umbraco.Web/Models/LoginStatusModel.cs b/src/Umbraco.Web/Models/LoginStatusModel.cs index e10b42b096..ffc04f4021 100644 --- a/src/Umbraco.Web/Models/LoginStatusModel.cs +++ b/src/Umbraco.Web/Models/LoginStatusModel.cs @@ -7,25 +7,24 @@ using Umbraco.Web.Security; namespace Umbraco.Web.Models { /// - /// The model representing the status of a logged in member + /// The model representing the status of a logged in member. /// public class LoginStatusModel { /// - /// Creates a new empty LoginStatusModel + /// Creates a new empty LoginStatusModel. /// /// public static LoginStatusModel CreateModel() { - var model = new LoginStatusModel(false); - return model; + return new LoginStatusModel(false); } private LoginStatusModel(bool doLookup) { - if (doLookup && HttpContext.Current != null && ApplicationContext.Current != null) + if (doLookup && HttpContext.Current != null) { - var helper = new MembershipHelper(ApplicationContext.Current, new HttpContextWrapper(HttpContext.Current)); + var helper = new MembershipHelper(new HttpContextWrapper(HttpContext.Current)); var model = helper.GetCurrentLoginStatus(); if (model != null) { @@ -43,9 +42,7 @@ namespace Umbraco.Web.Models [Obsolete("Do not use this ctor as it will perform business logic lookups. Use the MembershipHelper.GetCurrentLoginStatus or the static LoginStatusModel.CreateModel() to create an empty model.")] public LoginStatusModel() : this(true) - { - - } + { } /// /// The name of the member diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs index b5ef19c315..1c8fc5b01e 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs @@ -6,7 +6,6 @@ using System.Web; using System.Web.Mvc; using System.Web.Routing; using AutoMapper; -using umbraco; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Mapping; @@ -14,7 +13,6 @@ using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Trees; using Umbraco.Web.Routing; -using Umbraco.Core.PropertyEditors; using Umbraco.Web._Legacy.Actions; namespace Umbraco.Web.Models.Mapping @@ -24,17 +22,32 @@ namespace Umbraco.Web.Models.Mapping /// internal class ContentModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + private readonly IUserService _userService; + private readonly ILocalizedTextService _textService; + private readonly IContentService _contentService; + private readonly IContentTypeService _contentTypeService; + private readonly IDataTypeService _dataTypeService; + + public ContentModelMapper(IUserService userService, ILocalizedTextService textService, IContentService contentService, IContentTypeService contentTypeService, IDataTypeService dataTypeService) + { + _userService = userService; + _textService = textService; + _contentService = contentService; + _contentTypeService = contentTypeService; + _dataTypeService = dataTypeService; + } + + public override void ConfigureMappings(IMapperConfiguration config) { //FROM IContent TO ContentItemDisplay config.CreateMap() .ForMember( dto => dto.Owner, - expression => expression.ResolveUsing(new OwnerResolver(applicationContext.Services.UserService))) + expression => expression.ResolveUsing(new OwnerResolver(_userService))) .ForMember( dto => dto.Updater, - expression => expression.ResolveUsing(new CreatorResolver(applicationContext.Services.UserService))) + expression => expression.ResolveUsing(new CreatorResolver(_userService))) .ForMember( dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) @@ -53,7 +66,7 @@ namespace Umbraco.Web.Models.Mapping expression => expression.MapFrom(content => content.Trashed)) .ForMember( dto => dto.PublishDate, - expression => expression.MapFrom(content => GetPublishedDate(content, applicationContext))) + expression => expression.MapFrom(content => GetPublishedDate(_contentService, content))) .ForMember( dto => dto.TemplateAlias, expression => expression.MapFrom(content => content.Template.Alias)) .ForMember( @@ -67,20 +80,20 @@ namespace Umbraco.Web.Models.Mapping .ForMember(display => display.Notifications, expression => expression.Ignore()) .ForMember(display => display.Errors, expression => expression.Ignore()) .ForMember(display => display.Alias, expression => expression.Ignore()) - .ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver(applicationContext.Services.TextService))) + .ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver(_textService))) .ForMember(display => display.AllowedActions, expression => expression.ResolveUsing( - new ActionButtonsResolver(new Lazy(() => applicationContext.Services.UserService)))) - .AfterMap((media, display) => AfterMap(media, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService, - applicationContext.Services.ContentTypeService, applicationContext.Services.ContentService)); + new ActionButtonsResolver(new Lazy(() => _userService)))) + .AfterMap((media, display) => AfterMap(media, display, _dataTypeService, _textService, + _contentTypeService, _contentService)); //FROM IContent TO ContentItemBasic config.CreateMap>() .ForMember( dto => dto.Owner, - expression => expression.ResolveUsing(new OwnerResolver(applicationContext.Services.UserService))) + expression => expression.ResolveUsing(new OwnerResolver(_userService))) .ForMember( dto => dto.Updater, - expression => expression.ResolveUsing(new CreatorResolver(applicationContext.Services.UserService))) + expression => expression.ResolveUsing(new CreatorResolver(_userService))) .ForMember( dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) @@ -96,7 +109,7 @@ namespace Umbraco.Web.Models.Mapping config.CreateMap>() .ForMember( dto => dto.Owner, - expression => expression.ResolveUsing(new OwnerResolver(applicationContext.Services.UserService))) + expression => expression.ResolveUsing(new OwnerResolver(_userService))) .ForMember(display => display.Updater, expression => expression.Ignore()) .ForMember(display => display.Icon, expression => expression.Ignore()) .ForMember(display => display.Alias, expression => expression.Ignore()); @@ -257,10 +270,10 @@ namespace Umbraco.Web.Models.Mapping /// /// Gets the published date value for the IContent object /// + /// /// - /// /// - private static DateTime? GetPublishedDate(IContent content, ApplicationContext applicationContext) + private static DateTime? GetPublishedDate(IContentService contentService, IContent content) { if (content.Published) { @@ -268,7 +281,7 @@ namespace Umbraco.Web.Models.Mapping } if (content.HasPublishedVersion) { - var published = applicationContext.Services.ContentService.GetPublishedVersion(content.Id); + var published = contentService.GetPublishedVersion(content.Id); return published.UpdateDate; } return null; diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyModelMapper.cs index 6f09823644..3f92acd1af 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentPropertyModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyModelMapper.cs @@ -1,6 +1,5 @@ using System; using AutoMapper; -using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Mapping; using Umbraco.Core.Services; @@ -14,9 +13,16 @@ namespace Umbraco.Web.Models.Mapping /// internal class ContentPropertyModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + private readonly IDataTypeService _dataTypeService; + + public ContentPropertyModelMapper(IDataTypeService dataTypeService) { - var lazyDataTypeService = new Lazy(() => applicationContext.Services.DataTypeService); + _dataTypeService = dataTypeService; + } + + public override void ConfigureMappings(IMapperConfiguration config) + { + var lazyDataTypeService = new Lazy(() => _dataTypeService); //FROM Property TO ContentPropertyBasic config.CreateMap>() diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs index 46d5dc1ae3..ea85f1cee8 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs @@ -1,14 +1,11 @@ using System; using System.Linq; -using System.Threading; using AutoMapper; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Mapping; using Umbraco.Core.PropertyEditors; using Umbraco.Web.Models.ContentEditing; -using System.Collections.Generic; -using AutoMapper.Internal; using Umbraco.Core.Services; namespace Umbraco.Web.Models.Mapping @@ -19,24 +16,25 @@ namespace Umbraco.Web.Models.Mapping internal class ContentTypeModelMapper : ModelMapperConfiguration { private readonly PropertyEditorCollection _propertyEditors; + private readonly IDataTypeService _dataTypeService; + private readonly IFileService _fileService; + private readonly IContentTypeService _contentTypeService; + private readonly IMediaTypeService _mediaTypeService; - //default ctor - public ContentTypeModelMapper() + public ContentTypeModelMapper(PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, IFileService fileService, IContentTypeService contentTypeService, IMediaTypeService mediaTypeService) { - _propertyEditors = Current.PropertyEditors; + _propertyEditors = propertyEditors; + _dataTypeService = dataTypeService; + _fileService = fileService; + _contentTypeService = contentTypeService; + _mediaTypeService = mediaTypeService; } - //ctor can be used for testing - public ContentTypeModelMapper(PropertyEditorCollection propertyEditors) - { - _propertyEditors = propertyEditors; - } - - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + public override void ConfigureMappings(IMapperConfiguration config) { config.CreateMap() - .ConstructUsing(basic => new PropertyType(applicationContext.Services.DataTypeService.GetDataTypeDefinitionById(basic.DataTypeId))) + .ConstructUsing(basic => new PropertyType(_dataTypeService.GetDataTypeDefinitionById(basic.DataTypeId))) .ForMember(type => type.ValidationRegExp, expression => expression.ResolveUsing(basic => basic.Validation.Pattern)) .ForMember(type => type.Mandatory, expression => expression.ResolveUsing(basic => basic.Validation.Mandatory)) .ForMember(type => type.Name, expression => expression.ResolveUsing(basic => basic.Label)) @@ -51,7 +49,7 @@ namespace Umbraco.Web.Models.Mapping config.CreateMap() //do the base mapping - .MapBaseContentTypeSaveToEntity(applicationContext) + .MapBaseContentTypeSaveToEntity() .ConstructUsing((source) => new ContentType(source.ParentId)) .ForMember(source => source.AllowedTemplates, expression => expression.Ignore()) .ForMember(dto => dto.DefaultTemplate, expression => expression.Ignore()) @@ -59,31 +57,31 @@ namespace Umbraco.Web.Models.Mapping { dest.AllowedTemplates = source.AllowedTemplates .Where(x => x != null) - .Select(s => applicationContext.Services.FileService.GetTemplate(s)) + .Select(s => _fileService.GetTemplate(s)) .ToArray(); if (source.DefaultTemplate != null) - dest.SetDefaultTemplate(applicationContext.Services.FileService.GetTemplate(source.DefaultTemplate)); + dest.SetDefaultTemplate(_fileService.GetTemplate(source.DefaultTemplate)); - ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext); + ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, _contentTypeService); }); config.CreateMap() //do the base mapping - .MapBaseContentTypeSaveToEntity(applicationContext) + .MapBaseContentTypeSaveToEntity() .ConstructUsing((source) => new MediaType(source.ParentId)) .AfterMap((source, dest) => { - ContentTypeModelMapperExtensions.AfterMapMediaTypeSaveToEntity(source, dest, applicationContext); + ContentTypeModelMapperExtensions.AfterMapMediaTypeSaveToEntity(source, dest, _mediaTypeService); }); config.CreateMap() //do the base mapping - .MapBaseContentTypeSaveToEntity(applicationContext) + .MapBaseContentTypeSaveToEntity() .ConstructUsing((source) => new MemberType(source.ParentId)) .AfterMap((source, dest) => { - ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext); + ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, _contentTypeService); //map the MemberCanEditProperty,MemberCanViewProperty foreach (var propertyType in source.Groups.SelectMany(x => x.Properties)) @@ -102,7 +100,7 @@ namespace Umbraco.Web.Models.Mapping config.CreateMap() //map base logic - .MapBaseContentTypeEntityToDisplay(applicationContext, _propertyEditors) + .MapBaseContentTypeEntityToDisplay(_propertyEditors, _dataTypeService, _contentTypeService) .AfterMap((memberType, display) => { //map the MemberCanEditProperty,MemberCanViewProperty @@ -120,7 +118,7 @@ namespace Umbraco.Web.Models.Mapping config.CreateMap() //map base logic - .MapBaseContentTypeEntityToDisplay(applicationContext, _propertyEditors) + .MapBaseContentTypeEntityToDisplay(_propertyEditors, _dataTypeService, _contentTypeService) .AfterMap((source, dest) => { //default listview @@ -129,14 +127,14 @@ namespace Umbraco.Web.Models.Mapping if (string.IsNullOrEmpty(source.Name) == false) { var name = Constants.Conventions.DataTypes.ListViewPrefix + source.Name; - if (applicationContext.Services.DataTypeService.GetDataTypeDefinitionByName(name) != null) + if (_dataTypeService.GetDataTypeDefinitionByName(name) != null) dest.ListViewEditorName = name; } }); config.CreateMap() //map base logic - .MapBaseContentTypeEntityToDisplay(applicationContext, _propertyEditors) + .MapBaseContentTypeEntityToDisplay(_propertyEditors, _dataTypeService, _contentTypeService) .ForMember(dto => dto.AllowedTemplates, expression => expression.Ignore()) .ForMember(dto => dto.DefaultTemplate, expression => expression.Ignore()) .ForMember(display => display.Notifications, expression => expression.Ignore()) @@ -154,7 +152,7 @@ namespace Umbraco.Web.Models.Mapping if (string.IsNullOrEmpty(source.Alias) == false) { var name = Constants.Conventions.DataTypes.ListViewPrefix + source.Alias; - if (applicationContext.Services.DataTypeService.GetDataTypeDefinitionByName(name) != null) + if (_dataTypeService.GetDataTypeDefinitionByName(name) != null) dest.ListViewEditorName = name; } @@ -168,7 +166,7 @@ namespace Umbraco.Web.Models.Mapping .ConstructUsing(propertyTypeBasic => { - var dataType = applicationContext.Services.DataTypeService.GetDataTypeDefinitionById(propertyTypeBasic.DataTypeId); + var dataType = _dataTypeService.GetDataTypeDefinitionById(propertyTypeBasic.DataTypeId); if (dataType == null) throw new NullReferenceException("No data type found with id " + propertyTypeBasic.DataTypeId); return new PropertyType(dataType, propertyTypeBasic.Alias); }) @@ -212,7 +210,7 @@ namespace Umbraco.Web.Models.Mapping //if the dest is set and it's the same as the source, then don't change if (destAllowedTemplateAliases.SequenceEqual(source.AllowedTemplates) == false) { - var templates = applicationContext.Services.FileService.GetTemplates(source.AllowedTemplates.ToArray()); + var templates = _fileService.GetTemplates(source.AllowedTemplates.ToArray()); dest.AllowedTemplates = source.AllowedTemplates .Select(x => Mapper.Map(templates.SingleOrDefault(t => t.Alias == x))) .WhereNotNull() @@ -224,7 +222,7 @@ namespace Umbraco.Web.Models.Mapping //if the dest is set and it's the same as the source, then don't change if (dest.DefaultTemplate == null || source.DefaultTemplate != dest.DefaultTemplate.Alias) { - var template = applicationContext.Services.FileService.GetTemplate(source.DefaultTemplate); + var template = _fileService.GetTemplate(source.DefaultTemplate); dest.DefaultTemplate = template == null ? null : Mapper.Map(template); } } diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs index 66ebee02ec..7a91c7ef53 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs @@ -5,6 +5,7 @@ using AutoMapper; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Models.Mapping @@ -48,9 +49,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(g => g.Properties, expression => expression.MapFrom(display => display.Properties.Select(Mapper.Map))); } - public static void AfterMapContentTypeSaveToEntity( - TSource source, TDestination dest, - ApplicationContext applicationContext) + public static void AfterMapContentTypeSaveToEntity(TSource source, TDestination dest, IContentTypeService contentTypeService) where TSource : ContentTypeSave where TDestination : IContentTypeComposition { @@ -69,15 +68,13 @@ namespace Umbraco.Web.Models.Mapping foreach (var a in add) { //TODO: Remove N+1 lookup - var addCt = applicationContext.Services.ContentTypeService.Get(a); + var addCt = contentTypeService.Get(a); if (addCt != null) dest.AddContentType(addCt); } } - public static void AfterMapMediaTypeSaveToEntity( - TSource source, TDestination dest, - ApplicationContext applicationContext) + public static void AfterMapMediaTypeSaveToEntity(TSource source, TDestination dest, IMediaTypeService mediaTypeService) where TSource : MediaTypeSave where TDestination : IContentTypeComposition { @@ -96,7 +93,7 @@ namespace Umbraco.Web.Models.Mapping foreach (var a in add) { //TODO: Remove N+1 lookup - var addCt = applicationContext.Services.MediaTypeService.Get(a); + var addCt = mediaTypeService.Get(a); if (addCt != null) dest.AddContentType(addCt); } @@ -120,7 +117,8 @@ namespace Umbraco.Web.Models.Mapping } public static IMappingExpression MapBaseContentTypeEntityToDisplay( - this IMappingExpression mapping, ApplicationContext applicationContext, PropertyEditorCollection propertyEditors) + this IMappingExpression mapping, PropertyEditorCollection propertyEditors, + IDataTypeService dataTypeService, IContentTypeService contentTypeService) where TSource : IContentTypeComposition where TDestination : ContentTypeCompositionDisplay where TPropertyTypeDisplay : PropertyTypeDisplay, new() @@ -143,11 +141,11 @@ namespace Umbraco.Web.Models.Mapping .ForMember( dto => dto.LockedCompositeContentTypes, - expression => expression.ResolveUsing(new LockedCompositionsResolver(applicationContext))) + expression => expression.ResolveUsing(new LockedCompositionsResolver(contentTypeService))) .ForMember( dto => dto.Groups, - expression => expression.ResolveUsing(new PropertyTypeGroupResolver(applicationContext, propertyEditors))); + expression => expression.ResolveUsing(new PropertyTypeGroupResolver(propertyEditors, dataTypeService))); } /// @@ -157,10 +155,9 @@ namespace Umbraco.Web.Models.Mapping /// /// /// - /// /// public static IMappingExpression MapBaseContentTypeSaveToEntity( - this IMappingExpression mapping, ApplicationContext applicationContext) + this IMappingExpression mapping) //where TSource : ContentTypeCompositionDisplay where TSource : ContentTypeSave where TDestination : IContentTypeComposition diff --git a/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs b/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs index 12d10858d0..4cff44ba2f 100644 --- a/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs @@ -16,9 +16,16 @@ namespace Umbraco.Web.Models.Mapping /// internal class DataTypeModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + private readonly IDataTypeService _dataTypeService; + + public DataTypeModelMapper(IDataTypeService dataTypeService) { - var lazyDataTypeService = new Lazy(() => applicationContext.Services.DataTypeService); + _dataTypeService = dataTypeService; + } + + public override void ConfigureMappings(IMapperConfiguration config) + { + var lazyDataTypeService = new Lazy(() => _dataTypeService); config.CreateMap(); @@ -62,8 +69,7 @@ namespace Umbraco.Web.Models.Mapping config.CreateMap() .ForMember(display => display.AvailableEditors, expression => expression.ResolveUsing()) - .ForMember(display => display.PreValues, expression => expression.ResolveUsing( - new PreValueDisplayResolver(lazyDataTypeService))) + .ForMember(display => display.PreValues, expression => expression.ResolveUsing(new PreValueDisplayResolver(lazyDataTypeService))) .ForMember(display => display.SelectedEditor, expression => expression.MapFrom( definition => definition.PropertyEditorAlias.IsNullOrWhiteSpace() ? null : definition.PropertyEditorAlias)) .ForMember(x => x.HasPrevalues, expression => expression.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs index 659cb1bf50..4b796e7093 100644 --- a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs @@ -5,7 +5,6 @@ using AutoMapper; using Examine; using Examine.LuceneEngine; using Examine.LuceneEngine.Providers; -using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Mapping; using Umbraco.Core.Models.Membership; @@ -16,7 +15,7 @@ namespace Umbraco.Web.Models.Mapping { internal class EntityModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + public override void ConfigureMappings(IMapperConfiguration config) { config.CreateMap() .ForMember(basic => basic.Icon, expression => expression.MapFrom(entity => entity.ContentTypeIcon)) diff --git a/src/Umbraco.Web/Models/Mapping/LockedCompositionsResolver.cs b/src/Umbraco.Web/Models/Mapping/LockedCompositionsResolver.cs index cc3007ef29..c4335af02c 100644 --- a/src/Umbraco.Web/Models/Mapping/LockedCompositionsResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/LockedCompositionsResolver.cs @@ -3,16 +3,17 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.Services; namespace Umbraco.Web.Models.Mapping { internal class LockedCompositionsResolver : ValueResolver> { - private readonly ApplicationContext _applicationContext; + private readonly IContentTypeService _contentTypeService; - public LockedCompositionsResolver(ApplicationContext applicationContext) + public LockedCompositionsResolver(IContentTypeService contentTypeService) { - _applicationContext = applicationContext; + _contentTypeService = contentTypeService; } protected override IEnumerable ResolveCore(IContentTypeComposition source) @@ -21,12 +22,12 @@ namespace Umbraco.Web.Models.Mapping // get ancestor ids from path of parent if not root if (source.ParentId != Constants.System.Root) { - var parent = _applicationContext.Services.ContentTypeService.Get(source.ParentId); + var parent = _contentTypeService.Get(source.ParentId); if (parent != null) { var ancestorIds = parent.Path.Split(',').Select(int.Parse); // loop through all content types and return ordered aliases of ancestors - var allContentTypes = _applicationContext.Services.ContentTypeService.GetAll().ToArray(); + var allContentTypes = _contentTypeService.GetAll().ToArray(); foreach (var ancestorId in ancestorIds) { var ancestor = allContentTypes.FirstOrDefault(x => x.Id == ancestorId); diff --git a/src/Umbraco.Web/Models/Mapping/LogModelMapper.cs b/src/Umbraco.Web/Models/Mapping/LogModelMapper.cs index 349141ea4e..0b9847ea5e 100644 --- a/src/Umbraco.Web/Models/Mapping/LogModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/LogModelMapper.cs @@ -1,15 +1,13 @@ using AutoMapper; -using Umbraco.Core; using Umbraco.Core.Models.Mapping; using Umbraco.Web.Models.ContentEditing; -using umbraco.BusinessLogic; using Umbraco.Core.Models; namespace Umbraco.Web.Models.Mapping { internal class LogModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + public override void ConfigureMappings(IMapperConfiguration config) { config.CreateMap() .ForMember(log => log.NodeId, expression => expression.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/MacroModelMapper.cs b/src/Umbraco.Web/Models/Mapping/MacroModelMapper.cs index dfdd775e1f..c4807e9a01 100644 --- a/src/Umbraco.Web/Models/Mapping/MacroModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MacroModelMapper.cs @@ -1,12 +1,10 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using AutoMapper; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Mapping; -using Umbraco.Core.PropertyEditors; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Models.Mapping @@ -16,7 +14,7 @@ namespace Umbraco.Web.Models.Mapping /// internal class MacroModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + public override void ConfigureMappings(IMapperConfiguration config) { //FROM IMacro TO EntityBasic config.CreateMap() diff --git a/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs b/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs index afadf90902..df46ecdb76 100644 --- a/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs @@ -1,19 +1,14 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Web; using System.Web.Mvc; using System.Web.Routing; using AutoMapper; -using umbraco; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Mapping; -using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Trees; @@ -25,13 +20,28 @@ namespace Umbraco.Web.Models.Mapping /// internal class MediaModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + private readonly ILocalizedTextService _textService; + private readonly IUserService _userService; + private readonly IDataTypeService _dataTypeService; + private readonly IMediaService _mediaService; + private readonly ILogger _logger; + + public MediaModelMapper(IUserService userService, ILocalizedTextService textService, IDataTypeService dataTypeService, IMediaService mediaService, ILogger logger) + { + _userService = userService; + _textService = textService; + _dataTypeService = dataTypeService; + _mediaService = mediaService; + _logger = logger; + } + + public override void ConfigureMappings(IMapperConfiguration config) { //FROM IMedia TO MediaItemDisplay config.CreateMap() .ForMember( dto => dto.Owner, - expression => expression.ResolveUsing(new OwnerResolver(applicationContext.Services.UserService))) + expression => expression.ResolveUsing(new OwnerResolver(_userService))) .ForMember( dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) @@ -53,17 +63,14 @@ namespace Umbraco.Web.Models.Mapping .ForMember(display => display.Updater, expression => expression.Ignore()) .ForMember(display => display.Alias, expression => expression.Ignore()) .ForMember(display => display.IsContainer, expression => expression.Ignore()) - .ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver(applicationContext.Services.TextService))) - .AfterMap((media, display) => AfterMap( - media, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService, - applicationContext.ProfilingLogger.Logger, - applicationContext.Services.MediaService)); + .ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver(_textService))) + .AfterMap((media, display) => AfterMap(media, display, _dataTypeService, _textService, _logger, _mediaService)); //FROM IMedia TO ContentItemBasic config.CreateMap>() .ForMember( dto => dto.Owner, - expression => expression.ResolveUsing(new OwnerResolver(applicationContext.Services.UserService))) + expression => expression.ResolveUsing(new OwnerResolver(_userService))) .ForMember( dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) @@ -81,7 +88,7 @@ namespace Umbraco.Web.Models.Mapping config.CreateMap>() .ForMember( dto => dto.Owner, - expression => expression.ResolveUsing(new OwnerResolver(applicationContext.Services.UserService))) + expression => expression.ResolveUsing(new OwnerResolver(_userService))) .ForMember(x => x.Published, expression => expression.Ignore()) .ForMember(x => x.Updater, expression => expression.Ignore()) .ForMember(x => x.Icon, expression => expression.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs index febcc997e5..af14b2324d 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs @@ -11,9 +11,7 @@ using Umbraco.Core.Models.Mapping; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; -using umbraco; using System.Linq; -using Umbraco.Core.PropertyEditors; using Umbraco.Core.Security; using Umbraco.Web.Trees; @@ -24,7 +22,20 @@ namespace Umbraco.Web.Models.Mapping /// internal class MemberModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + private readonly IUserService _userService; + private readonly ILocalizedTextService _textService; + private readonly IMemberService _memberService; + private readonly IMemberTypeService _memberTypeService; + + public MemberModelMapper(IUserService userService, ILocalizedTextService textService, IMemberTypeService memberTypeService, IMemberService memberService) + { + _userService = userService; + _textService = textService; + _memberTypeService = memberTypeService; + _memberService = memberService; + } + + public override void ConfigureMappings(IMapperConfiguration config) { //FROM MembershipUser TO MediaItemDisplay - used when using a non-umbraco membership provider config.CreateMap() @@ -64,7 +75,7 @@ namespace Umbraco.Web.Models.Mapping config.CreateMap() .ForMember( dto => dto.Owner, - expression => expression.ResolveUsing(new OwnerResolver(applicationContext.Services.UserService))) + expression => expression.ResolveUsing(new OwnerResolver(_userService))) .ForMember( dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) @@ -76,11 +87,11 @@ namespace Umbraco.Web.Models.Mapping expression => expression.MapFrom(content => content.ContentType.Name)) .ForMember(display => display.Properties, expression => expression.Ignore()) .ForMember(display => display.Tabs, - expression => expression.ResolveUsing(new MemberTabsAndPropertiesResolver(applicationContext.Services.TextService))) + expression => expression.ResolveUsing(new MemberTabsAndPropertiesResolver(_textService))) .ForMember(display => display.MemberProviderFieldMapping, expression => expression.ResolveUsing()) .ForMember(display => display.MembershipScenario, - expression => expression.ResolveUsing(new MembershipScenarioMappingResolver(new Lazy(() => applicationContext.Services.MemberTypeService)))) + expression => expression.ResolveUsing(new MembershipScenarioMappingResolver(new Lazy(() => _memberTypeService)))) .ForMember(display => display.Notifications, expression => expression.Ignore()) .ForMember(display => display.Errors, expression => expression.Ignore()) .ForMember(display => display.Published, expression => expression.Ignore()) @@ -90,13 +101,13 @@ namespace Umbraco.Web.Models.Mapping .ForMember(display => display.Trashed, expression => expression.Ignore()) .ForMember(display => display.IsContainer, expression => expression.Ignore()) .ForMember(display => display.TreeNodeUrl, expression => expression.Ignore()) - .AfterMap((member, display) => MapGenericCustomProperties(applicationContext.Services.MemberService, member, display, applicationContext.Services.TextService)); + .AfterMap((member, display) => MapGenericCustomProperties(_memberService, member, display, _textService)); //FROM IMember TO MemberBasic config.CreateMap() .ForMember( dto => dto.Owner, - expression => expression.ResolveUsing(new OwnerResolver(applicationContext.Services.UserService))) + expression => expression.ResolveUsing(new OwnerResolver(_userService))) .ForMember( dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) @@ -149,7 +160,7 @@ namespace Umbraco.Web.Models.Mapping config.CreateMap>() .ForMember( dto => dto.Owner, - expression => expression.ResolveUsing(new OwnerResolver(applicationContext.Services.UserService))) + expression => expression.ResolveUsing(new OwnerResolver(_userService))) .ForMember(x => x.Published, expression => expression.Ignore()) .ForMember(x => x.Updater, expression => expression.Ignore()) .ForMember(x => x.Icon, expression => expression.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs b/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs index e7c53a9015..c53a7c48b3 100644 --- a/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs @@ -5,6 +5,7 @@ using System.Linq; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Models.Mapping @@ -12,13 +13,13 @@ namespace Umbraco.Web.Models.Mapping internal class PropertyTypeGroupResolver : ValueResolver>> where TPropertyType : PropertyTypeDisplay, new() { - private readonly ApplicationContext _applicationContext; private readonly PropertyEditorCollection _propertyEditors; + private readonly IDataTypeService _dataTypeService; - public PropertyTypeGroupResolver(ApplicationContext applicationContext, PropertyEditorCollection propertyEditors) + public PropertyTypeGroupResolver(PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService) { - _applicationContext = applicationContext; _propertyEditors = propertyEditors; + _dataTypeService = dataTypeService; } /// @@ -198,7 +199,7 @@ namespace Umbraco.Web.Models.Mapping foreach (var p in properties.Where(x => x.DataTypeDefinitionId != 0).OrderBy(x => x.SortOrder)) { var propertyEditor = _propertyEditors[p.PropertyEditorAlias]; - var preValues = _applicationContext.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(p.DataTypeDefinitionId); + var preValues = _dataTypeService.GetPreValuesCollectionByDataTypeId(p.DataTypeDefinitionId); if (propertyEditor == null) throw new InvalidOperationException("No property editor could be resolved with the alias: " + p.PropertyEditorAlias + ", ensure all packages are installed correctly."); diff --git a/src/Umbraco.Web/Models/Mapping/RelationModelMapper.cs b/src/Umbraco.Web/Models/Mapping/RelationModelMapper.cs index 11b435a21d..8b15f18f30 100644 --- a/src/Umbraco.Web/Models/Mapping/RelationModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/RelationModelMapper.cs @@ -1,5 +1,4 @@ using AutoMapper; -using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Mapping; using Relation = Umbraco.Web.Models.ContentEditing.Relation; @@ -9,7 +8,7 @@ namespace Umbraco.Web.Models.Mapping { internal class RelationModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + public override void ConfigureMappings(IMapperConfiguration config) { //FROM IRelationType TO RelationType config.CreateMap(); diff --git a/src/Umbraco.Web/Models/Mapping/SectionModelMapper.cs b/src/Umbraco.Web/Models/Mapping/SectionModelMapper.cs index e72db45bdf..61cd649185 100644 --- a/src/Umbraco.Web/Models/Mapping/SectionModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/SectionModelMapper.cs @@ -1,21 +1,26 @@ using System.Collections.Generic; using AutoMapper; -using Umbraco.Core; using Umbraco.Core.Services; using Umbraco.Core.Models.Mapping; using Umbraco.Web.Models.ContentEditing; -using umbraco; namespace Umbraco.Web.Models.Mapping { internal class SectionModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + private readonly ILocalizedTextService _textService; + + public SectionModelMapper(ILocalizedTextService textService) + { + _textService = textService; + } + + public override void ConfigureMappings(IMapperConfiguration config) { config.CreateMap() .ForMember( dto => dto.Name, - expression => expression.MapFrom(section => applicationContext.Services.TextService.Localize("sections/" + section.Alias, (IDictionary)null))) + expression => expression.MapFrom(section => _textService.Localize("sections/" + section.Alias, (IDictionary)null))) .ReverseMap(); //backwards too! } } diff --git a/src/Umbraco.Web/Models/Mapping/TabModelMapper.cs b/src/Umbraco.Web/Models/Mapping/TabModelMapper.cs index 466b123df7..31749b3a09 100644 --- a/src/Umbraco.Web/Models/Mapping/TabModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/TabModelMapper.cs @@ -1,5 +1,4 @@ using AutoMapper; -using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Mapping; @@ -7,7 +6,7 @@ namespace Umbraco.Web.Models.Mapping { internal class TabModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + public override void ConfigureMappings(IMapperConfiguration config) { config.CreateMap(); } diff --git a/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs b/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs index 11bc2e8419..ea39490f3a 100644 --- a/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs @@ -4,23 +4,30 @@ using Umbraco.Core; using Umbraco.Core.Models.Mapping; using Umbraco.Core.Models.Membership; using Umbraco.Web.Models.ContentEditing; -using umbraco; using Umbraco.Core.Models; using Umbraco.Core.Models.Identity; using Umbraco.Core.Security; +using Umbraco.Core.Services; namespace Umbraco.Web.Models.Mapping { internal class UserModelMapper : ModelMapperConfiguration { - public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext) + private readonly ILocalizedTextService _textService; + + public UserModelMapper(ILocalizedTextService textService) + { + _textService = textService; + } + + public override void ConfigureMappings(IMapperConfiguration config) { config.CreateMap() .ForMember(detail => detail.UserId, opt => opt.MapFrom(user => GetIntId(user.Id))) .ForMember(detail => detail.UserType, opt => opt.MapFrom(user => user.UserType.Alias)) .ForMember(detail => detail.StartContentId, opt => opt.MapFrom(user => user.StartContentId)) .ForMember(detail => detail.StartMediaId, opt => opt.MapFrom(user => user.StartMediaId)) - .ForMember(detail => detail.Culture, opt => opt.MapFrom(user => user.GetUserCulture(applicationContext.Services.TextService))) + .ForMember(detail => detail.Culture, opt => opt.MapFrom(user => user.GetUserCulture(_textService))) .ForMember( detail => detail.EmailHash, opt => opt.MapFrom(user => user.Email.ToLowerInvariant().Trim().ToMd5())) @@ -50,7 +57,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(detail => detail.StartContentNode, opt => opt.MapFrom(user => user.StartContentId)) .ForMember(detail => detail.StartMediaNode, opt => opt.MapFrom(user => user.StartMediaId)) .ForMember(detail => detail.Username, opt => opt.MapFrom(user => user.Username)) - .ForMember(detail => detail.Culture, opt => opt.MapFrom(user => user.GetUserCulture(applicationContext.Services.TextService))) + .ForMember(detail => detail.Culture, opt => opt.MapFrom(user => user.GetUserCulture(_textService))) .ForMember(detail => detail.SessionId, opt => opt.MapFrom(user => user.SecurityStamp.IsNullOrWhiteSpace() ? Guid.NewGuid().ToString("N") : user.SecurityStamp)); } diff --git a/src/Umbraco.Web/Models/ProfileModel.cs b/src/Umbraco.Web/Models/ProfileModel.cs index 118f9a9f7a..a7b36e50ab 100644 --- a/src/Umbraco.Web/Models/ProfileModel.cs +++ b/src/Umbraco.Web/Models/ProfileModel.cs @@ -34,10 +34,10 @@ namespace Umbraco.Web.Models MemberProperties = new List(); if (doLookup) { - var helper = new MembershipHelper(ApplicationContext.Current, new HttpContextWrapper(HttpContext.Current)); + var helper = new MembershipHelper(new HttpContextWrapper(HttpContext.Current)); var model = helper.GetCurrentMemberProfileModel(); MemberProperties = model.MemberProperties; - } + } } [Obsolete("Do not use this ctor as it will perform business logic lookups. Use the MembershipHelper.CreateProfileModel or the static ProfileModel.CreateModel() to create an empty model.")] @@ -58,7 +58,7 @@ namespace Umbraco.Web.Models /// /// The member's member type alias - /// + /// [ReadOnly(true)] public string MemberTypeAlias { get; set; } diff --git a/src/Umbraco.Web/Models/PublishedProperty.cs b/src/Umbraco.Web/Models/PublishedProperty.cs index 916011239a..e39b704f6b 100644 --- a/src/Umbraco.Web/Models/PublishedProperty.cs +++ b/src/Umbraco.Web/Models/PublishedProperty.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Models Func map) { var propertyEditors = Current.PropertyEditors; - var dataTypeService = ApplicationContext.Current.Services.DataTypeService; + var dataTypeService = Current.Services.DataTypeService; return propertyTypes.Select(x => { diff --git a/src/Umbraco.Web/Models/RegisterModel.cs b/src/Umbraco.Web/Models/RegisterModel.cs index 237f6d7845..fcec6677b3 100644 --- a/src/Umbraco.Web/Models/RegisterModel.cs +++ b/src/Umbraco.Web/Models/RegisterModel.cs @@ -2,10 +2,8 @@ using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; -using System.Linq; using System.Web; using System.Web.Mvc; -using umbraco.cms.businesslogic.member; using Umbraco.Core; using Umbraco.Web.Security; @@ -15,13 +13,12 @@ namespace Umbraco.Web.Models public class RegisterModel : PostRedirectModel { /// - /// Creates a new empty RegisterModel + /// Creates a new empty RegisterModel. /// /// public static RegisterModel CreateModel() { - var model = new RegisterModel(false); - return model; + return new RegisterModel(false); } private RegisterModel(bool doLookup) @@ -32,9 +29,9 @@ namespace Umbraco.Web.Models MemberProperties = new List(); LoginOnSuccess = true; CreatePersistentLoginCookie = true; - if (doLookup && HttpContext.Current != null && ApplicationContext.Current != null) + if (doLookup && HttpContext.Current != null) { - var helper = new MembershipHelper(ApplicationContext.Current, new HttpContextWrapper(HttpContext.Current)); + var helper = new MembershipHelper(new HttpContextWrapper(HttpContext.Current)); var model = helper.CreateRegistrationModel(MemberTypeAlias); MemberProperties = model.MemberProperties; } @@ -43,8 +40,7 @@ namespace Umbraco.Web.Models [Obsolete("Do not use this ctor as it will perform business logic lookups. Use the MembershipHelper.CreateRegistrationModel or the static RegisterModel.CreateModel() to create an empty model.")] public RegisterModel() : this(true) - { - } + { } [Required] [RegularExpression(@"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", @@ -55,7 +51,7 @@ namespace Umbraco.Web.Models /// Returns the member properties /// public List MemberProperties { get; set; } - + /// /// The member type alias to use to register the member /// @@ -72,11 +68,11 @@ namespace Umbraco.Web.Models /// [Required] public string Password { get; set; } - + [ReadOnly(true)] [Obsolete("This is no longer used and will be removed from the codebase in future versions")] public bool RedirectOnSucces { get; set; } - + /// /// The username of the model, if UsernameIsEmail is true then this is ignored. /// @@ -86,7 +82,7 @@ namespace Umbraco.Web.Models /// Flag to determine if the username should be the email address, if true then the Username property is ignored /// public bool UsernameIsEmail { get; set; } - + /// /// Specifies if the member should be logged in if they are succesfully created /// @@ -107,6 +103,5 @@ namespace Umbraco.Web.Models return RegisterModel.CreateModel(); } } - } } diff --git a/src/Umbraco.Web/Models/Trees/MenuItem.cs b/src/Umbraco.Web/Models/Trees/MenuItem.cs index b25918fbf6..f3373bda2e 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItem.cs +++ b/src/Umbraco.Web/Models/Trees/MenuItem.cs @@ -195,7 +195,7 @@ namespace Umbraco.Web.Models.Trees if (attempt2) { var view = attempt2.Result; - var textService = ApplicationContext.Current.Services.TextService; + var textService = Current.Services.TextService; LaunchDialogView(view, textService.Localize("defaultdialogs/confirmdelete") + " '" + (item == null ? "" : item.Name) + "' ?"); } } @@ -221,7 +221,7 @@ namespace Umbraco.Web.Models.Trees if (attempt2) { var view = attempt2.Result; - var textService = ApplicationContext.Current.Services.TextService; + var textService = Current.Services.TextService; LaunchDialogView(view, textService.Localize("defaultdialogs/confirmdelete") + " '" + path + "' ?"); } } diff --git a/src/Umbraco.Web/Mvc/AdminTokenAuthorizeAttribute.cs b/src/Umbraco.Web/Mvc/AdminTokenAuthorizeAttribute.cs index dc8aa15f6a..8b06f2aadf 100644 --- a/src/Umbraco.Web/Mvc/AdminTokenAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Mvc/AdminTokenAuthorizeAttribute.cs @@ -1,13 +1,12 @@ using System; -using System.Linq; using System.Net.Http.Headers; using System.Text; using System.Text.RegularExpressions; using System.Web; using System.Web.Mvc; -using umbraco; using Umbraco.Core; using Umbraco.Core.Logging; +using Umbraco.Core.Services; namespace Umbraco.Web.Mvc { @@ -16,56 +15,59 @@ namespace Umbraco.Web.Mvc /// public sealed class AdminTokenAuthorizeAttribute : AuthorizeAttribute { - private readonly ApplicationContext _applicationContext; + // see note in HttpInstallAuthorizeAttribute + private readonly IUserService _userService; + private readonly IRuntimeState _runtimeState; + + private IUserService UserService => _userService ?? Current.Services.UserService; + + private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS /// - /// - public AdminTokenAuthorizeAttribute(ApplicationContext appContext) + /// + /// + public AdminTokenAuthorizeAttribute(IUserService userService, IRuntimeState runtimeState) { - if (appContext == null) throw new ArgumentNullException("appContext"); - _applicationContext = appContext; + if (userService == null) throw new ArgumentNullException(nameof(userService)); + if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); + _userService = userService; + _runtimeState = runtimeState; } public AdminTokenAuthorizeAttribute() - { - } - - private ApplicationContext GetApplicationContext() - { - return _applicationContext ?? ApplicationContext.Current; - } + { } public const string AuthorizationType = "AToken"; /// /// Used to return the full value that needs to go in the Authorization header /// - /// + /// /// - public static string GetAuthHeaderTokenVal(ApplicationContext appContext) + public static string GetAuthHeaderTokenVal(IUserService userService) { - return string.Format("{0} {1}", AuthorizationType, GetAuthHeaderVal(appContext)); + return $"{AuthorizationType} {GetAuthHeaderVal(userService)}"; } - public static AuthenticationHeaderValue GetAuthenticationHeaderValue(ApplicationContext appContext) + public static AuthenticationHeaderValue GetAuthenticationHeaderValue(IUserService userService) { - return new AuthenticationHeaderValue(AuthorizationType, GetAuthHeaderVal(appContext)); + return new AuthenticationHeaderValue(AuthorizationType, GetAuthHeaderVal(userService)); } - private static string GetAuthHeaderVal(ApplicationContext appContext) + private static string GetAuthHeaderVal(IUserService userService) { - var admin = appContext.Services.UserService.GetUserById(0); + var admin = userService.GetUserById(0); - var token = string.Format("{0}u____u{1}u____u{2}", admin.Email, admin.Username, admin.RawPasswordValue); + var token = $"{admin.Email}u____u{admin.Username}u____u{admin.RawPasswordValue}"; var encrypted = token.EncryptWithMachineKey(); var bytes = Encoding.UTF8.GetBytes(encrypted); var base64 = Convert.ToBase64String(bytes); - return string.Format("val=\"{0}\"", base64); + return $"val=\"{base64}\""; } - + /// /// Ensures that the user must be in the Administrator or the Install role /// @@ -73,14 +75,12 @@ namespace Umbraco.Web.Mvc /// protected override bool AuthorizeCore(HttpContextBase httpContext) { - if (httpContext == null) throw new ArgumentNullException("httpContext"); + if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); - var appContext = GetApplicationContext(); + // we need to that the app is configured and that a user is logged in + if (RuntimeState.Level != RuntimeLevel.Run) return false; - //we need to that the app is configured and that a user is logged in - if (appContext.IsConfigured == false) return false; - - //need the auth header + // need the auth header if (httpContext.Request.Headers["Authorization"] == null || httpContext.Request.Headers["Authorization"].IsNullOrWhiteSpace()) return false; var header = httpContext.Request.Headers["Authorization"]; @@ -90,7 +90,7 @@ namespace Umbraco.Web.Mvc if (keyVal.Count != 1) return false; if (keyVal[0].Groups.Count != 2) return false; - var admin = appContext.Services.UserService.GetUserById(0); + var admin = UserService.GetUserById(0); if (admin == null) return false; try diff --git a/src/Umbraco.Web/Mvc/ContentModelBinder.cs b/src/Umbraco.Web/Mvc/ContentModelBinder.cs index 5e012a422f..f4426f3fb8 100644 --- a/src/Umbraco.Web/Mvc/ContentModelBinder.cs +++ b/src/Umbraco.Web/Mvc/ContentModelBinder.cs @@ -148,7 +148,7 @@ namespace Umbraco.Web.Mvc if (context == null) AppDomain.Unload(AppDomain.CurrentDomain); else - ApplicationContext.Current.RestartApplicationPool(new HttpContextWrapper(context)); + Current.RestartAppPool(new HttpContextWrapper(context)); } throw new ModelBindingException(msg.ToString()); diff --git a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs index 6406c7ea8a..cce9acfb14 100644 --- a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs +++ b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs @@ -78,18 +78,13 @@ namespace Umbraco.Web.Mvc /// /// Exposes the UmbracoContext /// - protected UmbracoContext UmbracoContext - { - get { return _umbracoContext ?? (_umbracoContext = UmbracoContext.Current); } - } + protected UmbracoContext UmbracoContext => _umbracoContext ?? (_umbracoContext = UmbracoContext.Current); /// /// Exposes an UmbracoHelper /// - protected UmbracoHelper Umbraco - { - get { return _helper ?? (_helper = new UmbracoHelper(UmbracoContext.Current)); } - } + protected UmbracoHelper Umbraco => _helper + ?? (_helper = new UmbracoHelper(Current.UmbracoContext, Current.Services, Current.ApplicationCache)); public override void OnActionExecuted(ActionExecutedContext filterContext) { diff --git a/src/Umbraco.Web/Mvc/MemberAuthorizeAttribute.cs b/src/Umbraco.Web/Mvc/MemberAuthorizeAttribute.cs index 71ebfb8288..a9bfc34bad 100644 --- a/src/Umbraco.Web/Mvc/MemberAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Mvc/MemberAuthorizeAttribute.cs @@ -17,13 +17,10 @@ namespace Umbraco.Web.Mvc /// public sealed class MemberAuthorizeAttribute : AuthorizeAttribute { - + // see note in HttpInstallAuthorizeAttribute private readonly UmbracoContext _umbracoContext; - private UmbracoContext GetUmbracoContext() - { - return _umbracoContext ?? UmbracoContext.Current; - } + private UmbracoContext UmbracoContext => _umbracoContext ?? Current.UmbracoContext; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS @@ -83,7 +80,7 @@ namespace Umbraco.Web.Mvc } } - return GetUmbracoContext().Security.IsMemberAuthorized(AllowAll, + return UmbracoContext.Security.IsMemberAuthorized(AllowAll, AllowType.Split(','), AllowGroup.Split(','), members); diff --git a/src/Umbraco.Web/Mvc/PluginController.cs b/src/Umbraco.Web/Mvc/PluginController.cs index 48608fc9a1..168210faa2 100644 --- a/src/Umbraco.Web/Mvc/PluginController.cs +++ b/src/Umbraco.Web/Mvc/PluginController.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Concurrent; using System.Web.Mvc; +using LightInject; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; @@ -10,139 +12,109 @@ using Umbraco.Web.WebApi; namespace Umbraco.Web.Mvc { /// - /// A base class for all plugin controllers to inherit from + /// Provides a base class for plugin controllers. /// public abstract class PluginController : Controller { - /// - /// stores the metadata about plugin controllers - /// - private static readonly ConcurrentDictionary MetadataStorage = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary MetadataStorage + = new ConcurrentDictionary(); - private UmbracoHelper _umbracoHelper; + private UmbracoHelper _umbracoHelper; + + // for debugging purposes + internal Guid InstanceId { get; } = Guid.NewGuid(); + + // note + // properties marked as [Inject] below will be property-injected (vs constructor-injected) in + // order to keep the constuctor as light as possible, so that ppl implementing eg a SurfaceController + // don't need to implement complex constructors + need to refactor them each time we change ours. + // this means that these properties have a setter. + // what can go wrong? /// - /// Default constructor + /// Gets or sets the Umbraco context. /// - /// - protected PluginController(UmbracoContext umbracoContext) - { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); - UmbracoContext = umbracoContext; - InstanceId = Guid.NewGuid(); - } + [Inject] + public virtual UmbracoContext UmbracoContext { get; set; } - protected PluginController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) + /// + /// Gets or sets the database context. + /// + [Inject] + public DatabaseContext DatabaseContext { get; set; } + + /// + /// Gets or sets the services context. + /// + [Inject] + public ServiceContext Services { get; set; } + + /// + /// Gets or sets the application cache. + /// + [Inject] + public CacheHelper ApplicationCache { get; set; } + + /// + /// Gets or sets the logger. + /// + [Inject] + public ILogger Logger { get; set; } + + /// + /// Gets or sets the profiling logger. + /// + [Inject] + public ProfilingLogger ProfilingLogger { get; set; } + + /// + /// Gets the membership helper. + /// + public MembershipHelper Members => Umbraco.MembershipHelper; + + /// + /// Gets the Umbraco helper. + /// + public UmbracoHelper Umbraco { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); - if (umbracoHelper == null) throw new ArgumentNullException("umbracoHelper"); - UmbracoContext = umbracoContext; - InstanceId = Guid.NewGuid(); - _umbracoHelper = umbracoHelper; + get + { + return _umbracoHelper + ?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services, ApplicationCache)); + } + internal set // tests + { + _umbracoHelper = value; + } } /// - /// Useful for debugging + /// Gets metadata for this instance. /// - internal Guid InstanceId { get; private set; } + internal PluginControllerMetadata Metadata => GetMetadata(GetType()); /// - /// Returns the MemberHelper instance + /// Gets metadata for a controller type. /// - public MembershipHelper Members + /// The controller type. + /// Metadata for the controller type. + internal static PluginControllerMetadata GetMetadata(Type controllerType) { - get { return Umbraco.MembershipHelper; } - } + return MetadataStorage.GetOrAdd(controllerType, type => + { + // plugin controller? back-office controller? + var pluginAttribute = controllerType.GetCustomAttribute(false); + var backOfficeAttribute = controllerType.GetCustomAttribute(true); - /// - /// Returns an UmbracoHelper object - /// - public virtual UmbracoHelper Umbraco - { - get { return _umbracoHelper ?? (_umbracoHelper = new UmbracoHelper(UmbracoContext)); } - } - - /// - /// Returns an ILogger - /// - public ILogger Logger - { - get { return ProfilingLogger.Logger; } - } - - /// - /// Returns a ProfilingLogger - /// - public virtual ProfilingLogger ProfilingLogger - { - get { return UmbracoContext.Application.ProfilingLogger; } - } - - /// - /// Returns the current UmbracoContext - /// - public virtual UmbracoContext UmbracoContext { get; private set; } - - /// - /// Returns the current ApplicationContext - /// - public virtual ApplicationContext ApplicationContext - { - get { return UmbracoContext.Application; } - } - - /// - /// Returns a ServiceContext - /// - public ServiceContext Services - { - get { return ApplicationContext.Services; } - } - - /// - /// Returns a DatabaseContext - /// - public DatabaseContext DatabaseContext - { - get { return ApplicationContext.DatabaseContext; } - } - - /// - /// Returns the metadata for this instance - /// - internal PluginControllerMetadata Metadata - { - get { return GetMetadata(this.GetType()); } - } - - /// - /// Returns the metadata for a PluginController - /// - /// - /// - internal static PluginControllerMetadata GetMetadata(Type type) - { - - return MetadataStorage.GetOrAdd(type, type1 => + return new PluginControllerMetadata { - var pluginAttribute = type.GetCustomAttribute(false); - //check if any inherited class of this type contains the IsBackOffice attribute - var backOfficeAttribute = type.GetCustomAttribute(true); - - var meta = new PluginControllerMetadata() - { - AreaName = pluginAttribute == null ? null : pluginAttribute.AreaName, - ControllerName = ControllerExtensions.GetControllerName(type), - ControllerNamespace = type.Namespace, - ControllerType = type, - IsBackOffice = backOfficeAttribute != null - }; - - MetadataStorage.TryAdd(type, meta); - - return meta; - }); - + AreaName = pluginAttribute?.AreaName, + ControllerName = ControllerExtensions.GetControllerName(controllerType), + ControllerNamespace = controllerType.Namespace, + ControllerType = controllerType, + IsBackOffice = backOfficeAttribute != null + }; + }); } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Mvc/RenderMvcController.cs b/src/Umbraco.Web/Mvc/RenderMvcController.cs index b9ec03d394..055a6aedf5 100644 --- a/src/Umbraco.Web/Mvc/RenderMvcController.cs +++ b/src/Umbraco.Web/Mvc/RenderMvcController.cs @@ -1,59 +1,40 @@ using System; using System.Web.Mvc; +using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; -using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Services; using Umbraco.Web.Models; using Umbraco.Web.Routing; namespace Umbraco.Web.Mvc { - /// - /// The default controller to render front-end requests + /// Represents the default front-end rendering controller. /// [PreRenderViewActionFilter] public class RenderMvcController : UmbracoController, IRenderMvcController { - - public RenderMvcController() - : base() - { - ActionInvoker = new RenderActionInvoker(); - } - - public RenderMvcController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) - : base(umbracoContext, umbracoHelper) - { - ActionInvoker = new RenderActionInvoker(); - } - - public RenderMvcController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - ActionInvoker = new RenderActionInvoker(); - } - private PublishedContentRequest _publishedContentRequest; - /// - /// Returns the current UmbracoContext - /// - public override UmbracoContext UmbracoContext + public RenderMvcController() { - get { return PublishedContentRequest.RoutingContext.UmbracoContext; } + ActionInvoker = new RenderActionInvoker(); } /// - /// Returns the Current published content item for rendering the content + /// Gets the Umbraco context. /// - protected IPublishedContent CurrentPage - { - get { return PublishedContentRequest.PublishedContent; } - } + public override UmbracoContext UmbracoContext => PublishedContentRequest.RoutingContext.UmbracoContext; /// - /// Returns the current PublishedContentRequest + /// Gets the current content item. + /// + protected IPublishedContent CurrentPage => PublishedContentRequest.PublishedContent; + + /// + /// Gets the current published content request. /// protected internal virtual PublishedContentRequest PublishedContentRequest { @@ -71,30 +52,25 @@ namespace Umbraco.Web.Mvc } /// - /// Checks to make sure the physical view file exists on disk + /// Ensures that a physical view file exists on disk. /// - /// - /// + /// The view name. protected bool EnsurePhsyicalViewExists(string template) { var result = ViewEngines.Engines.FindView(ControllerContext, template, null); - if (result.View == null) - { - LogHelper.Warn("No physical template file was found for template " + template); - return false; - } - return true; + if (result.View != null) return true; + + LogHelper.Warn("No physical template file was found for template " + template); + return false; } /// - /// Returns an ActionResult based on the template name found in the route values and the given model. + /// Gets an action result based on the template name found in the route values and a model. /// - /// - /// - /// - /// - /// If the template found in the route values doesn't physically exist, then an empty ContentResult will be returned. - /// + /// The type of the model. + /// The model. + /// The action result. + /// If the template found in the route values doesn't physically exist, then an empty ContentResult will be returned. protected ActionResult CurrentTemplate(T model) { var template = ControllerContext.RouteData.Values["action"].ToString(); @@ -104,7 +80,7 @@ namespace Umbraco.Web.Mvc } /// - /// The default action to render the front-end view + /// The default action to render the front-end view. /// /// /// diff --git a/src/Umbraco.Web/Mvc/RenderViewEngine.cs b/src/Umbraco.Web/Mvc/RenderViewEngine.cs index 9b1766e84c..6ae8a5d5bb 100644 --- a/src/Umbraco.Web/Mvc/RenderViewEngine.cs +++ b/src/Umbraco.Web/Mvc/RenderViewEngine.cs @@ -14,7 +14,6 @@ namespace Umbraco.Web.Mvc /// public class RenderViewEngine : ReflectedFixedRazorViewEngine { - private readonly IEnumerable _supplementedViewLocations = new[] { "/{0}.cshtml" }; //NOTE: we will make the main view location the last to be searched since if it is the first to be searched and there is both a view and a partial // view in both locations and the main view is rendering a partial view with the same name, we will get a stack overflow exception. @@ -31,7 +30,7 @@ namespace Umbraco.Web.Mvc var replaceWithUmbracoFolder = _supplementedViewLocations.ForEach(location => templateFolder + location); var replacePartialWithUmbracoFolder = _supplementedPartialViewLocations.ForEach(location => templateFolder + location); - //The Render view engine doesn't support Area's so make those blank + // the Render view engine doesn't support Area's so make those blank ViewLocationFormats = replaceWithUmbracoFolder.ToArray(); PartialViewLocationFormats = replacePartialWithUmbracoFolder.ToArray(); @@ -44,43 +43,39 @@ namespace Umbraco.Web.Mvc /// /// Ensures that the correct web.config for razor exists in the /Views folder, the partials folder exist and the ViewStartPage exists. /// - private void EnsureFoldersAndFiles() + private static void EnsureFoldersAndFiles() { var viewFolder = IOHelper.MapPath(Constants.ViewLocation); - //ensure the web.config file is in the ~/Views folder + + // ensure the web.config file is in the ~/Views folder Directory.CreateDirectory(viewFolder); - if (!File.Exists(Path.Combine(viewFolder, "web.config"))) + if (File.Exists(Path.Combine(viewFolder, "web.config")) == false) { using (var writer = File.CreateText(Path.Combine(viewFolder, "web.config"))) { writer.Write(Strings.WebConfigTemplate); } } + //auto create the partials folder var partialsFolder = Path.Combine(viewFolder, "Partials"); Directory.CreateDirectory(partialsFolder); - //We could create a _ViewStart page if it isn't there as well, but we may not allow editing of this page in the back office. + // We could create a _ViewStart page if it isn't there as well, but we may not allow editing of this page in the back office. } public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { - if (!ShouldFindView(controllerContext, false)) - { - return new ViewEngineResult(new string[] { }); - } - - return base.FindView(controllerContext, viewName, masterName, useCache); + return ShouldFindView(controllerContext, false) + ? base.FindView(controllerContext, viewName, masterName, useCache) + : new ViewEngineResult(new string[] { }); } public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) { - if (!ShouldFindView(controllerContext, true)) - { - return new ViewEngineResult(new string[] { }); - } - - return base.FindPartialView(controllerContext, partialViewName, useCache); + return ShouldFindView(controllerContext, true) + ? base.FindPartialView(controllerContext, partialViewName, useCache) + : new ViewEngineResult(new string[] { }); } /// @@ -91,24 +86,17 @@ namespace Umbraco.Web.Mvc /// /// /// - private bool ShouldFindView(ControllerContext controllerContext, bool isPartial) + private static bool ShouldFindView(ControllerContext controllerContext, bool isPartial) { var umbracoToken = controllerContext.GetDataTokenInViewContextHierarchy(Core.Constants.Web.UmbracoDataToken); - //first check if we're rendering a partial view for the back office, or surface controller, etc... - //anything that is not IUmbracoRenderModel as this should only pertain to Umbraco views. - if (isPartial && ((umbracoToken is ContentModel) == false)) - { + // first check if we're rendering a partial view for the back office, or surface controller, etc... + // anything that is not IUmbracoRenderModel as this should only pertain to Umbraco views. + if (isPartial && (umbracoToken is ContentModel == false)) return true; - } - //only find views if we're rendering the umbraco front end - if (umbracoToken is ContentModel) - { - return true; - } - - return false; + // only find views if we're rendering the umbraco front end + return umbracoToken is ContentModel; } } diff --git a/src/Umbraco.Web/Mvc/SurfaceController.cs b/src/Umbraco.Web/Mvc/SurfaceController.cs index 7cc908a69b..c65ad63721 100644 --- a/src/Umbraco.Web/Mvc/SurfaceController.cs +++ b/src/Umbraco.Web/Mvc/SurfaceController.cs @@ -1,44 +1,17 @@ using System; -using System.Web.Mvc; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; using Umbraco.Core; -using Umbraco.Web.Security; using System.Collections.Specialized; using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Web.Mvc { - /// - /// The base controller that all Presentation Add-in controllers should inherit from + /// Provides a base class for front-end add-in controllers. /// [MergeModelStateToChildAction] [MergeParentContextViewData] public abstract class SurfaceController : PluginController { - /// - /// Default constructor - /// - /// - protected SurfaceController(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - - protected SurfaceController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) - : base(umbracoContext, umbracoHelper) - { - } - - /// - /// Empty constructor, uses Singleton to resolve the UmbracoContext - /// - protected SurfaceController() - : base(UmbracoContext.Current) - { - } - /// /// Redirects to the Umbraco page with the given id /// @@ -125,12 +98,13 @@ namespace Umbraco.Web.Mvc /// /// Redirects to the currently rendered Umbraco page and passes provided querystring /// - /// + /// /// protected RedirectToUmbracoPageResult RedirectToCurrentUmbracoPage(string queryString) { return new RedirectToUmbracoPageResult(CurrentPage, queryString, UmbracoContext); } + /// /// Redirects to the currently rendered Umbraco URL /// @@ -151,7 +125,7 @@ namespace Umbraco.Web.Mvc /// protected UmbracoPageResult CurrentUmbracoPage() { - return new UmbracoPageResult(ApplicationContext.ProfilingLogger); + return new UmbracoPageResult(ProfilingLogger); } /// @@ -162,10 +136,8 @@ namespace Umbraco.Web.Mvc get { var routeDefAttempt = TryGetRouteDefinitionFromAncestorViewContexts(); - if (!routeDefAttempt.Success) - { + if (routeDefAttempt.Success == false) throw routeDefAttempt.Exception; - } var routeDef = routeDefAttempt.Result; return routeDef.PublishedContentRequest.PublishedContent; @@ -182,24 +154,16 @@ namespace Umbraco.Web.Mvc /// private Attempt TryGetRouteDefinitionFromAncestorViewContexts() { - ControllerContext currentContext = ControllerContext; + var currentContext = ControllerContext; while (currentContext != null) { var currentRouteData = currentContext.RouteData; if (currentRouteData.DataTokens.ContainsKey(Core.Constants.Web.UmbracoRouteDefinitionDataToken)) - { return Attempt.Succeed((RouteDefinition)currentRouteData.DataTokens[Core.Constants.Web.UmbracoRouteDefinitionDataToken]); - } - if (currentContext.IsChildAction) - { - //assign current context to parent - currentContext = currentContext.ParentActionViewContext; - } - else - { - //exit the loop - currentContext = null; - } + + currentContext = currentContext.IsChildAction + ? currentContext.ParentActionViewContext + : null; } return Attempt.Fail( new InvalidOperationException("Cannot find the Umbraco route definition in the route values, the request must be made in the context of an Umbraco request")); diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs index faf5d875f7..2ff090cfaa 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs @@ -5,38 +5,34 @@ using Umbraco.Core; namespace Umbraco.Web.Mvc { - /// - /// Ensures authorization is successful for a back office user + /// + /// Ensures authorization is successful for a back office user. /// public sealed class UmbracoAuthorizeAttribute : AuthorizeAttribute { - private readonly ApplicationContext _applicationContext; + // see note in HttpInstallAuthorizeAttribute private readonly UmbracoContext _umbracoContext; + private readonly IRuntimeState _runtimeState; - private ApplicationContext GetApplicationContext() - { - return _applicationContext ?? ApplicationContext.Current; - } + private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private UmbracoContext GetUmbracoContext() - { - return _umbracoContext ?? UmbracoContext.Current; - } + private UmbracoContext UmbracoContext => _umbracoContext ?? Current.UmbracoContext; - /// - /// THIS SHOULD BE ONLY USED FOR UNIT TESTS - /// - /// - public UmbracoAuthorizeAttribute(UmbracoContext umbracoContext) + /// + /// THIS SHOULD BE ONLY USED FOR UNIT TESTS + /// + /// + /// + public UmbracoAuthorizeAttribute(UmbracoContext umbracoContext, IRuntimeState runtimeState) { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); + if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); _umbracoContext = umbracoContext; - _applicationContext = _umbracoContext.Application; + _runtimeState = runtimeState; } public UmbracoAuthorizeAttribute() - { - } + { } /// /// Ensures that the user must be in the Administrator or the Install role @@ -45,21 +41,17 @@ namespace Umbraco.Web.Mvc /// protected override bool AuthorizeCore(HttpContextBase httpContext) { - if (httpContext == null) throw new ArgumentNullException("httpContext"); - + if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); + try { - var appContext = GetApplicationContext(); - var umbContext = GetUmbracoContext(); - - //we need to that the app is configured and that a user is logged in - if (!appContext.IsConfigured) - return false; - - var isLoggedIn = umbContext.Security.ValidateCurrentUser(); - return isLoggedIn; - } - catch (Exception) + // if not configured (install or upgrade) then we can continue + // otherwise we need to ensure that a user is logged in + return RuntimeState.Level == RuntimeLevel.Install + || RuntimeState.Level == RuntimeLevel.Upgrade + || UmbracoContext.Security.ValidateCurrentUser(); + } + catch (Exception) { return false; } @@ -71,9 +63,9 @@ namespace Umbraco.Web.Mvc /// protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { - filterContext.Result = (ActionResult)new HttpUnauthorizedResult("You must login to view this resource."); - - //DON'T do a FormsAuth redirect... argh!! thankfully we're running .Net 4.5 :) + filterContext.Result = new HttpUnauthorizedResult("You must login to view this resource."); + + // DON'T do a FormsAuth redirect... argh!! thankfully we're running .Net 4.5 :) filterContext.RequestContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true; } diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs index 50d580cf82..853fc336e7 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs @@ -1,16 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Umbraco.Core.Configuration; -using Umbraco.Web.Routing; -using Umbraco.Web.Security; -using umbraco.BusinessLogic; - -namespace Umbraco.Web.Mvc +namespace Umbraco.Web.Mvc { /// - /// A base MVC controller for use in the back office that ensures that every call to it authorizes the current user. + /// Provides a base class for authorized Umbraco controllers. /// /// /// This controller essentially just uses a global UmbracoAuthorizeAttribute, inheritors that require more granular control over the @@ -19,7 +10,5 @@ namespace Umbraco.Web.Mvc [UmbracoAuthorize] [DisableBrowserCache] public abstract class UmbracoAuthorizedController : UmbracoController - { - - } + { } } diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index 37d7549d05..226983c5e6 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -1,8 +1,10 @@ using System; using System.Web; using System.Web.Mvc; +using LightInject; using Microsoft.Owin; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; @@ -10,104 +12,74 @@ using Umbraco.Web.Security; namespace Umbraco.Web.Mvc { /// - /// A base controller class containing all of the Umbraco objects as properties that a developer requires + /// Provides a base class for Umbraco controllers. /// public abstract class UmbracoController : Controller { - protected UmbracoController(UmbracoContext umbracoContext) - { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); - UmbracoContext = umbracoContext; - } + private UmbracoHelper _umbracoHelper; - protected UmbracoController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) - { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); - if (umbracoHelper == null) throw new ArgumentNullException("umbracoHelper"); - UmbracoContext = umbracoContext; - _umbraco = umbracoHelper; - } + // for debugging purposes + internal Guid InstanceId { get; } = Guid.NewGuid(); - protected UmbracoController() - : this(UmbracoContext.Current) - { - - } - - protected IOwinContext OwinContext - { - get { return Request.GetOwinContext(); } - } - - private UmbracoHelper _umbraco; + // note + // properties marked as [Inject] below will be property-injected (vs constructor-injected) in + // order to keep the constuctor as light as possible, so that ppl implementing eg a SurfaceController + // don't need to implement complex constructors + need to refactor them each time we change ours. + // this means that these properties have a setter. + // what can go wrong? /// - /// Returns the MemberHelper instance + /// Gets or sets the Umbraco context. /// - public MembershipHelper Members - { - get { return Umbraco.MembershipHelper; } - } + [Inject] + public virtual UmbracoContext UmbracoContext { get; set; } /// - /// Returns an UmbracoHelper object + /// Gets or sets the database context. /// - public virtual UmbracoHelper Umbraco - { - get { return _umbraco ?? (_umbraco = new UmbracoHelper(UmbracoContext)); } - } + [Inject] + public DatabaseContext DatabaseContext { get; set; } /// - /// Returns an ILogger + /// Gets or sets the services context. /// - public ILogger Logger - { - get { return ProfilingLogger.Logger; } - } + [Inject] + public ServiceContext Services { get; set; } /// - /// Returns a ProfilingLogger + /// Gets or sets the application cache. /// - public virtual ProfilingLogger ProfilingLogger - { - get { return UmbracoContext.Application.ProfilingLogger; } - } + [Inject] + public CacheHelper ApplicationCache { get; set; } /// - /// Returns the current UmbracoContext + /// Gets or sets the logger. /// - public virtual UmbracoContext UmbracoContext { get; private set; } + [Inject] + public ILogger Logger { get; set; } /// - /// Returns the current ApplicationContext + /// Gets or sets the profiling logger. /// - public virtual ApplicationContext ApplicationContext - { - get { return UmbracoContext.Application; } - } + [Inject] + public ProfilingLogger ProfilingLogger { get; set; } + + protected IOwinContext OwinContext => Request.GetOwinContext(); /// - /// Returns a ServiceContext + /// Gets the membership helper. /// - public ServiceContext Services - { - get { return ApplicationContext.Services; } - } + public MembershipHelper Members => Umbraco.MembershipHelper; /// - /// Returns a DatabaseContext + /// Gets the Umbraco helper. /// - public DatabaseContext DatabaseContext - { - get { return ApplicationContext.DatabaseContext; } - } + public UmbracoHelper Umbraco => _umbracoHelper + ?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services, ApplicationCache)); /// - /// Returns the WebSecurity instance + /// Gets the web security helper. /// - public virtual WebSecurity Security - { - get { return UmbracoContext.Security; } - } + public virtual WebSecurity Security => UmbracoContext.Security; } } \ No newline at end of file diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index 6ff1bf9ff8..f3df6e40ca 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -3,10 +3,13 @@ using System.Text; using System.Web; using System.Web.Mvc; using System.Web.WebPages; +using LightInject; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Services; using Umbraco.Web.Models; using Umbraco.Web.Routing; using Umbraco.Web.Security; @@ -20,25 +23,43 @@ namespace Umbraco.Web.Mvc { private UmbracoContext _umbracoContext; private UmbracoHelper _helper; - private MembershipHelper _membershipHelper; + + // note + // properties marked as [Inject] below will be property-injected (vs constructor-injected) since + // we have no control over the view constructor (generated by eg the Razor engine). + // this means that these properties have a setter. + // what can go wrong? /// - /// Gets the current . + /// Gets or sets the database context. /// - // always try to return the context from the data tokens just in case its a custom context and not - // using the Current.UmbracoContext. Fallback to that singleton if necessary, the only reason this - // should ever happen is is someone is rendering a page that inherits from this class and are rendering - // it outside of the normal Umbraco routing process. Very unlikely. - public UmbracoContext UmbracoContext => _umbracoContext ?? - (_umbracoContext = ViewContext.GetUmbracoContext() ?? Current.UmbracoContext); + [Inject] + public ServiceContext Services { get; set; } /// - /// Gets the current . + /// Gets or sets the application cache. /// - public ApplicationContext ApplicationContext => UmbracoContext.Application; + [Inject] + public CacheHelper ApplicationCache { get; set; } + + // fixme + // previously, Services and ApplicationCache would derive from UmbracoContext.Application, which + // was an ApplicationContext - so that everything derived from UmbracoContext. + // UmbracoContext is fetched from the data tokens, thus allowing the view to be rendered with a + // custom context and NOT the Current.UmbracoContext - eg outside the normal Umbraco routing + // process. + // leaving it as-it for the time being but really - the UmbracoContext should be injected just + // like the Services & ApplicationCache properties, and have a setter for those special weird + // cases. /// - /// Gets the current . + /// Gets the Umbraco context. + /// + public UmbracoContext UmbracoContext => _umbracoContext + ?? (_umbracoContext = ViewContext.GetUmbracoContext() ?? Current.UmbracoContext); + + /// + /// Gets the public content request. /// internal PublishedContentRequest PublishedContentRequest { @@ -63,7 +84,7 @@ namespace Umbraco.Web.Mvc } /// - /// Gets an instance. + /// Gets the Umbraco helper. /// public virtual UmbracoHelper Umbraco { @@ -76,17 +97,18 @@ namespace Umbraco.Web.Mvc if (content == null && model is IContentModel) content = ((IContentModel) model).Content; _helper = content == null - ? new UmbracoHelper(UmbracoContext) - : new UmbracoHelper(UmbracoContext, content); + ? new UmbracoHelper(UmbracoContext, Services, ApplicationCache) + : new UmbracoHelper(UmbracoContext, Services, ApplicationCache, content); return _helper; } } /// - /// Gets a instance. + /// Gets the membership helper. /// - public MembershipHelper Members => _membershipHelper ?? - (_membershipHelper = new MembershipHelper(UmbracoContext)); + public MembershipHelper Members => Umbraco.MembershipHelper; + + // view logic below: /// /// Ensure that the current view context is added to the route data tokens so we can extract it if we like diff --git a/src/Umbraco.Web/NotificationServiceExtensions.cs b/src/Umbraco.Web/NotificationServiceExtensions.cs index a4ad00ee11..a5e4434f3b 100644 --- a/src/Umbraco.Web/NotificationServiceExtensions.cs +++ b/src/Umbraco.Web/NotificationServiceExtensions.cs @@ -12,31 +12,51 @@ using System.Collections.Generic; namespace Umbraco.Web { - //TODO: all of these require an UmbracoContext because currently to send the notifications we need an HttpContext, this is based on legacy code + // TODO: all of these require an UmbracoContext because currently to send the notifications we need an HttpContext, this is based on legacy code // for which probably requires updating so that these can be sent outside of the http context. internal static class NotificationServiceExtensions { - internal static void SendNotification(this INotificationService service, IUmbracoEntity entity, IAction action, ApplicationContext applicationContext) + internal static void SendNotification(this INotificationService service, IUmbracoEntity entity, IAction action) { - if (UmbracoContext.Current == null) + if (Current.UmbracoContext == null) { LogHelper.Warn(typeof(NotificationServiceExtensions), "Cannot send notifications, there is no current UmbracoContext"); return; } - service.SendNotification(entity, action, UmbracoContext.Current); + service.SendNotification(entity, action, Current.UmbracoContext); } - internal static void SendNotification(this INotificationService service, IEnumerable entities, IAction action, ApplicationContext applicationContext) + internal static void SendNotification(this INotificationService service, IEnumerable entities, IAction action) { - if (UmbracoContext.Current == null) + if (Current.UmbracoContext == null) { LogHelper.Warn(typeof(NotificationServiceExtensions), "Cannot send notifications, there is no current UmbracoContext"); return; } - service.SendNotification(entities, action, UmbracoContext.Current); + service.SendNotification(entities, action, Current.UmbracoContext); } + //internal static void SendNotification(this INotificationService service, IUmbracoEntity entity, IAction action, UmbracoContext umbracoContext) + //{ + // if (umbracoContext == null) + // { + // LogHelper.Warn(typeof(NotificationServiceExtensions), "Cannot send notifications, there is no current UmbracoContext"); + // return; + // } + // service.SendNotification(entity, action, umbracoContext); + //} + + //internal static void SendNotification(this INotificationService service, IEnumerable entities, IAction action, UmbracoContext umbracoContext) + //{ + // if (umbracoContext == null) + // { + // LogHelper.Warn(typeof(NotificationServiceExtensions), "Cannot send notifications, there is no current UmbracoContext"); + // return; + // } + // service.SendNotification(entities, action, umbracoContext); + //} + internal static void SendNotification(this INotificationService service, IUmbracoEntity entity, IAction action, UmbracoContext umbracoContext) { if (umbracoContext == null) @@ -44,20 +64,25 @@ namespace Umbraco.Web LogHelper.Warn(typeof(NotificationServiceExtensions), "Cannot send notifications, there is no current UmbracoContext"); return; } - service.SendNotification(entity, action, umbracoContext, umbracoContext.Application); + + var user = umbracoContext.Security.CurrentUser; + var userService = Current.Services.UserService; // fixme inject + + //if there is no current user, then use the admin + if (user == null) + { + LogHelper.Debug(typeof(NotificationServiceExtensions), "There is no current Umbraco user logged in, the notifications will be sent from the administrator"); + user = userService.GetUserById(0); + if (user == null) + { + LogHelper.Warn(typeof(NotificationServiceExtensions), "Noticiations can not be sent, no admin user with id 0 could be resolved"); + return; + } + } + service.SendNotification(user, entity, action, umbracoContext); } internal static void SendNotification(this INotificationService service, IEnumerable entities, IAction action, UmbracoContext umbracoContext) - { - if (umbracoContext == null) - { - LogHelper.Warn(typeof(NotificationServiceExtensions), "Cannot send notifications, there is no current UmbracoContext"); - return; - } - service.SendNotification(entities, action, umbracoContext, umbracoContext.Application); - } - - internal static void SendNotification(this INotificationService service, IUmbracoEntity entity, IAction action, UmbracoContext umbracoContext, ApplicationContext applicationContext) { if (umbracoContext == null) { @@ -66,81 +91,58 @@ namespace Umbraco.Web } var user = umbracoContext.Security.CurrentUser; + var userService = Current.Services.UserService; // fixme inject //if there is no current user, then use the admin if (user == null) { LogHelper.Debug(typeof(NotificationServiceExtensions), "There is no current Umbraco user logged in, the notifications will be sent from the administrator"); - user = applicationContext.Services.UserService.GetUserById(0); + user = userService.GetUserById(0); if (user == null) { LogHelper.Warn(typeof(NotificationServiceExtensions), "Noticiations can not be sent, no admin user with id 0 could be resolved"); return; } } - service.SendNotification(user, entity, action, umbracoContext, applicationContext); + service.SendNotification(user, entities, action, umbracoContext); } - internal static void SendNotification(this INotificationService service, IEnumerable entities, IAction action, UmbracoContext umbracoContext, ApplicationContext applicationContext) - { - if (umbracoContext == null) - { - LogHelper.Warn(typeof(NotificationServiceExtensions), "Cannot send notifications, there is no current UmbracoContext"); - return; - } - - var user = umbracoContext.Security.CurrentUser; - - //if there is no current user, then use the admin - if (user == null) - { - LogHelper.Debug(typeof(NotificationServiceExtensions), "There is no current Umbraco user logged in, the notifications will be sent from the administrator"); - user = applicationContext.Services.UserService.GetUserById(0); - if (user == null) - { - LogHelper.Warn(typeof(NotificationServiceExtensions), "Noticiations can not be sent, no admin user with id 0 could be resolved"); - return; - } - } - service.SendNotification(user, entities, action, umbracoContext, applicationContext); - } - - internal static void SendNotification(this INotificationService service, IUser sender, IUmbracoEntity entity, IAction action, UmbracoContext umbracoContext, ApplicationContext applicationContext) + internal static void SendNotification(this INotificationService service, IUser sender, IUmbracoEntity entity, IAction action, UmbracoContext umbracoContext) { if (sender == null) throw new ArgumentNullException(nameof(sender)); if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); - if (applicationContext == null) throw new ArgumentNullException(nameof(applicationContext)); - - applicationContext.Services.NotificationService.SendNotifications( + var textService = Current.Services.TextService; // fixme inject + + service.SendNotifications( sender, entity, action.Letter.ToString(CultureInfo.InvariantCulture), - applicationContext.Services.TextService.Localize("actions", action.Alias), + textService.Localize("actions", action.Alias), umbracoContext.HttpContext, - (mailingUser, strings) => applicationContext.Services.TextService.Localize("notifications/mailSubject", mailingUser.GetUserCulture(applicationContext.Services.TextService), strings), + (mailingUser, strings) => textService.Localize("notifications/mailSubject", mailingUser.GetUserCulture(textService), strings), (mailingUser, strings) => UmbracoConfig.For.UmbracoSettings().Content.DisableHtmlEmail - ? applicationContext.Services.TextService.Localize("notifications/mailBody", mailingUser.GetUserCulture(applicationContext.Services.TextService), strings) - : applicationContext.Services.TextService.Localize("notifications/mailBodyHtml", mailingUser.GetUserCulture(applicationContext.Services.TextService), strings)); + ? textService.Localize("notifications/mailBody", mailingUser.GetUserCulture(textService), strings) + : textService.Localize("notifications/mailBodyHtml", mailingUser.GetUserCulture(textService), strings)); } - internal static void SendNotification(this INotificationService service, IUser sender, IEnumerable entities, IAction action, UmbracoContext umbracoContext, ApplicationContext applicationContext) + internal static void SendNotification(this INotificationService service, IUser sender, IEnumerable entities, IAction action, UmbracoContext umbracoContext) { if (sender == null) throw new ArgumentNullException(nameof(sender)); if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); - if (applicationContext == null) throw new ArgumentNullException(nameof(applicationContext)); - - applicationContext.Services.NotificationService.SendNotifications( + var textService = Current.Services.TextService; // fixme inject + + service.SendNotifications( sender, entities, action.Letter.ToString(CultureInfo.InvariantCulture), - applicationContext.Services.TextService.Localize("actions", action.Alias), + textService.Localize("actions", action.Alias), umbracoContext.HttpContext, - (mailingUser, strings) => applicationContext.Services.TextService.Localize("notifications/mailSubject", mailingUser.GetUserCulture(applicationContext.Services.TextService), strings), + (mailingUser, strings) => textService.Localize("notifications/mailSubject", mailingUser.GetUserCulture(textService), strings), (mailingUser, strings) => UmbracoConfig.For.UmbracoSettings().Content.DisableHtmlEmail - ? applicationContext.Services.TextService.Localize("notifications/mailBody", mailingUser.GetUserCulture(applicationContext.Services.TextService), strings) - : applicationContext.Services.TextService.Localize("notifications/mailBodyHtml", mailingUser.GetUserCulture(applicationContext.Services.TextService), strings)); + ? textService.Localize("notifications/mailBody", mailingUser.GetUserCulture(textService), strings) + : textService.Localize("notifications/mailBodyHtml", mailingUser.GetUserCulture(textService), strings)); } } } \ No newline at end of file diff --git a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs index 0f49b50070..bcc91ad042 100644 --- a/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/FileUploadPropertyEditor.cs @@ -286,7 +286,7 @@ namespace Umbraco.Web.PropertyEditors /// We're going to bind to the MediaService Saving event so that we can populate the umbracoFile size, type, etc... label fields /// if we find any attached to the current media item. /// - protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication) { MediaService.Saving += _fileUploadPropertyEditor.MediaServiceSaving; MediaService.Created += _fileUploadPropertyEditor.MediaServiceCreating; @@ -305,20 +305,20 @@ namespace Umbraco.Web.PropertyEditors } } - public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication) { //wrap - _applicationStartup.OnApplicationInitialized(umbracoApplication, applicationContext); + _applicationStartup.OnApplicationInitialized(umbracoApplication); } - public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication) { //wrap - _applicationStartup.OnApplicationStarting(umbracoApplication, applicationContext); + _applicationStartup.OnApplicationStarting(umbracoApplication); } - public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication) { //wrap - _applicationStartup.OnApplicationStarted(umbracoApplication, applicationContext); + _applicationStartup.OnApplicationStarted(umbracoApplication); } #endregion diff --git a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs index 522978fef1..fdef4c9be4 100644 --- a/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/GridPropertyEditor.cs @@ -148,7 +148,7 @@ namespace Umbraco.Web.PropertyEditors /// /// We're going to bind to the Examine events so we can ensure grid data is index nicely. /// - protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication) { foreach (var i in _indexCollection.Indexes.Values.OfType()) { @@ -157,20 +157,20 @@ namespace Umbraco.Web.PropertyEditors } } - public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication) { //wrap - _applicationStartup.OnApplicationInitialized(umbracoApplication, applicationContext); + _applicationStartup.OnApplicationInitialized(umbracoApplication); } - public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication) { //wrap - _applicationStartup.OnApplicationStarting(umbracoApplication, applicationContext); + _applicationStartup.OnApplicationStarting(umbracoApplication); } - public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication) { //wrap - _applicationStartup.OnApplicationStarted(umbracoApplication, applicationContext); + _applicationStartup.OnApplicationStarted(umbracoApplication); } #endregion } diff --git a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs index a9c040b022..e4aa3bdecc 100644 --- a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs @@ -227,7 +227,7 @@ namespace Umbraco.Web.PropertyEditors else if (p.Value is string) { var src = p.Value == null ? string.Empty : p.Value.ToString(); - var config = ApplicationContext.Current.Services.DataTypeService.GetPreValuesByDataTypeId(p.PropertyType.DataTypeDefinitionId).FirstOrDefault(); + var config = Current.Services.DataTypeService.GetPreValuesByDataTypeId(p.PropertyType.DataTypeDefinitionId).FirstOrDefault(); var crops = string.IsNullOrEmpty(config) == false ? config : "[]"; p.Value = "{src: '" + p.Value + "', crops: " + crops + "}"; //Only provide the source path, not the whole JSON value @@ -273,7 +273,7 @@ namespace Umbraco.Web.PropertyEditors /// We're going to bind to the MediaService Saving event so that we can populate the umbracoFile size, type, etc... label fields /// if we find any attached to the current media item. /// - protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication) { MediaService.Saving += _imageCropperPropertyEditor.MediaServiceSaving; MediaService.Created += _imageCropperPropertyEditor.MediaServiceCreated; @@ -292,20 +292,20 @@ namespace Umbraco.Web.PropertyEditors } } - public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication) { //wrap - _applicationStartup.OnApplicationInitialized(umbracoApplication, applicationContext); + _applicationStartup.OnApplicationInitialized(umbracoApplication); } - public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication) { //wrap - _applicationStartup.OnApplicationStarting(umbracoApplication, applicationContext); + _applicationStartup.OnApplicationStarting(umbracoApplication); } - public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication) { //wrap - _applicationStartup.OnApplicationStarted(umbracoApplication, applicationContext); + _applicationStartup.OnApplicationStarted(umbracoApplication); } #endregion } diff --git a/src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs b/src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs index 98a1ecefa1..1024fa968f 100644 --- a/src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/PublishValueValueEditor.cs @@ -26,7 +26,7 @@ namespace Umbraco.Web.PropertyEditors } public PublishValueValueEditor(PropertyValueEditor wrapped) - : this(ApplicationContext.Current.Services.DataTypeService, wrapped) + : this(Current.Services.DataTypeService, wrapped) { } diff --git a/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs b/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs index 044a958deb..fe3dcfc5ef 100644 --- a/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs @@ -26,7 +26,7 @@ namespace Umbraco.Web.PropertyEditors } public PublishValuesMultipleValueEditor(bool publishIds, PropertyValueEditor wrapped) - : this(publishIds, ApplicationContext.Current.Services.DataTypeService, wrapped) + : this(publishIds, Current.Services.DataTypeService, wrapped) { } diff --git a/src/Umbraco.Web/PropertyEditors/RichTextPreValueController.cs b/src/Umbraco.Web/PropertyEditors/RichTextPreValueController.cs index ca8df2b9be..4b364df27f 100644 --- a/src/Umbraco.Web/PropertyEditors/RichTextPreValueController.cs +++ b/src/Umbraco.Web/PropertyEditors/RichTextPreValueController.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; using System.Xml; using Umbraco.Core.IO; using Umbraco.Web.Editors; @@ -18,16 +13,15 @@ namespace Umbraco.Web.PropertyEditors [PluginController("UmbracoApi")] public class RichTextPreValueController : UmbracoAuthorizedJsonController { - private static volatile bool _init = false; + private static volatile bool _init; private static readonly object Locker = new object(); private static readonly Dictionary Commands = new Dictionary(); private static readonly Dictionary Plugins = new Dictionary(); private static readonly Dictionary ConfigOptions = new Dictionary(); - + private static string _invalidElements = ""; private static string _validElements = ""; - public RichTextEditorConfiguration GetConfiguration() { EnsureInit(); @@ -131,7 +125,7 @@ namespace Umbraco.Web.PropertyEditors } } } - + } } diff --git a/src/Umbraco.Web/PropertyEditors/RteEmbedController.cs b/src/Umbraco.Web/PropertyEditors/RteEmbedController.cs index 6e6417615d..744511dbc5 100644 --- a/src/Umbraco.Web/PropertyEditors/RteEmbedController.cs +++ b/src/Umbraco.Web/PropertyEditors/RteEmbedController.cs @@ -1,17 +1,11 @@ using System; using System.Linq; -using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; -using System.Web.Http; using System.Xml; -using umbraco.BusinessLogic; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Web.Editors; using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi.Filters; -using Constants = Umbraco.Core.Constants; using Umbraco.Core.Media; using System.IO; @@ -23,7 +17,6 @@ namespace Umbraco.Web.PropertyEditors [PluginController("UmbracoApi")] public class RteEmbedController : UmbracoAuthorizedJsonController { - public Result GetEmbed(string url, int width, int height) { var result = new Result(); diff --git a/src/Umbraco.Web/PropertyEditors/TagsDataController.cs b/src/Umbraco.Web/PropertyEditors/TagsDataController.cs index 5d8e799c6c..0daf22abe7 100644 --- a/src/Umbraco.Web/PropertyEditors/TagsDataController.cs +++ b/src/Umbraco.Web/PropertyEditors/TagsDataController.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Umbraco.Web.Editors; using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; diff --git a/src/Umbraco.Web/PropertyEditors/UploadFileTypeValidator.cs b/src/Umbraco.Web/PropertyEditors/UploadFileTypeValidator.cs index 42ad7d96c4..9d42eaf531 100644 --- a/src/Umbraco.Web/PropertyEditors/UploadFileTypeValidator.cs +++ b/src/Umbraco.Web/PropertyEditors/UploadFileTypeValidator.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.PropertyEditors { if (ValidateFileExtension(fileName) == false) { - yield return new ValidationResult(ApplicationContext.Current.Services.TextService.Localize("errors/dissallowedMediaType"), + yield return new ValidationResult(Current.Services.TextService.Localize("errors/dissallowedMediaType"), new[] { //we only store a single value for this editor so the 'member' or 'field' diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MacroContainerValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/MacroContainerValueConverter.cs index c8a3f08f9d..c8761b2d6a 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/MacroContainerValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/MacroContainerValueConverter.cs @@ -2,9 +2,11 @@ using System; using System.Text; using System.Web; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Macros; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors.ValueConverters { @@ -15,11 +17,15 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters [DefaultPropertyValueConverter] public class MacroContainerValueConverter : PropertyValueConverterBase { - private readonly UmbracoContext _umbracoContext; + private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly ServiceContext _services; + private readonly CacheHelper _appCache; - public MacroContainerValueConverter(UmbracoContext umbracoContext) + public MacroContainerValueConverter(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, CacheHelper appCache) { - _umbracoContext = umbracoContext; + _umbracoContextAccessor = umbracoContextAccessor; + _services = services; + _appCache = appCache; } public override bool IsConverter(PublishedPropertyType propertyType) @@ -42,12 +48,13 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters // should never execute in // over the same UmbracoContext with // different preview modes. string RenderMacros(string source, bool preview) - { - using (_umbracoContext.ForcedPreview(preview)) // force for macro rendering + { + var umbracoContext = _umbracoContextAccessor.UmbracoContext; + using (umbracoContext.ForcedPreview(preview)) // force for macro rendering { var sb = new StringBuilder(); - var umbracoHelper = new UmbracoHelper(_umbracoContext); + var umbracoHelper = new UmbracoHelper(umbracoContext, _services, _appCache); MacroTagParser.ParseMacros( source, //callback for when text block is found diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/RelatedLinksEditorValueConvertor.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/RelatedLinksEditorValueConvertor.cs index c7bfad1e42..2f08b27dc6 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/RelatedLinksEditorValueConvertor.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/RelatedLinksEditorValueConvertor.cs @@ -4,21 +4,27 @@ using System.Xml; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors.ValueConverters { [DefaultPropertyValueConverter(typeof(JsonValueConverter))] //this shadows the JsonValueConverter public class RelatedLinksEditorValueConvertor : PropertyValueConverterBase { - private readonly UmbracoContext _umbracoContext; + private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly ServiceContext _services; + private readonly CacheHelper _appCache; - public RelatedLinksEditorValueConvertor(UmbracoContext umbracoContext) + public RelatedLinksEditorValueConvertor(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, CacheHelper appCache) { - _umbracoContext = umbracoContext; + _umbracoContextAccessor = umbracoContextAccessor; + _services = services; + _appCache = appCache; } public override bool IsConverter(PublishedPropertyType propertyType) @@ -40,6 +46,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters { if (source == null) return null; var sourceString = source.ToString(); + var umbracoContext = _umbracoContextAccessor.UmbracoContext; if (sourceString.DetectIsJson()) { @@ -47,7 +54,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters { var obj = JsonConvert.DeserializeObject(sourceString); //update the internal links if we have a context - var helper = new UmbracoHelper(_umbracoContext); + var helper = new UmbracoHelper(umbracoContext, _services, _appCache); foreach (var a in obj) { var type = a.Value("type"); diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs index 357dba193c..7d351e548c 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; using System.Text; -using System.Web; using Umbraco.Core; using Umbraco.Core.Macros; using Umbraco.Core.PropertyEditors; @@ -10,6 +7,8 @@ using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Web.Templates; using System.Linq; using HtmlAgilityPack; +using Umbraco.Core.Cache; +using Umbraco.Core.Services; namespace Umbraco.Web.PropertyEditors.ValueConverters { @@ -20,7 +19,9 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters /// public class RteMacroRenderingValueConverter : TinyMceValueConverter { - private readonly UmbracoContext _umbracoContext; + private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly ServiceContext _services; + private readonly CacheHelper _appCache; public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType) { @@ -29,22 +30,25 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters return PropertyCacheLevel.Facade; } - public RteMacroRenderingValueConverter(UmbracoContext umbracoContext) + public RteMacroRenderingValueConverter(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, CacheHelper appCache) { - _umbracoContext = umbracoContext; + _umbracoContextAccessor = umbracoContextAccessor; + _services = services; + _appCache = appCache; } // NOT thread-safe over a request because it modifies the // global UmbracoContext.Current.InPreviewMode status. So it // should never execute in // over the same UmbracoContext with // different preview modes. - string RenderRteMacros(string source, bool preview) - { - using (_umbracoContext.ForcedPreview(preview)) // force for macro rendering + string RenderRteMacros(string source, bool preview) + { + var umbracoContext = _umbracoContextAccessor.UmbracoContext; + using (umbracoContext.ForcedPreview(preview)) // force for macro rendering { var sb = new StringBuilder(); - var umbracoHelper = new UmbracoHelper(_umbracoContext); + var umbracoHelper = new UmbracoHelper(umbracoContext, _services, _appCache); MacroTagParser.ParseMacros( source, //callback for when text block is found diff --git a/src/Umbraco.Web/PublishedCache/NuCache/FacadeService.cs b/src/Umbraco.Web/PublishedCache/NuCache/FacadeService.cs index 443a3307eb..e5d5d7fa2a 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/FacadeService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/FacadeService.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; -using System.Threading; using System.Web.Hosting; using CSharpTest.Net.Collections; using Newtonsoft.Json; @@ -75,7 +74,7 @@ namespace Umbraco.Web.PublishedCache.NuCache //private static int _singletonCheck; - public FacadeService(Options options, MainDom mainDom, ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, IFacadeAccessor facadeAccessor, ILogger logger) + public FacadeService(Options options, MainDom mainDom, IRuntimeState runtime, ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, IFacadeAccessor facadeAccessor, ILogger logger) : base(facadeAccessor) { //if (Interlocked.Increment(ref _singletonCheck) > 1) @@ -97,7 +96,7 @@ namespace Umbraco.Web.PublishedCache.NuCache // Notifications" region), so // - notifications will be ignored // - trying to obtain a facade from the service will throw - if (ApplicationContext.Current.IsConfigured == false) + if (runtime.Level != RuntimeLevel.Run) return; if (_options.IgnoreLocalDb == false) @@ -935,7 +934,7 @@ namespace Umbraco.Web.PublishedCache.NuCache } var facadeCache = _options.FacadeCacheIsApplicationRequestCache - ? ApplicationContext.Current.ApplicationCache.RequestCache + ? Current.ApplicationCache.RequestCache : new StaticCacheProvider(); // assuming that's OK for tests, etc var memberTypeCache = new PublishedContentTypeCache(null, null, _serviceContext.MemberTypeService); diff --git a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs index a74f5d7967..3e42cbed94 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs @@ -17,7 +17,8 @@ namespace Umbraco.Web.PublishedCache.NuCache // register the NuCache facade service container.RegisterSingleton(factory => new FacadeService( new FacadeService.Options { FacadeCacheIsApplicationRequestCache = true }, - factory.GetInstance().MainDom, + factory.GetInstance(), + factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs index 5732c5af31..daff925e83 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs @@ -53,14 +53,12 @@ namespace Umbraco.Web.PublishedCache.NuCache private static string GetProfileNameByIdNoCache(int id) { #if DEBUG - var context = ApplicationContext.Current; - var servicesContext = context?.Services; - var userService = servicesContext?.UserService; + var userService = Current.Services?.UserService; if (userService == null) return "[null]"; // for tests #else // we don't want each published content to hold a reference to the service - // so where should they get the service from really? from the source... - var userService = ApplicationContext.Current.Services.UserService; + // so where should they get the service from really? from the locator... + var userService = Current.Services.UserService; #endif var user = userService.GetProfileById(id); return user?.Name; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/FacadeService.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/FacadeService.cs index 3ee9ca40c0..e94456310a 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/FacadeService.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/FacadeService.cs @@ -37,8 +37,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache ICacheProvider requestCache, IEnumerable segmentProviders, IFacadeAccessor facadeAccessor, + MainDom mainDom, bool testing = false, bool enableRepositoryEvents = true) - : this(serviceContext, uowProvider, requestCache, segmentProviders, facadeAccessor, null, testing, enableRepositoryEvents) + : this(serviceContext, uowProvider, requestCache, segmentProviders, facadeAccessor, null, mainDom, testing, enableRepositoryEvents) { } // used in some tests @@ -47,8 +48,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache ICacheProvider requestCache, IFacadeAccessor facadeAccessor, PublishedContentTypeCache contentTypeCache, + MainDom mainDom, bool testing, bool enableRepositoryEvents) - : this(serviceContext, uowProvider, requestCache, Enumerable.Empty(), facadeAccessor, contentTypeCache, testing, enableRepositoryEvents) + : this(serviceContext, uowProvider, requestCache, Enumerable.Empty(), facadeAccessor, contentTypeCache, mainDom, testing, enableRepositoryEvents) { } private FacadeService(ServiceContext serviceContext, @@ -57,6 +59,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache IEnumerable segmentProviders, IFacadeAccessor facadeAccessor, PublishedContentTypeCache contentTypeCache, + MainDom mainDom, bool testing, bool enableRepositoryEvents) : base(facadeAccessor) { @@ -64,7 +67,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _contentTypeCache = contentTypeCache ?? new PublishedContentTypeCache(serviceContext.ContentTypeService, serviceContext.MediaTypeService, serviceContext.MemberTypeService); - _xmlStore = new XmlStore(serviceContext, uowProvider, _routesCache, _contentTypeCache, segmentProviders, facadeAccessor, testing, enableRepositoryEvents); + _xmlStore = new XmlStore(serviceContext, uowProvider, _routesCache, _contentTypeCache, segmentProviders, facadeAccessor, mainDom, testing, enableRepositoryEvents); _domainService = serviceContext.DomainService; _memberService = serviceContext.MemberService; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs index 57fa989ba8..ef091f42db 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs @@ -877,14 +877,14 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache if (_publishedMediaCacheEnabled == false) return func(id); - var cache = ApplicationContext.Current.ApplicationCache.RuntimeCache; + var cache = Current.ApplicationCache.RuntimeCache; var key = PublishedMediaCacheKey + id; return (CacheValues) cache.GetCacheItem(key, () => func(id), _publishedMediaCacheTimespan); } internal static void ClearCache(int id) { - var cache = ApplicationContext.Current.ApplicationCache.RuntimeCache; + var cache = Current.ApplicationCache.RuntimeCache; var sid = id.ToString(); var key = PublishedMediaCacheKey + sid; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs index 9324fa35d1..810603ea60 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs @@ -1,4 +1,5 @@ using LightInject; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Persistence.UnitOfWork; @@ -21,7 +22,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache factory.GetInstance(), factory.GetInstance().RequestCache, factory.GetAllInstances(), - factory.GetInstance())); + factory.GetInstance(), + factory.GetInstance())); } public void Initialize(IFacadeService service) diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs index 26bb28963b..f568dc1e0f 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs @@ -423,7 +423,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache public static void ClearRequest() { - ApplicationContext.Current.ApplicationCache.RequestCache.ClearCacheByKeySearch(CacheKeyPrefix); + Current.ApplicationCache.RequestCache.ClearCacheByKeySearch(CacheKeyPrefix); } private const string CacheKeyPrefix = "CONTENTCACHE_XMLPUBLISHEDCONTENT_"; diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs index dad048a7a1..94cab16071 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlStore.cs @@ -59,17 +59,18 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache /// /// Initializes a new instance of the class. /// - /// The default constructor will boot the cache, load data from file or database, - /// wire events in order to manage changes, etc. - public XmlStore(ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, IEnumerable segmentProviders, IFacadeAccessor facadeAccessor) - : this(serviceContext, uowProvider, routesCache, contentTypeCache, segmentProviders, facadeAccessor, false, false) + /// The default constructor will boot the cache, load data from file or database, /// wire events in order to manage changes, etc. + public XmlStore(ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, + IEnumerable segmentProviders, IFacadeAccessor facadeAccessor, MainDom mainDom) + : this(serviceContext, uowProvider, routesCache, contentTypeCache, segmentProviders, facadeAccessor, mainDom, false, false) { } // internal for unit tests // no file nor db, no config check // fixme - er, we DO have a DB? internal XmlStore(ServiceContext serviceContext, IDatabaseUnitOfWorkProvider uowProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, - IEnumerable segmentProviders, IFacadeAccessor facadeAccessor, bool testing, bool enableRepositoryEvents) + IEnumerable segmentProviders, IFacadeAccessor facadeAccessor, MainDom mainDom, + bool testing, bool enableRepositoryEvents) { if (testing == false) EnsureConfigurationIsValid(); @@ -88,7 +89,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache } else { - InitializeFilePersister(); + InitializeFilePersister(mainDom); } Initialize(testing, enableRepositoryEvents); @@ -126,7 +127,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _xmlMediaSerializer = m => exs.Serialize(_serviceContext.MediaService, _serviceContext.DataTypeService, _serviceContext.UserService, segmentProviders, m); } - private void InitializeFilePersister() + private void InitializeFilePersister(MainDom mainDom) { if (SyncToXmlFile == false) return; @@ -144,7 +145,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache // create (and add to runner) _persisterTask = new XmlStoreFilePersister(runner, this, logger); - var registered = ApplicationContext.Current.MainDom.Register( + var registered = mainDom.Register( null, () => { diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index cfd0589e05..cf5383a6a7 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -76,7 +76,7 @@ namespace Umbraco.Web /// public static string GetTemplateAlias(this IPublishedContent content) { - var template = ApplicationContext.Current.Services.FileService.GetTemplate(content.TemplateId); + var template = Current.Services.FileService.GetTemplate(content.TemplateId); return template == null ? string.Empty : template.Alias; } @@ -314,7 +314,7 @@ namespace Umbraco.Web private static bool IsDocumentTypeRecursive(IPublishedContent content, string docTypeAlias) { - var contentTypeService = UmbracoContext.Current.Application.Services.ContentTypeService; + var contentTypeService = Current.Services.ContentTypeService; // fixme - inject var type = contentTypeService.Get(content.DocumentTypeAlias); while (type != null && type.ParentId > 0) { @@ -1196,9 +1196,9 @@ namespace Umbraco.Web public static CultureInfo GetCulture(this IPublishedContent content, Uri current = null) { return Models.ContentExtensions.GetCulture(UmbracoContext.Current, - ApplicationContext.Current.Services.DomainService, - ApplicationContext.Current.Services.LocalizationService, - ApplicationContext.Current.Services.ContentService, + Current.Services.DomainService, + Current.Services.LocalizationService, + Current.Services.ContentService, content.Id, content.Path, current); } diff --git a/src/Umbraco.Web/Redirects/RedirectTrackingEventHandler.cs b/src/Umbraco.Web/Redirects/RedirectTrackingEventHandler.cs index 623136a10d..becc9ed7d4 100644 --- a/src/Umbraco.Web/Redirects/RedirectTrackingEventHandler.cs +++ b/src/Umbraco.Web/Redirects/RedirectTrackingEventHandler.cs @@ -26,7 +26,7 @@ namespace Umbraco.Web.Redirects private const string ContextKey3 = "Umbraco.Web.Redirects.RedirectTrackingEventHandler.3"; /// - protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication) { // events are weird // on 'published' we 'could' get the old or the new route depending on event handlers order @@ -163,7 +163,7 @@ namespace Umbraco.Web.Redirects var contentCache = UmbracoContext.Current.ContentCache; var newRoute = contentCache.GetRouteById(contentId); if (IsNotRoute(newRoute) || oldRoute == newRoute) return; - var redirectUrlService = ApplicationContext.Current.Services.RedirectUrlService; + var redirectUrlService = Current.Services.RedirectUrlService; redirectUrlService.Register(oldRoute, contentKey); } diff --git a/src/Umbraco.Web/Routing/ContentFinderByLegacy404.cs b/src/Umbraco.Web/Routing/ContentFinderByLegacy404.cs index bfd50447b4..46f992817e 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByLegacy404.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByLegacy404.cs @@ -1,16 +1,10 @@ -using System.Collections.Generic; -using System.Globalization; +using System.Globalization; using System.Linq; -using System.Reflection; -using System.Web; -using System.Xml; using Umbraco.Core; -using umbraco.cms.businesslogic.web; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; -using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Services; namespace Umbraco.Web.Routing { @@ -21,11 +15,13 @@ namespace Umbraco.Web.Routing { private readonly ILogger _logger; + private readonly IEntityService _entityService; private readonly IContentSection _contentConfigSection; - public ContentFinderByLegacy404(ILogger logger, IContentSection contentConfigSection) + public ContentFinderByLegacy404(ILogger logger, IEntityService entityService, IContentSection contentConfigSection) { _logger = logger; + _entityService = entityService; _contentConfigSection = contentConfigSection; } @@ -66,7 +62,7 @@ namespace Umbraco.Web.Routing var error404 = NotFoundHandlerHelper.GetCurrentNotFoundPageId( _contentConfigSection.Error404Collection.ToArray(), - pcr.RoutingContext.UmbracoContext.Application.Services.EntityService, + _entityService, new PublishedContentQuery(pcr.RoutingContext.UmbracoContext.ContentCache, pcr.RoutingContext.UmbracoContext.MediaCache), errorCulture); diff --git a/src/Umbraco.Web/Routing/ContentFinderByNiceUrlAndTemplate.cs b/src/Umbraco.Web/Routing/ContentFinderByNiceUrlAndTemplate.cs index 74037a3070..9ef3cbd9c5 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByNiceUrlAndTemplate.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByNiceUrlAndTemplate.cs @@ -39,7 +39,7 @@ namespace Umbraco.Web.Routing var templateAlias = path.Substring(pos + 1); path = pos == 0 ? "/" : path.Substring(0, pos); - var template = ApplicationContext.Current.Services.FileService.GetTemplate(templateAlias); + var template = Current.Services.FileService.GetTemplate(templateAlias); if (template != null) { Logger.Debug("Valid template: \"{0}\"", () => templateAlias); diff --git a/src/Umbraco.Web/Routing/ContentFinderByRedirectUrl.cs b/src/Umbraco.Web/Routing/ContentFinderByRedirectUrl.cs index 72d91eb0cf..e94e7369e2 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByRedirectUrl.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByRedirectUrl.cs @@ -1,5 +1,6 @@ using Umbraco.Core; using Umbraco.Core.Logging; +using Umbraco.Core.Services; namespace Umbraco.Web.Routing { @@ -12,6 +13,13 @@ namespace Umbraco.Web.Routing /// public class ContentFinderByRedirectUrl : IContentFinder { + private readonly IRedirectUrlService _redirectUrlService; + + public ContentFinderByRedirectUrl(IRedirectUrlService redirectUrlService) + { + _redirectUrlService = redirectUrlService; + } + /// /// Tries to find and assign an Umbraco document to a PublishedContentRequest. /// @@ -24,8 +32,7 @@ namespace Umbraco.Web.Routing ? contentRequest.Domain.ContentId + DomainHelper.PathRelativeToDomain(contentRequest.Domain.Uri, contentRequest.Uri.GetAbsolutePathDecoded()) : contentRequest.Uri.GetAbsolutePathDecoded(); - var service = contentRequest.RoutingContext.UmbracoContext.Application.Services.RedirectUrlService; - var redirectUrl = service.GetMostRecentRedirectUrl(route); + var redirectUrl = _redirectUrlService.GetMostRecentRedirectUrl(route); if (redirectUrl == null) { diff --git a/src/Umbraco.Web/Routing/EnsureRoutableOutcome.cs b/src/Umbraco.Web/Routing/EnsureRoutableOutcome.cs index fd09f5ff8c..5c4ab0a4ea 100644 --- a/src/Umbraco.Web/Routing/EnsureRoutableOutcome.cs +++ b/src/Umbraco.Web/Routing/EnsureRoutableOutcome.cs @@ -31,14 +31,9 @@ namespace Umbraco.Web.Routing /// NotReady = 11, - /// - /// Umbraco was not configured. - /// - NotConfigured = 12, - /// /// There was no content at all. /// - NoContent = 13 + NoContent = 12 } } \ No newline at end of file diff --git a/src/Umbraco.Web/Routing/PublishedContentRequest.cs b/src/Umbraco.Web/Routing/PublishedContentRequest.cs index d0a859fe65..c9255fef67 100644 --- a/src/Umbraco.Web/Routing/PublishedContentRequest.cs +++ b/src/Umbraco.Web/Routing/PublishedContentRequest.cs @@ -343,7 +343,7 @@ namespace Umbraco.Web.Routing // NOTE - can we stil get it with whitespaces in it due to old legacy bugs? alias = alias.Replace(" ", ""); - var model = ApplicationContext.Current.Services.FileService.GetTemplate(alias); + var model = Current.Services.FileService.GetTemplate(alias); if (model == null) return false; diff --git a/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs b/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs index d002a8a1ec..d4044b421d 100644 --- a/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs +++ b/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs @@ -45,9 +45,9 @@ namespace Umbraco.Web.Routing //if (umbracoContext.PublishedContentRequest != _pcr) throw new ArgumentException("PublishedContentRequest confusion."); } - protected ProfilingLogger ProfilingLogger => _routingContext.UmbracoContext.Application.ProfilingLogger; + protected ProfilingLogger ProfilingLogger => Current.ProfilingLogger; // fixme inject - protected ServiceContext Services => _routingContext.UmbracoContext.Application.Services; + protected ServiceContext Services => Current.Services; // fixme inject #region Public @@ -623,7 +623,7 @@ namespace Umbraco.Web.Routing if (templateId > 0) { ProfilingLogger.Logger.Debug("{0}Look for template id={1}", () => tracePrefix, () => templateId); - var template = ApplicationContext.Current.Services.FileService.GetTemplate(templateId); + var template = Current.Services.FileService.GetTemplate(templateId); if (template == null) throw new InvalidOperationException("The template with Id " + templateId + " does not exist, the page cannot render"); _pcr.TemplateModel = template; @@ -646,7 +646,7 @@ namespace Umbraco.Web.Routing ProfilingLogger.Logger.Debug("{0}Has a template already, but also an alternate template.", () => tracePrefix); ProfilingLogger.Logger.Debug("{0}Look for alternate template alias=\"{1}\"", () => tracePrefix, () => altTemplate); - var template = ApplicationContext.Current.Services.FileService.GetTemplate(altTemplate); + var template = Current.Services.FileService.GetTemplate(altTemplate); if (template != null) { _pcr.TemplateModel = template; diff --git a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs index 09201776b0..c6a792a6ae 100644 --- a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs +++ b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs @@ -1,14 +1,16 @@ using System; using System.Collections.Generic; using Umbraco.Core.Models; -using umbraco; -using Umbraco.Core; using Umbraco.Core.Services; namespace Umbraco.Web.Routing { internal static class UrlProviderExtensions { + // fixme inject + private static ILocalizedTextService TextService => Current.Services.TextService; + private static IContentService ContentService => Current.Services.ContentService; + /// /// Gets the URLs for the content item /// @@ -21,14 +23,14 @@ namespace Umbraco.Web.Routing /// public static IEnumerable GetContentUrls(this IContent content, UmbracoContext umbracoContext) { - if (content == null) throw new ArgumentNullException("content"); - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + if (content == null) throw new ArgumentNullException(nameof(content)); + if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); var urls = new List(); if (content.HasPublishedVersion == false) { - urls.Add(umbracoContext.Application.Services.TextService.Localize("content/itemNotPublished")); + urls.Add(TextService.Localize("content/itemNotPublished")); return urls; } @@ -41,14 +43,13 @@ namespace Umbraco.Web.Routing var parent = content; do { - parent = parent.ParentId > 0 ? parent.Parent(umbracoContext.Application.Services.ContentService) : null; + parent = parent.ParentId > 0 ? parent.Parent(ContentService) : null; } while (parent != null && parent.Published); - - if (parent == null) // oops - internal error - urls.Add(umbracoContext.Application.Services.TextService.Localize("content/parentNotPublishedAnomaly")); - else - urls.Add(umbracoContext.Application.Services.TextService.Localize("content/parentNotPublished", new[] { parent.Name })); + + urls.Add(parent == null + ? TextService.Localize("content/parentNotPublishedAnomaly") // oops - internal error + : TextService.Localize("content/parentNotPublished", new[] { parent.Name })); } else if (url.StartsWith("#err-")) { @@ -72,7 +73,7 @@ namespace Umbraco.Web.Routing s = "/" + string.Join("/", l) + " (id=" + id + ")"; } - urls.Add(umbracoContext.Application.Services.TextService.Localize("content/routeError", s)); + urls.Add(TextService.Localize("content/routeError", s)); } else { diff --git a/src/Umbraco.Web/Scheduling/KeepAlive.cs b/src/Umbraco.Web/Scheduling/KeepAlive.cs index 380ae85401..d5618e4be2 100644 --- a/src/Umbraco.Web/Scheduling/KeepAlive.cs +++ b/src/Umbraco.Web/Scheduling/KeepAlive.cs @@ -1,23 +1,21 @@ using System; -using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Umbraco.Core; -using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; namespace Umbraco.Web.Scheduling { internal class KeepAlive : RecurringTaskBase { - private readonly ApplicationContext _appContext; + private readonly IRuntimeState _runtime; public KeepAlive(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - ApplicationContext appContext) + IRuntimeState runtime) : base(runner, delayMilliseconds, periodMilliseconds) { - _appContext = appContext; + _runtime = runtime; } public override bool PerformRun() @@ -27,10 +25,8 @@ namespace Umbraco.Web.Scheduling public override async Task PerformRunAsync(CancellationToken token) { - if (_appContext == null) return true; // repeat... - // ensure we do not run if not main domain, but do NOT lock it - if (_appContext.MainDom.IsMainDom == false) + if (_runtime.IsMainDom == false) { LogHelper.Debug("Does not run if not MainDom."); return false; // do NOT repeat, going down @@ -42,7 +38,7 @@ namespace Umbraco.Web.Scheduling try { - umbracoAppUrl = _appContext.UmbracoApplicationUrl; + umbracoAppUrl = _runtime.ApplicationUrl.ToString(); if (umbracoAppUrl.IsNullOrWhiteSpace()) { LogHelper.Warn("No url for service (yet), skip."); diff --git a/src/Umbraco.Web/Scheduling/LogScrubber.cs b/src/Umbraco.Web/Scheduling/LogScrubber.cs index d2f1eb2e11..7a62ce5278 100644 --- a/src/Umbraco.Web/Scheduling/LogScrubber.cs +++ b/src/Umbraco.Web/Scheduling/LogScrubber.cs @@ -1,26 +1,26 @@ using System; using System.Threading; using System.Threading.Tasks; -using System.Web; -using System.Web.Caching; -using umbraco.BusinessLogic; using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; +using Umbraco.Core.Services; using Umbraco.Core.Sync; namespace Umbraco.Web.Scheduling { internal class LogScrubber : RecurringTaskBase { - private readonly ApplicationContext _appContext; + private readonly IRuntimeState _runtime; + private readonly IAuditService _auditService; private readonly IUmbracoSettingsSection _settings; - public LogScrubber(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - ApplicationContext appContext, IUmbracoSettingsSection settings) + public LogScrubber(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, + IRuntimeState runtime, IAuditService auditService, IUmbracoSettingsSection settings) : base(runner, delayMilliseconds, periodMilliseconds) { - _appContext = appContext; + _runtime = runtime; + _auditService = auditService; _settings = settings; } @@ -58,9 +58,7 @@ namespace Umbraco.Web.Scheduling public override bool PerformRun() { - if (_appContext == null) return true; // repeat... - - switch (_appContext.GetCurrentServerRole()) + switch (_runtime.ServerRole) { case ServerRole.Slave: LogHelper.Debug("Does not run on slave servers."); @@ -71,7 +69,7 @@ namespace Umbraco.Web.Scheduling } // ensure we do not run if not main domain, but do NOT lock it - if (_appContext.MainDom.IsMainDom == false) + if (_runtime.IsMainDom == false) { LogHelper.Debug("Does not run if not MainDom."); return false; // do NOT repeat, going down @@ -79,7 +77,7 @@ namespace Umbraco.Web.Scheduling using (DisposableTimer.DebugDuration("Log scrubbing executing", "Log scrubbing complete")) { - _appContext.Services.AuditService.CleanLogs(GetLogScrubbingMaximumAge(_settings)); + _auditService.CleanLogs(GetLogScrubbingMaximumAge(_settings)); } return true; // repeat diff --git a/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs b/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs index 0f7e3f0183..123c48a715 100644 --- a/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs +++ b/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs @@ -3,8 +3,8 @@ using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Umbraco.Core; -using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; +using Umbraco.Core.Services; using Umbraco.Core.Sync; using Umbraco.Web.Mvc; @@ -12,15 +12,15 @@ namespace Umbraco.Web.Scheduling { internal class ScheduledPublishing : RecurringTaskBase { - private readonly ApplicationContext _appContext; - private readonly IUmbracoSettingsSection _settings; + private readonly IRuntimeState _runtime; + private readonly IUserService _userService; public ScheduledPublishing(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - ApplicationContext appContext, IUmbracoSettingsSection settings) + IRuntimeState runtime, IUserService userService) : base(runner, delayMilliseconds, periodMilliseconds) { - _appContext = appContext; - _settings = settings; + _runtime = runtime; + _userService = userService; } public override bool PerformRun() @@ -29,10 +29,8 @@ namespace Umbraco.Web.Scheduling } public override async Task PerformRunAsync(CancellationToken token) - { - if (_appContext == null) return true; // repeat... - - switch (_appContext.GetCurrentServerRole()) + { + switch (_runtime.ServerRole) { case ServerRole.Slave: LogHelper.Debug("Does not run on slave servers."); @@ -43,7 +41,7 @@ namespace Umbraco.Web.Scheduling } // ensure we do not run if not main domain, but do NOT lock it - if (_appContext.MainDom.IsMainDom == false) + if (_runtime.IsMainDom == false) { LogHelper.Debug("Does not run if not MainDom."); return false; // do NOT repeat, going down @@ -55,7 +53,7 @@ namespace Umbraco.Web.Scheduling try { - umbracoAppUrl = _appContext.UmbracoApplicationUrl; + umbracoAppUrl = _runtime.ApplicationUrl.ToString(); if (umbracoAppUrl.IsNullOrWhiteSpace()) { LogHelper.Warn("No url for service (yet), skip."); @@ -70,7 +68,7 @@ namespace Umbraco.Web.Scheduling Content = new StringContent(string.Empty) }; //pass custom the authorization header - request.Headers.Authorization = AdminTokenAuthorizeAttribute.GetAuthenticationHeaderValue(_appContext); + request.Headers.Authorization = AdminTokenAuthorizeAttribute.GetAuthenticationHeaderValue(_userService); var result = await wc.SendAsync(request, token); } @@ -88,7 +86,7 @@ namespace Umbraco.Web.Scheduling { get { return true; } } - + public override bool RunsOnShutdown { get { return false; } diff --git a/src/Umbraco.Web/Scheduling/ScheduledTasks.cs b/src/Umbraco.Web/Scheduling/ScheduledTasks.cs index 3f0a9f2a97..3bb841b388 100644 --- a/src/Umbraco.Web/Scheduling/ScheduledTasks.cs +++ b/src/Umbraco.Web/Scheduling/ScheduledTasks.cs @@ -17,15 +17,15 @@ namespace Umbraco.Web.Scheduling internal class ScheduledTasks : RecurringTaskBase { - private readonly ApplicationContext _appContext; + private readonly IRuntimeState _runtime; private readonly IUmbracoSettingsSection _settings; private static readonly Hashtable ScheduledTaskTimes = new Hashtable(); - public ScheduledTasks(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - ApplicationContext appContext, IUmbracoSettingsSection settings) + public ScheduledTasks(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, + IRuntimeState runtime, IUmbracoSettingsSection settings) : base(runner, delayMilliseconds, periodMilliseconds) { - _appContext = appContext; + _runtime = runtime; _settings = settings; } @@ -88,9 +88,7 @@ namespace Umbraco.Web.Scheduling public override async Task PerformRunAsync(CancellationToken token) { - if (_appContext == null) return true; // repeat... - - switch (_appContext.GetCurrentServerRole()) + switch (_runtime.ServerRole) { case ServerRole.Slave: LogHelper.Debug("Does not run on slave servers."); @@ -101,7 +99,7 @@ namespace Umbraco.Web.Scheduling } // ensure we do not run if not main domain, but do NOT lock it - if (_appContext.MainDom.IsMainDom == false) + if (_runtime.IsMainDom == false) { LogHelper.Debug("Does not run if not MainDom."); return false; // do NOT repeat, going down diff --git a/src/Umbraco.Web/Scheduling/Scheduler.cs b/src/Umbraco.Web/Scheduling/SchedulerComponent.cs similarity index 66% rename from src/Umbraco.Web/Scheduling/Scheduler.cs rename to src/Umbraco.Web/Scheduling/SchedulerComponent.cs index f5f8a799d1..94eebd27fb 100644 --- a/src/Umbraco.Web/Scheduling/Scheduler.cs +++ b/src/Umbraco.Web/Scheduling/SchedulerComponent.cs @@ -1,9 +1,10 @@ using System.Collections.Generic; using System.Threading; -using System.Web; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; +using Umbraco.Core.Services; using Umbraco.Web.Routing; namespace Umbraco.Web.Scheduling @@ -12,36 +13,37 @@ namespace Umbraco.Web.Scheduling /// Used to do the scheduling for tasks, publishing, etc... /// /// - /// All tasks are run in a background task runner which is web aware and will wind down the task correctly instead of killing it completely when - /// the app domain shuts down. + /// All tasks are run in a background task runner which is web aware and will wind down + /// the task correctly instead of killing it completely when the app domain shuts down. /// - internal sealed class Scheduler : ApplicationEventHandler + internal sealed class SchedulerComponent : UmbracoComponentBase, IUmbracoCoreComponent { + private IRuntimeState _runtime; + private IUserService _userService; + private IAuditService _auditService; + private BackgroundTaskRunner _keepAliveRunner; private BackgroundTaskRunner _publishingRunner; private BackgroundTaskRunner _tasksRunner; private BackgroundTaskRunner _scrubberRunner; - private bool _started = false; + + private bool _started; private object _locker = new object(); private IBackgroundTask[] _tasks; - /// - /// Overridable method to execute when the ApplicationContext is created and other static objects that require initialization have been setup - /// - /// - /// - protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + public void Initialize(IRuntimeState runtime, IUserService userService, IAuditService auditService, ILogger logger) { - if (umbracoApplication.Context == null) - return; + _runtime = runtime; + _userService = userService; + _auditService = auditService; // backgrounds runners are web aware, if the app domain dies, these tasks will wind down correctly - _keepAliveRunner = new BackgroundTaskRunner("KeepAlive", applicationContext.ProfilingLogger.Logger); - _publishingRunner = new BackgroundTaskRunner("ScheduledPublishing", applicationContext.ProfilingLogger.Logger); - _tasksRunner = new BackgroundTaskRunner("ScheduledTasks", applicationContext.ProfilingLogger.Logger); - _scrubberRunner = new BackgroundTaskRunner("LogScrubber", applicationContext.ProfilingLogger.Logger); + _keepAliveRunner = new BackgroundTaskRunner("KeepAlive", logger); + _publishingRunner = new BackgroundTaskRunner("ScheduledPublishing", logger); + _tasksRunner = new BackgroundTaskRunner("ScheduledTasks", logger); + _scrubberRunner = new BackgroundTaskRunner("LogScrubber", logger); - //We will start the whole process when a successful request is made + // we will start the whole process when a successful request is made UmbracoModule.RouteAttempt += UmbracoModuleRouteAttempt; } @@ -58,20 +60,20 @@ namespace Umbraco.Web.Scheduling private void RegisterBackgroundTasks(UmbracoRequestEventArgs e) { - //remove handler, we're done + // remove handler, we're done UmbracoModule.RouteAttempt -= UmbracoModuleRouteAttempt; LazyInitializer.EnsureInitialized(ref _tasks, ref _started, ref _locker, () => { - LogHelper.Debug(() => "Initializing the scheduler"); + LogHelper.Debug(() => "Initializing the scheduler"); var settings = UmbracoConfig.For.UmbracoSettings(); var tasks = new List { - new KeepAlive(_keepAliveRunner, 60000, 300000, e.UmbracoContext.Application), - new ScheduledPublishing(_publishingRunner, 60000, 60000, e.UmbracoContext.Application, settings), - new ScheduledTasks(_tasksRunner, 60000, 60000, e.UmbracoContext.Application, settings), - new LogScrubber(_scrubberRunner, 60000, LogScrubber.GetLogScrubbingInterval(settings), e.UmbracoContext.Application, settings) + new KeepAlive(_keepAliveRunner, 60000, 300000, _runtime), + new ScheduledPublishing(_publishingRunner, 60000, 60000, _runtime, _userService), + new ScheduledTasks(_tasksRunner, 60000, 60000, _runtime, settings), + new LogScrubber(_scrubberRunner, 60000, LogScrubber.GetLogScrubbingInterval(settings), _runtime, _auditService, settings) }; // ping/keepalive diff --git a/src/Umbraco.Web/Search/ExamineEvents.cs b/src/Umbraco.Web/Search/ExamineEvents.cs index e55cdc2faa..835a31f46b 100644 --- a/src/Umbraco.Web/Search/ExamineEvents.cs +++ b/src/Umbraco.Web/Search/ExamineEvents.cs @@ -34,7 +34,7 @@ namespace Umbraco.Web.Search /// /// We need to do this on the Started event as to guarantee that all resolvers are setup properly. /// - protected override void ApplicationStarted(UmbracoApplicationBase httpApplication, ApplicationContext applicationContext) + protected override void ApplicationStarted(UmbracoApplicationBase httpApplication) { LogHelper.Info("Initializing Examine and binding to business logic events"); @@ -74,7 +74,7 @@ namespace Umbraco.Web.Search switch (args.MessageType) { case MessageType.RefreshById: - var c1 = ApplicationContext.Current.Services.MemberService.GetById((int)args.MessageObject); + var c1 = Current.Services.MemberService.GetById((int)args.MessageObject); if (c1 != null) { ReIndexForMember(c1); @@ -116,7 +116,7 @@ namespace Umbraco.Web.Search if (args.MessageType != MessageType.RefreshByPayload) throw new NotSupportedException(); - var mediaService = ApplicationContext.Current.Services.MediaService; + var mediaService = Current.Services.MediaService; foreach (var payload in (MediaCacheRefresher.JsonPayload[]) args.MessageObject) { @@ -162,7 +162,7 @@ namespace Umbraco.Web.Search if (args.MessageType != MessageType.RefreshByPayload) throw new NotSupportedException(); - var contentService = ApplicationContext.Current.Services.ContentService; + var contentService = Current.Services.ContentService; foreach (var payload in (ContentCacheRefresher.JsonPayload[]) args.MessageObject) { diff --git a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs index f1dab2ee63..460942673e 100644 --- a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.Identity; using Umbraco.Core.Security; +using Umbraco.Core.Services; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Security.Identity @@ -53,22 +54,22 @@ namespace Umbraco.Web.Security.Identity /// Configure Default Identity User Manager for Umbraco /// /// - /// + /// /// public static void ConfigureUserManagerForUmbracoBackOffice(this IAppBuilder app, - ApplicationContext appContext, + ServiceContext services, MembershipProviderBase userMembershipProvider) { - if (appContext == null) throw new ArgumentNullException("appContext"); - if (userMembershipProvider == null) throw new ArgumentNullException("userMembershipProvider"); + if (services == null) throw new ArgumentNullException(nameof(services)); + if (userMembershipProvider == null) throw new ArgumentNullException(nameof(userMembershipProvider)); //Configure Umbraco user manager to be created per request app.CreatePerOwinContext( (options, owinContext) => BackOfficeUserManager.Create( options, - appContext.Services.UserService, - appContext.Services.MemberTypeService, - appContext.Services.ExternalLoginService, + services.UserService, + services.MemberTypeService, + services.ExternalLoginService, userMembershipProvider)); //Create a sign in manager per request @@ -79,17 +80,17 @@ namespace Umbraco.Web.Security.Identity /// Configure a custom UserStore with the Identity User Manager for Umbraco /// /// - /// + /// /// /// public static void ConfigureUserManagerForUmbracoBackOffice(this IAppBuilder app, - ApplicationContext appContext, + IRuntimeState runtimeState, MembershipProviderBase userMembershipProvider, BackOfficeUserStore customUserStore) { - if (appContext == null) throw new ArgumentNullException("appContext"); - if (userMembershipProvider == null) throw new ArgumentNullException("userMembershipProvider"); - if (customUserStore == null) throw new ArgumentNullException("customUserStore"); + if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); + if (userMembershipProvider == null) throw new ArgumentNullException(nameof(userMembershipProvider)); + if (customUserStore == null) throw new ArgumentNullException(nameof(customUserStore)); //Configure Umbraco user manager to be created per request app.CreatePerOwinContext( @@ -106,16 +107,16 @@ namespace Umbraco.Web.Security.Identity /// Configure a custom BackOfficeUserManager for Umbraco /// /// - /// + /// /// public static void ConfigureUserManagerForUmbracoBackOffice(this IAppBuilder app, - ApplicationContext appContext, + IRuntimeState runtimeState, Func, IOwinContext, TManager> userManager) where TManager : BackOfficeUserManager where TUser : BackOfficeIdentityUser { - if (appContext == null) throw new ArgumentNullException("appContext"); - if (userManager == null) throw new ArgumentNullException("userManager"); + if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); + if (userManager == null) throw new ArgumentNullException(nameof(userManager)); //Configure Umbraco user manager to be created per request app.CreatePerOwinContext(userManager); @@ -128,26 +129,26 @@ namespace Umbraco.Web.Security.Identity /// Ensures that the UmbracoBackOfficeAuthenticationMiddleware is assigned to the pipeline /// /// - /// + /// /// /// /// By default this will be configured to execute on PipelineStage.Authenticate /// - public static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, ApplicationContext appContext) + public static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, IRuntimeState runtimeState) { - return app.UseUmbracoBackOfficeCookieAuthentication(appContext, PipelineStage.Authenticate); + return app.UseUmbracoBackOfficeCookieAuthentication(runtimeState, PipelineStage.Authenticate); } /// /// Ensures that the UmbracoBackOfficeAuthenticationMiddleware is assigned to the pipeline /// /// - /// + /// /// /// Configurable pipeline stage /// /// - public static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, ApplicationContext appContext, PipelineStage stage) + public static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, IRuntimeState runtimeState, PipelineStage stage) { //Create the default options and provider var authOptions = app.CreateUmbracoCookieAuthOptions(); @@ -165,58 +166,57 @@ namespace Umbraco.Web.Security.Identity }; - return app.UseUmbracoBackOfficeCookieAuthentication(appContext, authOptions, stage); + return app.UseUmbracoBackOfficeCookieAuthentication(runtimeState, authOptions, stage); } /// /// Ensures that the UmbracoBackOfficeAuthenticationMiddleware is assigned to the pipeline /// /// - /// + /// /// Custom auth cookie options can be specified to have more control over the cookie authentication logic /// /// Configurable pipeline stage /// /// - public static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, ApplicationContext appContext, CookieAuthenticationOptions cookieOptions, PipelineStage stage) + public static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, IRuntimeState runtimeState, CookieAuthenticationOptions cookieOptions, PipelineStage stage) { - if (app == null) throw new ArgumentNullException("app"); - if (appContext == null) throw new ArgumentNullException("appContext"); - if (cookieOptions == null) throw new ArgumentNullException("cookieOptions"); - if (cookieOptions.Provider == null) throw new ArgumentNullException("cookieOptions.Provider"); - if ((cookieOptions.Provider is BackOfficeCookieAuthenticationProvider) == false) throw new ArgumentException("The cookieOptions.Provider must be of type " + typeof(BackOfficeCookieAuthenticationProvider)); - - app.UseUmbracoBackOfficeCookieAuthenticationInternal(cookieOptions, appContext, stage); + if (app == null) throw new ArgumentNullException(nameof(app)); + if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); + if (cookieOptions == null) throw new ArgumentNullException(nameof(cookieOptions)); + if (cookieOptions.Provider == null) + throw new ArgumentNullException("cookieOptions.Provider cannot be null.", nameof(cookieOptions)); + if (cookieOptions.Provider is BackOfficeCookieAuthenticationProvider == false) + throw new ArgumentException($"cookieOptions.Provider must be of type {typeof(BackOfficeCookieAuthenticationProvider)}.", nameof(cookieOptions)); + + app.UseUmbracoBackOfficeCookieAuthenticationInternal(cookieOptions, runtimeState, stage); //don't apply if app is not ready - if (appContext.IsUpgrading || appContext.IsConfigured) - { - var getSecondsOptions = app.CreateUmbracoCookieAuthOptions( - //This defines the explicit path read cookies from for this middleware - new[] {string.Format("{0}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds", GlobalSettings.Path)}); - getSecondsOptions.Provider = cookieOptions.Provider; + if (runtimeState.Level != RuntimeLevel.Upgrade && runtimeState.Level != RuntimeLevel.Run) return app; - //This is a custom middleware, we need to return the user's remaining logged in seconds - app.Use( - getSecondsOptions, - UmbracoConfig.For.UmbracoSettings().Security, - app.CreateLogger()); - } + var getSecondsOptions = app.CreateUmbracoCookieAuthOptions( + //This defines the explicit path read cookies from for this middleware + new[] {string.Format("{0}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds", GlobalSettings.Path)}); + getSecondsOptions.Provider = cookieOptions.Provider; + + //This is a custom middleware, we need to return the user's remaining logged in seconds + app.Use( + getSecondsOptions, + UmbracoConfig.For.UmbracoSettings().Security, + app.CreateLogger()); return app; } - private static void UseUmbracoBackOfficeCookieAuthenticationInternal(this IAppBuilder app, CookieAuthenticationOptions options, ApplicationContext appContext, PipelineStage stage) + private static void UseUmbracoBackOfficeCookieAuthenticationInternal(this IAppBuilder app, CookieAuthenticationOptions options, IRuntimeState runtimeState, PipelineStage stage) { - if (app == null) - { - throw new ArgumentNullException("app"); - } + if (app == null) throw new ArgumentNullException(nameof(app)); + if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); //First the normal cookie middleware app.Use(typeof(CookieAuthenticationMiddleware), app, options); - //don't apply if app isnot ready - if (appContext.IsUpgrading || appContext.IsConfigured) + //don't apply if app is not ready + if (runtimeState.Level == RuntimeLevel.Upgrade || runtimeState.Level == RuntimeLevel.Run) { //Then our custom middlewares app.Use(typeof(ForceRenewalCookieAuthenticationMiddleware), app, options, Current.UmbracoContextAccessor); @@ -224,7 +224,7 @@ namespace Umbraco.Web.Security.Identity } //Marks all of the above middlewares to execute on Authenticate - app.UseStageMarker(stage); + app.UseStageMarker(stage); } @@ -233,14 +233,14 @@ namespace Umbraco.Web.Security.Identity /// Umbraco back office configuration /// /// - /// + /// /// /// /// By default this will be configured to execute on PipelineStage.Authenticate /// - public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, ApplicationContext appContext) + public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, IRuntimeState runtimeState) { - return app.UseUmbracoBackOfficeExternalCookieAuthentication(appContext, PipelineStage.Authenticate); + return app.UseUmbracoBackOfficeExternalCookieAuthentication(runtimeState, PipelineStage.Authenticate); } /// @@ -248,13 +248,13 @@ namespace Umbraco.Web.Security.Identity /// Umbraco back office configuration /// /// - /// + /// /// /// - public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, ApplicationContext appContext, PipelineStage stage) + public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, IRuntimeState runtimeState, PipelineStage stage) { - if (app == null) throw new ArgumentNullException("app"); - if (appContext == null) throw new ArgumentNullException("appContext"); + if (app == null) throw new ArgumentNullException(nameof(app)); + if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); app.UseCookieAuthentication(new CookieAuthenticationOptions { @@ -263,7 +263,7 @@ namespace Umbraco.Web.Security.Identity CookieName = Constants.Security.BackOfficeExternalCookieName, ExpireTimeSpan = TimeSpan.FromMinutes(5), //Custom cookie manager so we can filter requests - CookieManager = new BackOfficeCookieManager(Current.UmbracoContextAccessor), + CookieManager = new BackOfficeCookieManager(Current.UmbracoContextAccessor, Current.RuntimeState), CookiePath = "/", CookieSecure = GlobalSettings.UseSSL ? CookieSecureOption.Always : CookieSecureOption.SameAsRequest, CookieHttpOnly = true, @@ -277,7 +277,7 @@ namespace Umbraco.Web.Security.Identity /// In order for preview to work this needs to be called /// /// - /// + /// /// /// /// This ensures that during a preview request that the back office use is also Authenticated and that the back office Identity @@ -286,43 +286,37 @@ namespace Umbraco.Web.Security.Identity /// /// By default this will be configured to execute on PipelineStage.PostAuthenticate /// - public static IAppBuilder UseUmbracoPreviewAuthentication(this IAppBuilder app, ApplicationContext appContext) + public static IAppBuilder UseUmbracoPreviewAuthentication(this IAppBuilder app, IRuntimeState runtimeState) { - return app.UseUmbracoPreviewAuthentication(appContext, PipelineStage.PostAuthenticate); + return app.UseUmbracoPreviewAuthentication(runtimeState, PipelineStage.PostAuthenticate); } /// /// In order for preview to work this needs to be called /// /// - /// + /// /// /// /// /// This ensures that during a preview request that the back office use is also Authenticated and that the back office Identity /// is added as a secondary identity to the current IPrincipal so it can be used to Authorize the previewed document. /// - public static IAppBuilder UseUmbracoPreviewAuthentication(this IAppBuilder app, ApplicationContext appContext, PipelineStage stage) + public static IAppBuilder UseUmbracoPreviewAuthentication(this IAppBuilder app, IRuntimeState runtimeState, PipelineStage stage) { - //don't apply if app isnot ready - if (appContext.IsConfigured) - { - var authOptions = app.CreateUmbracoCookieAuthOptions(); - app.Use(typeof(PreviewAuthenticationMiddleware), authOptions); + if (runtimeState.Level != RuntimeLevel.Run) return app; - // This middleware must execute at least on PostAuthentication, by default it is on Authorize - // The middleware needs to execute after the RoleManagerModule executes which is during PostAuthenticate, - // currently I've had 100% success with ensuring this fires after RoleManagerModule even if this is set - // to PostAuthenticate though not sure if that's always a guarantee so by default it's Authorize. - if (stage < PipelineStage.PostAuthenticate) - { - throw new InvalidOperationException("The stage specified for UseUmbracoPreviewAuthentication must be greater than or equal to " + PipelineStage.PostAuthenticate); - } + var authOptions = app.CreateUmbracoCookieAuthOptions(); + app.Use(typeof(PreviewAuthenticationMiddleware), authOptions); + // This middleware must execute at least on PostAuthentication, by default it is on Authorize + // The middleware needs to execute after the RoleManagerModule executes which is during PostAuthenticate, + // currently I've had 100% success with ensuring this fires after RoleManagerModule even if this is set + // to PostAuthenticate though not sure if that's always a guarantee so by default it's Authorize. + if (stage < PipelineStage.PostAuthenticate) + throw new InvalidOperationException("The stage specified for UseUmbracoPreviewAuthentication must be greater than or equal to " + PipelineStage.PostAuthenticate); - app.UseStageMarker(stage); - } - + app.UseStageMarker(stage); return app; } diff --git a/src/Umbraco.Web/Security/Identity/BackOfficeCookieManager.cs b/src/Umbraco.Web/Security/Identity/BackOfficeCookieManager.cs index a874c12832..ba420b8804 100644 --- a/src/Umbraco.Web/Security/Identity/BackOfficeCookieManager.cs +++ b/src/Umbraco.Web/Security/Identity/BackOfficeCookieManager.cs @@ -6,7 +6,6 @@ using Microsoft.Owin; using Microsoft.Owin.Infrastructure; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.IO; namespace Umbraco.Web.Security.Identity { @@ -20,19 +19,20 @@ namespace Umbraco.Web.Security.Identity internal class BackOfficeCookieManager : ChunkingCookieManager, ICookieManager { private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IRuntimeState _runtime; private readonly string[] _explicitPaths; private readonly string _getRemainingSecondsPath; - public BackOfficeCookieManager(IUmbracoContextAccessor umbracoContextAccessor) - : this(umbracoContextAccessor, null) - { - - } - public BackOfficeCookieManager(IUmbracoContextAccessor umbracoContextAccessor, IEnumerable explicitPaths) + public BackOfficeCookieManager(IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtime) + : this(umbracoContextAccessor, runtime, null) + { } + + public BackOfficeCookieManager(IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtime, IEnumerable explicitPaths) { _umbracoContextAccessor = umbracoContextAccessor; - _explicitPaths = explicitPaths == null ? null : explicitPaths.ToArray(); - _getRemainingSecondsPath = string.Format("{0}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds", GlobalSettings.Path); + _runtime = runtime; + _explicitPaths = explicitPaths?.ToArray(); + _getRemainingSecondsPath = $"{GlobalSettings.Path}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds"; } /// @@ -51,10 +51,10 @@ namespace Umbraco.Web.Security.Identity return ShouldAuthenticateRequest( context, _umbracoContextAccessor.UmbracoContext.OriginalRequestUrl) == false - //Don't auth request, don't return a cookie - ? null - //Return the default implementation - : base.GetRequestCookie(context, key); + //Don't auth request, don't return a cookie + ? null + //Return the default implementation + : GetRequestCookie(context, key); } /// @@ -73,15 +73,14 @@ namespace Umbraco.Web.Security.Identity /// internal bool ShouldAuthenticateRequest(IOwinContext ctx, Uri originalRequestUrl, bool checkForceAuthTokens = true) { - if (_umbracoContextAccessor.UmbracoContext.Application.IsConfigured == false - && _umbracoContextAccessor.UmbracoContext.Application.DatabaseContext.IsDatabaseConfigured == false) - { - //Do not authenticate the request if we don't have a db and we are not configured - since we will never need - // to know a current user in this scenario - we treat it as a new install. Without this we can have some issues - // when people have older invalid cookies on the same domain since our user managers might attempt to lookup a user - // and we don't even have a db. + // Do not authenticate the request if we are not running (don't have a db, are not configured) - since we will never need + // to know a current user in this scenario - we treat it as a new install. Without this we can have some issues + // when people have older invalid cookies on the same domain since our user managers might attempt to lookup a user + // and we don't even have a db. + // was: app.IsConfigured == false (equiv to !Run) && dbContext.IsDbConfigured == false (equiv to Install) + // so, we handle .Install here and NOT .Upgrade + if (_runtime.Level == RuntimeLevel.Install) return false; - } var request = ctx.Request; var httpCtx = ctx.TryGetHttpContext(); diff --git a/src/Umbraco.Web/Security/Identity/UmbracoBackOfficeCookieAuthOptions.cs b/src/Umbraco.Web/Security/Identity/UmbracoBackOfficeCookieAuthOptions.cs index f528bc09f1..79f4caf5f9 100644 --- a/src/Umbraco.Web/Security/Identity/UmbracoBackOfficeCookieAuthOptions.cs +++ b/src/Umbraco.Web/Security/Identity/UmbracoBackOfficeCookieAuthOptions.cs @@ -45,7 +45,7 @@ namespace Umbraco.Web.Security.Identity CookiePath = "/"; //Custom cookie manager so we can filter requests - CookieManager = new BackOfficeCookieManager(Current.UmbracoContextAccessor, explicitPaths); + CookieManager = new BackOfficeCookieManager(Current.UmbracoContextAccessor, Current.RuntimeState, explicitPaths); } public UmbracoBackOfficeCookieAuthOptions( diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index 6fb8a27247..390642e54c 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -13,6 +13,7 @@ using Umbraco.Web.Models; using Umbraco.Web.PublishedCache; using Umbraco.Core.Cache; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Services; using Umbraco.Web.Security.Providers; using MPE = global::Umbraco.Core.Security.MembershipProviderExtensions; @@ -25,21 +26,24 @@ namespace Umbraco.Web.Security { private readonly MembershipProvider _membershipProvider; private readonly RoleProvider _roleProvider; - private readonly ApplicationContext _applicationContext; + //private readonly ApplicationContext _applicationContext; private readonly HttpContextBase _httpContext; private readonly IPublishedMemberCache _memberCache; + // fixme - inject! + private readonly IMemberService _memberService = Current.Services.MemberService; + private readonly IMemberTypeService _memberTypeService = Current.Services.MemberTypeService; + private readonly CacheHelper _applicationCache = Current.ApplicationCache; + #region Constructors // used here and there for IMember operations (not front-end stuff, no need for _memberCache) - public MembershipHelper(ApplicationContext applicationContext, HttpContextBase httpContext) + public MembershipHelper(HttpContextBase httpContext) { - if (applicationContext == null) throw new ArgumentNullException(nameof(applicationContext)); if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); - _applicationContext = applicationContext; _httpContext = httpContext; _membershipProvider = MPE.GetMembersMembershipProvider(); - _roleProvider = Roles.Enabled ? Roles.Provider : new MembersRoleProvider(applicationContext.Services.MemberService); + _roleProvider = Roles.Enabled ? Roles.Provider : new MembersRoleProvider(_memberService); // _memberCache remains null - not supposed to use it // alternatively we'd need to get if from the 'current' UmbracoContext? @@ -47,7 +51,7 @@ namespace Umbraco.Web.Security // used everywhere public MembershipHelper(UmbracoContext umbracoContext) - : this(umbracoContext, MPE.GetMembersMembershipProvider(), Roles.Enabled ? Roles.Provider: new MembersRoleProvider(umbracoContext.Application.Services.MemberService)) + : this(umbracoContext, MPE.GetMembersMembershipProvider(), Roles.Enabled ? Roles.Provider : new MembersRoleProvider(Current.Services.MemberService)) { } // used in tests and (this) @@ -57,7 +61,6 @@ namespace Umbraco.Web.Security if (membershipProvider == null) throw new ArgumentNullException(nameof(membershipProvider)); if (roleProvider == null) throw new ArgumentNullException(nameof(roleProvider)); _httpContext = umbracoContext.HttpContext; - _applicationContext = umbracoContext.Application; _membershipProvider = membershipProvider; _roleProvider = roleProvider; _memberCache = umbracoContext.Facade.MemberCache; @@ -143,7 +146,7 @@ namespace Umbraco.Web.Security } } - _applicationContext.Services.MemberService.Save(member); + _memberService.Save(member); //reset the FormsAuth cookie since the username might have changed FormsAuthentication.SetAuthCookie(member.Username, true); @@ -178,7 +181,7 @@ namespace Umbraco.Web.Security if (status != MembershipCreateStatus.Success) return null; - var member = _applicationContext.Services.MemberService.GetByUsername(membershipUser.UserName); + var member = _memberService.GetByUsername(membershipUser.UserName); member.Name = model.Name; if (model.MemberProperties != null) @@ -190,7 +193,7 @@ namespace Umbraco.Web.Security } } - _applicationContext.Services.MemberService.Save(member); + _memberService.Save(member); } else { @@ -372,7 +375,7 @@ namespace Umbraco.Web.Security if (provider.IsUmbracoMembershipProvider()) { memberTypeAlias = memberTypeAlias ?? Constants.Conventions.MemberTypes.DefaultAlias; - var memberType = _applicationContext.Services.MemberTypeService.Get(memberTypeAlias); + var memberType = _memberTypeService.Get(memberTypeAlias); if (memberType == null) throw new InvalidOperationException("Could not find a member type with alias " + memberTypeAlias); @@ -800,7 +803,7 @@ namespace Umbraco.Web.Security /// private IMember GetCurrentPersistedMember() { - return _applicationContext.ApplicationCache.RequestCache.GetCacheItem( + return _applicationCache.RequestCache.GetCacheItem( GetCacheKey("GetCurrentPersistedMember"), () => { var provider = _membershipProvider; @@ -810,7 +813,7 @@ namespace Umbraco.Web.Security throw new NotSupportedException("An IMember model can only be retreived when using the built-in Umbraco membership providers"); } var username = provider.GetCurrentUserName(); - var member = _applicationContext.Services.MemberService.GetByUsername(username); + var member = _memberService.GetByUsername(username); return member; }); } diff --git a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs index c5ddf795e1..11a7062053 100644 --- a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.Security.Providers public class MembersMembershipProvider : UmbracoMembershipProvider, IUmbracoMemberTypeMembershipProvider { public MembersMembershipProvider() - : this(ApplicationContext.Current.Services.MemberService, ApplicationContext.Current.Services.MemberTypeService) + : this(Current.Services.MemberService, Current.Services.MemberTypeService) { } diff --git a/src/Umbraco.Web/Security/Providers/MembersRoleProvider.cs b/src/Umbraco.Web/Security/Providers/MembersRoleProvider.cs index 2ddbc0b5a2..8dda8078d2 100644 --- a/src/Umbraco.Web/Security/Providers/MembersRoleProvider.cs +++ b/src/Umbraco.Web/Security/Providers/MembersRoleProvider.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Security.Providers } public MembersRoleProvider() - : this(ApplicationContext.Current.Services.MemberService) + : this(Current.Services.MemberService) { } diff --git a/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs index e7d8fa4d22..041acdd036 100644 --- a/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.Security.Providers { public UsersMembershipProvider() - : this(ApplicationContext.Current.Services.UserService, ApplicationContext.Current.Services.MemberTypeService) + : this(Current.Services.UserService, Current.Services.MemberTypeService) { } diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index e50bd5a0bd..635003824d 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -22,14 +22,14 @@ namespace Umbraco.Web.Security public class WebSecurity : DisposableObject { private HttpContextBase _httpContext; - private ApplicationContext _applicationContext; + private readonly IUserService _userService; - public WebSecurity(HttpContextBase httpContext, ApplicationContext applicationContext) + public WebSecurity(HttpContextBase httpContext, IUserService userService) { _httpContext = httpContext; - _applicationContext = applicationContext; + _userService = userService; } - + /// /// Returns true or false if the currently logged in member is authorized based on the parameters provided /// @@ -45,11 +45,11 @@ namespace Umbraco.Web.Security IEnumerable allowGroups = null, IEnumerable allowMembers = null) { - if (HttpContext.Current == null || ApplicationContext.Current == null) + if (HttpContext.Current == null || Current.RuntimeState.Level != RuntimeLevel.Run) { return false; } - var helper = new MembershipHelper(ApplicationContext.Current, new HttpContextWrapper(HttpContext.Current)); + var helper = new MembershipHelper(new HttpContextWrapper(HttpContext.Current)); return helper.IsMemberAuthorized(allowAll, allowTypes, allowGroups, allowMembers); } @@ -71,7 +71,7 @@ namespace Umbraco.Web.Security { return null; } - _currentUser = _applicationContext.Services.UserService.GetUserById(id); + _currentUser = _userService.GetUserById(id); } return _currentUser; @@ -124,7 +124,7 @@ namespace Umbraco.Web.Security var owinCtx = _httpContext.GetOwinContext(); //ensure it's done for owin too owinCtx.Authentication.SignOut(Constants.Security.BackOfficeExternalAuthenticationType); - + var user = UserManager.FindByIdAsync(userId).Result; var userData = Mapper.Map(user); _httpContext.SetPrincipalForRequest(userData); @@ -136,7 +136,7 @@ namespace Umbraco.Web.Security [Obsolete("This method should not be used, login is performed by the OWIN pipeline, use the overload that returns double and accepts a UserId instead")] public virtual FormsAuthenticationTicket PerformLogin(IUser user) { - //clear the external cookie - we do this first without owin context because we're writing cookies directly to httpcontext + //clear the external cookie - we do this first without owin context because we're writing cookies directly to httpcontext // and cookie handling is different with httpcontext vs webapi and owin, normally we'd just do: //_httpContext.GetOwinContext().Authentication.SignOut(Constants.Security.BackOfficeExternalAuthenticationType); @@ -184,7 +184,7 @@ namespace Umbraco.Web.Security var membershipProvider = Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider(); return membershipProvider != null && membershipProvider.ValidateUser(username, password); } - + /// /// Returns the MembershipUser from the back office membership provider /// @@ -204,7 +204,7 @@ namespace Umbraco.Web.Security /// /// /// This will return an Iuser instance no matter what membership provider is installed for the back office, it will automatically - /// create any missing Iuser accounts if one is not found and a custom membership provider is being used. + /// create any missing Iuser accounts if one is not found and a custom membership provider is being used. /// internal IUser GetBackOfficeUser(string username) { @@ -221,7 +221,7 @@ namespace Umbraco.Web.Security } //regarldess of the membership provider used, see if this user object already exists in the umbraco data - var user = _applicationContext.Services.UserService.GetByUsername(membershipUser.UserName); + var user = _userService.GetByUsername(membershipUser.UserName); //we're using the built-in membership provider so the user will already be available if (provider.IsUmbracoUsersProvider()) @@ -239,8 +239,8 @@ namespace Umbraco.Web.Security if (user != null) return user; //we need to create an Umbraco IUser of a 'writer' type with access to only content - this was how v6 operates. - var writer = _applicationContext.Services.UserService.GetUserTypeByAlias("writer"); - + var writer = _userService.GetUserTypeByAlias("writer"); + var email = membershipUser.Email; if (email.IsNullOrWhiteSpace()) { @@ -262,7 +262,7 @@ namespace Umbraco.Web.Security }; user.AddAllowedSection("content"); - _applicationContext.Services.UserService.Save(user); + _userService.Save(user); return user; } @@ -276,9 +276,9 @@ namespace Umbraco.Web.Security /// internal bool ValidateUserNodeTreePermissions(IUser umbracoUser, string path, string action) { - + //we only want permissions for the last node in the pat - var permission = _applicationContext.Services.UserService.GetPermissions(umbracoUser, path); + var permission = _userService.GetPermissions(umbracoUser, path); if (permission == null) throw new InvalidOperationException("No permissions found"); if (permission.AssignedPermissions.Contains(action, StringComparer.Ordinal) && (path.Contains("-20") || ("," + path + ",").Contains("," + umbracoUser.StartContentId + ","))) @@ -303,7 +303,7 @@ namespace Umbraco.Web.Security } return CurrentUser.AllowedSections.Any(uApp => uApp.InvariantEquals(app)); } - + /// /// Gets the user id. /// @@ -311,7 +311,7 @@ namespace Umbraco.Web.Security /// [Obsolete("This method is no longer used, use the GetUserId() method without parameters instead")] public int GetUserId(string umbracoUserContextId) - { + { return GetUserId(); } @@ -357,7 +357,7 @@ namespace Umbraco.Web.Security public virtual bool ValidateCurrentUser() { var result = ValidateCurrentUser(false); - return result == ValidateRequestAttempt.Success; + return result == ValidateRequestAttempt.Success; } /// @@ -368,10 +368,10 @@ namespace Umbraco.Web.Security internal ValidateRequestAttempt ValidateCurrentUser(bool throwExceptions) { //This will first check if the current user is already authenticated - which should be the case in nearly all circumstances - // since the authentication happens in the Module, that authentication also checks the ticket expiry. We don't + // since the authentication happens in the Module, that authentication also checks the ticket expiry. We don't // need to check it a second time because that requires another decryption phase and nothing can tamper with it during the request. - if (IsAuthenticated() == false) + if (IsAuthenticated() == false) { //There is no user if (throwExceptions) throw new InvalidOperationException("The user has no umbraco contextid - try logging in"); @@ -426,7 +426,7 @@ namespace Umbraco.Web.Security /// internal bool UserHasAppAccess(string app, string username) { - var user = _applicationContext.Services.UserService.GetByUsername(username); + var user = _userService.GetByUsername(username); if (user == null) { return false; @@ -439,7 +439,7 @@ namespace Umbraco.Web.Security { get { - return _httpContext.GetUmbracoAuthTicket() == null ? "" : GetSessionId(); + return _httpContext.GetUmbracoAuthTicket() == null ? "" : GetSessionId(); } set { @@ -459,7 +459,5 @@ namespace Umbraco.Web.Security { _httpContext = null; } - - } } diff --git a/src/Umbraco.Web/Services/ApplicationTreeService.cs b/src/Umbraco.Web/Services/ApplicationTreeService.cs index a101c367dc..3719c3fb08 100644 --- a/src/Umbraco.Web/Services/ApplicationTreeService.cs +++ b/src/Umbraco.Web/Services/ApplicationTreeService.cs @@ -108,7 +108,7 @@ namespace Umbraco.Web.Services new XAttribute("initialize", tree.Initialize), new XAttribute("sortOrder", tree.SortOrder), new XAttribute("alias", tree.Alias), - new XAttribute("application", tree.ApplicationAlias), + new XAttribute("application", tree.ApplicationAlias), new XAttribute("iconClosed", tree.IconClosed), new XAttribute("iconOpen", tree.IconOpened), new XAttribute("type", tree.Type))); @@ -125,7 +125,7 @@ namespace Umbraco.Web.Services new XAttribute("iconOpen", tree.IconOpened), new XAttribute("type", tree.Type))); } - + } count++; } @@ -282,7 +282,7 @@ namespace Umbraco.Web.Services } /// - /// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the + /// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the /// callback with the xml document and saves the structure back to disk if saveAfterCallback is true. /// /// @@ -300,7 +300,7 @@ namespace Umbraco.Web.Services var hasChanges = callback.Invoke(doc); if (saveAfterCallbackIfChanges && hasChanges - //Don't save it if it is empty, in some very rare cases if the app domain get's killed in the middle of this process + //Don't save it if it is empty, in some very rare cases if the app domain get's killed in the middle of this process // in some insane way the file saved will be empty. I'm pretty sure it's not actually anything to do with the xml doc and // more about the IO trying to save the XML doc, but it doesn't hurt to check. && doc.Root != null && doc.Root.Elements().Any()) @@ -349,8 +349,8 @@ namespace Umbraco.Web.Services { list.Add(new ApplicationTree( addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value), - addElement.Attribute("sortOrder") != null - ? Convert.ToByte(addElement.Attribute("sortOrder").Value) + addElement.Attribute("sortOrder") != null + ? Convert.ToByte(addElement.Attribute("sortOrder").Value) : (byte)0, (string)addElement.Attribute("application"), (string)addElement.Attribute("alias"), @@ -408,7 +408,7 @@ namespace Umbraco.Web.Services var added = new List(); // Load all Controller Trees by attribute - var types = PluginManager.Current.ResolveTypesWithAttribute(); + var types = Current.PluginManager.ResolveTypesWithAttribute(); // fixme inject //convert them to ApplicationTree instances var items = types .Select(x => diff --git a/src/Umbraco.Web/Services/SectionService.cs b/src/Umbraco.Web/Services/SectionService.cs index b0f82a17cc..d1cdf4c942 100644 --- a/src/Umbraco.Web/Services/SectionService.cs +++ b/src/Umbraco.Web/Services/SectionService.cs @@ -43,7 +43,7 @@ namespace Umbraco.Web.Services _cache = cache; _allAvailableSections = new Lazy>(() => new LazyEnumerableSections()); } - + /// /// gets/sets the application.config file path @@ -63,7 +63,7 @@ namespace Umbraco.Web.Services } set { _appConfig = value; } } - + /// /// The cache storage for all applications /// @@ -74,15 +74,15 @@ namespace Umbraco.Web.Services () => { var list = ReadFromXmlAndSort(); - var hasChanges = false; + var hasChanges = false; var localCopyList = list; LoadXml(doc => { //Now, load in the xml structure and update it with anything that is not declared there and save the file. - //NOTE: On the first iteration here, it will lazily scan all apps, etc... this is because this ienumerable is lazy + //NOTE: On the first iteration here, it will lazily scan all apps, etc... this is because this ienumerable is lazy //Get all the trees not registered in the config - + var unregistered = _allAvailableSections.Value .Where(x => localCopyList.Any(l => l.Alias == x.Alias) == false) .ToArray(); @@ -149,7 +149,7 @@ namespace Umbraco.Web.Services /// public IEnumerable
GetAllowedSections(int userId) { - + var user = _userService.GetUserById(userId); if (user == null) { @@ -188,7 +188,7 @@ namespace Umbraco.Web.Services /// The icon. /// The sort order. public void MakeNew(string name, string alias, string icon, int sortOrder) - { + { if (GetSections().All(x => x.Alias != alias)) { LoadXml(doc => @@ -208,7 +208,7 @@ namespace Umbraco.Web.Services /// /// Deletes the section - /// + ///
public void DeleteSection(Section section) { lock (Locker) @@ -237,8 +237,8 @@ namespace Umbraco.Web.Services }, true); //raise event - OnDeleted(section, new EventArgs()); - } + OnDeleted(section, new EventArgs()); + } } private List
ReadFromXmlAndSort() @@ -263,7 +263,7 @@ namespace Umbraco.Web.Services }, false); return tmp; - } + } internal static event TypedEventHandler Deleted; private static void OnDeleted(Section app, EventArgs args) @@ -295,10 +295,10 @@ namespace Umbraco.Web.Services // Load all Applications by attribute and add them to the XML config //don't cache the result of this because it is only used once during app startup, caching will just add a bit more mem overhead for no reason - var types = PluginManager.Current.ResolveTypesWithAttribute(cacheResult: false); + var types = Current.PluginManager.ResolveTypesWithAttribute(cacheResult: false); // fixme - inject - //since applications don't populate their metadata from the attribute and because it is an interface, - //we need to interrogate the attributes for the data. Would be better to have a base class that contains + //since applications don't populate their metadata from the attribute and because it is an interface, + //we need to interrogate the attributes for the data. Would be better to have a base class that contains //metadata populated by the attribute. Oh well i guess. var attrs = types.Select(x => x.GetCustomAttributes(false).Single()); return Enumerable.ToArray
(attrs.Select(x => new Section(x.Name, x.Alias, x.Icon, x.SortOrder))); diff --git a/src/Umbraco.Web/Strategies/ServerRegistrationEventHandler.cs b/src/Umbraco.Web/Strategies/DatabaseServerRegistrationComponent.cs similarity index 79% rename from src/Umbraco.Web/Strategies/ServerRegistrationEventHandler.cs rename to src/Umbraco.Web/Strategies/DatabaseServerRegistrationComponent.cs index f2354a71a0..f1aa07413c 100644 --- a/src/Umbraco.Web/Strategies/ServerRegistrationEventHandler.cs +++ b/src/Umbraco.Web/Strategies/DatabaseServerRegistrationComponent.cs @@ -1,158 +1,153 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using System.Web; -using Newtonsoft.Json; -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Core.Services; -using Umbraco.Core.Sync; -using Umbraco.Web.Routing; -using Umbraco.Web.Scheduling; - -namespace Umbraco.Web.Strategies -{ - /// - /// Ensures that servers are automatically registered in the database, when using the database server registrar. - /// - /// - /// At the moment servers are automatically registered upon first request and then on every - /// request but not more than once per (configurable) period. This really is "for information & debug" purposes so - /// we can look at the table and see what servers are registered - but the info is not used anywhere. - /// Should we actually want to use this, we would need a better and more deterministic way of figuring - /// out the "server address" ie the address to which server-to-server requests should be sent - because it - /// probably is not the "current request address" - especially in multi-domains configurations. - /// - public sealed class ServerRegistrationEventHandler : ApplicationEventHandler - { - private DatabaseServerRegistrar _registrar; - private BackgroundTaskRunner _backgroundTaskRunner; - private bool _started = false; - private TouchServerTask _task; - private object _lock = new object(); - - // bind to events - protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) - { - _registrar = Current.ServerRegistrar as DatabaseServerRegistrar; - - // only for the DatabaseServerRegistrar - if (_registrar == null) return; - - _backgroundTaskRunner = new BackgroundTaskRunner( - new BackgroundTaskRunnerOptions { AutoStart = true }, - applicationContext.ProfilingLogger.Logger); - - //We will start the whole process when a successful request is made - UmbracoModule.RouteAttempt += UmbracoModuleRouteAttempt; - } - - /// - /// Handle when a request is made - /// - /// - /// - /// - /// We require this because: - /// - ApplicationContext.UmbracoApplicationUrl is initialized by UmbracoModule in BeginRequest - /// - RegisterServer is called on UmbracoModule.RouteAttempt which is triggered in ProcessRequest - /// we are safe, UmbracoApplicationUrl has been initialized - /// - private void UmbracoModuleRouteAttempt(object sender, RoutableAttemptEventArgs e) - { - switch (e.Outcome) - { - case EnsureRoutableOutcome.IsRoutable: - case EnsureRoutableOutcome.NotDocumentRequest: - RegisterBackgroundTasks(e); - break; - } - } - - private void RegisterBackgroundTasks(UmbracoRequestEventArgs e) - { - //remove handler, we're done - UmbracoModule.RouteAttempt -= UmbracoModuleRouteAttempt; - - //only perform this one time ever - LazyInitializer.EnsureInitialized(ref _task, ref _started, ref _lock, () => - { - var serverAddress = e.UmbracoContext.Application.UmbracoApplicationUrl; - var svc = e.UmbracoContext.Application.Services.ServerRegistrationService; - - var task = new TouchServerTask(_backgroundTaskRunner, - 15000, //delay before first execution - _registrar.Options.RecurringSeconds*1000, //amount of ms between executions - svc, _registrar, serverAddress); - - //Perform the rest async, we don't want to block the startup sequence - // this will just reoccur on a background thread - _backgroundTaskRunner.TryAdd(task); - - return task; - }); - } - - private class TouchServerTask : RecurringTaskBase - { - private readonly IServerRegistrationService _svc; - private readonly DatabaseServerRegistrar _registrar; - private readonly string _serverAddress; - - /// - /// Initializes a new instance of the class. - /// - /// The task runner. - /// The delay. - /// The period. - /// - /// - /// - /// The task will repeat itself periodically. Use this constructor to create a new task. - public TouchServerTask(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - IServerRegistrationService svc, DatabaseServerRegistrar registrar, string serverAddress) - : base(runner, delayMilliseconds, periodMilliseconds) - { - if (svc == null) throw new ArgumentNullException("svc"); - _svc = svc; - _registrar = registrar; - _serverAddress = serverAddress; - } - - public override bool IsAsync - { - get { return false; } - } - - public override bool RunsOnShutdown - { - get { return false; } - } - - /// - /// Runs the background task. - /// - /// A value indicating whether to repeat the task. - public override bool PerformRun() - { - try - { - _svc.TouchServer(_serverAddress, _svc.CurrentServerIdentity, _registrar.Options.StaleServerTimeout); - - return true; // repeat - } - catch (Exception ex) - { - LogHelper.Error("Failed to update server record in database.", ex); - - return false; // probably stop if we have an error - } - } - - public override Task PerformRunAsync(CancellationToken token) - { - throw new NotImplementedException(); - } - } - } -} +using System; +using System.Threading; +using System.Threading.Tasks; +using Umbraco.Core; +using Umbraco.Core.Components; +using Umbraco.Core.Logging; +using Umbraco.Core.Services; +using Umbraco.Core.Sync; +using Umbraco.Web.Routing; +using Umbraco.Web.Scheduling; + +namespace Umbraco.Web.Strategies +{ + /// + /// Ensures that servers are automatically registered in the database, when using the database server registrar. + /// + /// + /// At the moment servers are automatically registered upon first request and then on every + /// request but not more than once per (configurable) period. This really is "for information & debug" purposes so + /// we can look at the table and see what servers are registered - but the info is not used anywhere. + /// Should we actually want to use this, we would need a better and more deterministic way of figuring + /// out the "server address" ie the address to which server-to-server requests should be sent - because it + /// probably is not the "current request address" - especially in multi-domains configurations. + /// + public sealed class DatabaseServerRegistrationComponent : UmbracoComponentBase, IUmbracoCoreComponent + { + private object _locker = new object(); + private DatabaseServerRegistrar _registrar; + private IRuntimeState _runtime; + private IServerRegistrationService _registrationService; + private BackgroundTaskRunner _backgroundTaskRunner; + private bool _started; + private TouchServerTask _task; + + public void Initialize(IRuntimeState runtime, IServerRegistrar serverRegistrar, IServerRegistrationService registrationService, ILogger logger) + { + _registrar = serverRegistrar as DatabaseServerRegistrar; + + // only for the DatabaseServerRegistrar + if (_registrar == null) return; + + _runtime = runtime; + _registrationService = registrationService; + + _backgroundTaskRunner = new BackgroundTaskRunner( + new BackgroundTaskRunnerOptions { AutoStart = true }, + logger); + + //We will start the whole process when a successful request is made + UmbracoModule.RouteAttempt += UmbracoModuleRouteAttempt; + } + + /// + /// Handle when a request is made + /// + /// + /// + /// + /// We require this because: + /// - ApplicationContext.UmbracoApplicationUrl is initialized by UmbracoModule in BeginRequest + /// - RegisterServer is called on UmbracoModule.RouteAttempt which is triggered in ProcessRequest + /// we are safe, UmbracoApplicationUrl has been initialized + /// + private void UmbracoModuleRouteAttempt(object sender, RoutableAttemptEventArgs e) + { + switch (e.Outcome) + { + case EnsureRoutableOutcome.IsRoutable: + case EnsureRoutableOutcome.NotDocumentRequest: + RegisterBackgroundTasks(e); + break; + } + } + + private void RegisterBackgroundTasks(UmbracoRequestEventArgs e) + { + // remove handler, we're done + UmbracoModule.RouteAttempt -= UmbracoModuleRouteAttempt; + + // only perform this one time ever + LazyInitializer.EnsureInitialized(ref _task, ref _started, ref _locker, () => + { + var serverAddress = _runtime.ApplicationUrl.ToString(); + var svc = _registrationService; + + var task = new TouchServerTask(_backgroundTaskRunner, + 15000, //delay before first execution + _registrar.Options.RecurringSeconds*1000, //amount of ms between executions + svc, _registrar, serverAddress); + + // perform the rest async, we don't want to block the startup sequence + // this will just reoccur on a background thread + _backgroundTaskRunner.TryAdd(task); + + return task; + }); + } + + private class TouchServerTask : RecurringTaskBase + { + private readonly IServerRegistrationService _svc; + private readonly DatabaseServerRegistrar _registrar; + private readonly string _serverAddress; + + /// + /// Initializes a new instance of the class. + /// + /// The task runner. + /// The delay. + /// The period. + /// + /// + /// + /// The task will repeat itself periodically. Use this constructor to create a new task. + public TouchServerTask(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, + IServerRegistrationService svc, DatabaseServerRegistrar registrar, string serverAddress) + : base(runner, delayMilliseconds, periodMilliseconds) + { + if (svc == null) throw new ArgumentNullException(nameof(svc)); + _svc = svc; + _registrar = registrar; + _serverAddress = serverAddress; + } + + public override bool IsAsync => false; + + public override bool RunsOnShutdown => false; + + /// + /// Runs the background task. + /// + /// A value indicating whether to repeat the task. + public override bool PerformRun() + { + try + { + _svc.TouchServer(_serverAddress, _svc.CurrentServerIdentity, _registrar.Options.StaleServerTimeout); + return true; // repeat + } + catch (Exception ex) + { + LogHelper.Error("Failed to update server record in database.", ex); + return false; // probably stop if we have an error + } + } + + public override Task PerformRunAsync(CancellationToken token) + { + throw new NotImplementedException(); + } + } + } +} diff --git a/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHandler.cs b/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHandler.cs index 3b40bbdf5d..8bfda241ff 100644 --- a/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHandler.cs +++ b/src/Umbraco.Web/Strategies/Migrations/MigrationStartupHandler.cs @@ -38,7 +38,7 @@ namespace Umbraco.Web.Strategies.Migrations ///
/// /// - protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication) { MigrationRunner.Migrated += MigrationRunner_Migrated; } diff --git a/src/Umbraco.Web/Strategies/NotificationsComponent.cs b/src/Umbraco.Web/Strategies/NotificationsComponent.cs new file mode 100644 index 0000000000..b6e2291f39 --- /dev/null +++ b/src/Umbraco.Web/Strategies/NotificationsComponent.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using Umbraco.Core; +using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Services; +using Umbraco.Core.Components; +using Umbraco.Web._Legacy.Actions; +using Umbraco.Core.Models; + +namespace Umbraco.Web.Strategies +{ + public sealed class NotificationsComponent : UmbracoComponentBase, IUmbracoCoreComponent + { + public void Initialize(INotificationService notificationService) + { + ContentService.SentToPublish += (sender, args) => + notificationService.SendNotification(args.Entity, ActionToPublish.Instance); + + //Send notifications for the published action + ContentService.Published += (sender, args) => + args.PublishedEntities.ForEach(content => notificationService.SendNotification(content, ActionPublish.Instance)); + + //Send notifications for the update and created actions + ContentService.Saved += (sender, args) => + { + var newEntities = new List(); + var updatedEntities = new List(); + + //need to determine if this is updating or if it is new + foreach (var entity in args.SavedEntities) + { + var dirty = (IRememberBeingDirty) entity; + if (dirty.WasPropertyDirty("Id")) + { + //it's new + newEntities.Add(entity); + } + else + { + //it's updating + updatedEntities.Add(entity); + } + } + notificationService.SendNotification(newEntities, ActionNew.Instance); + notificationService.SendNotification(updatedEntities, ActionUpdate.Instance); + }; + + //Send notifications for the delete action + ContentService.Deleted += (sender, args) => + args.DeletedEntities.ForEach(content => notificationService.SendNotification(content, ActionDelete.Instance)); + + //Send notifications for the unpublish action + ContentService.UnPublished += (sender, args) => + args.PublishedEntities.ForEach(content => notificationService.SendNotification(content, ActionUnPublish.Instance)); + } + } +} diff --git a/src/Umbraco.Web/Strategies/NotificationsHandler.cs b/src/Umbraco.Web/Strategies/NotificationsHandler.cs deleted file mode 100644 index a13c9ceda3..0000000000 --- a/src/Umbraco.Web/Strategies/NotificationsHandler.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.Models.EntityBase; -using Umbraco.Core.Services; -using umbraco; -using Umbraco.Web._Legacy.Actions; -using Umbraco.Core.Models; - -namespace Umbraco.Web.Strategies -{ - /// - /// Subscribes to the relavent events in order to send out notifications - /// - public sealed class NotificationsHandler : ApplicationEventHandler - { - - protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) - { - base.ApplicationStarted(umbracoApplication, applicationContext); - - ContentService.SentToPublish += (sender, args) => - applicationContext.Services.NotificationService.SendNotification( - args.Entity, ActionToPublish.Instance, applicationContext); - - //Send notifications for the published action - ContentService.Published += (sender, args) => - args.PublishedEntities.ForEach( - content => - applicationContext.Services.NotificationService.SendNotification( - content, ActionPublish.Instance, applicationContext)); - - //Send notifications for the update and created actions - ContentService.Saved += (sender, args) => - { - var newEntities = new List(); - var updatedEntities = new List(); - - //need to determine if this is updating or if it is new - foreach (var entity in args.SavedEntities) - { - var dirty = (IRememberBeingDirty) entity; - if (dirty.WasPropertyDirty("Id")) - { - //it's new - newEntities.Add(entity); - } - else - { - //it's updating - updatedEntities.Add(entity); - } - } - applicationContext.Services.NotificationService.SendNotification(newEntities, ActionNew.Instance, applicationContext); - applicationContext.Services.NotificationService.SendNotification(updatedEntities, ActionUpdate.Instance, applicationContext); - }; - - //Send notifications for the delete action - ContentService.Deleted += (sender, args) => - args.DeletedEntities.ForEach( - content => - applicationContext.Services.NotificationService.SendNotification( - content, ActionDelete.Instance, applicationContext)); - - //Send notifications for the unpublish action - ContentService.UnPublished += (sender, args) => - args.PublishedEntities.ForEach( - content => - applicationContext.Services.NotificationService.SendNotification( - content, ActionUnPublish.Instance, applicationContext)); - - } - } -} diff --git a/src/Umbraco.Web/Strategies/PublicAccessEventHandler.cs b/src/Umbraco.Web/Strategies/PublicAccessEventHandler.cs index d543567ac3..275b00c72f 100644 --- a/src/Umbraco.Web/Strategies/PublicAccessEventHandler.cs +++ b/src/Umbraco.Web/Strategies/PublicAccessEventHandler.cs @@ -14,9 +14,9 @@ namespace Umbraco.Web.Strategies ///
public sealed class PublicAccessEventHandler : ApplicationEventHandler { - protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication) { - base.ApplicationStarted(umbracoApplication, applicationContext); + base.ApplicationStarted(umbracoApplication); MemberGroupService.Saved += MemberGroupService_Saved; } @@ -31,7 +31,7 @@ namespace Umbraco.Web.Strategies && grp.AdditionalData["previousName"].ToString().IsNullOrWhiteSpace() == false && grp.AdditionalData["previousName"].ToString() != grp.Name) { - ApplicationContext.Current.Services.PublicAccessService.RenameMemberGroupRoleRules(grp.AdditionalData["previousName"].ToString(), grp.Name); + Current.Services.PublicAccessService.RenameMemberGroupRoleRules(grp.AdditionalData["previousName"].ToString(), grp.Name); } } } diff --git a/src/Umbraco.Web/Templates/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs index 92f547343f..fe34036571 100644 --- a/src/Umbraco.Web/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs @@ -12,6 +12,7 @@ using Umbraco.Web.Routing; using umbraco; using umbraco.cms.businesslogic.language; using Umbraco.Core.Configuration; +using Umbraco.Core.Services; namespace Umbraco.Web.Templates { @@ -23,6 +24,7 @@ namespace Umbraco.Web.Templates /// internal class TemplateRenderer { + private readonly IFileService _fileService = Current.Services.FileService; // fixme inject private readonly UmbracoContext _umbracoContext; private object _oldPageId; private object _oldPageElements; @@ -82,8 +84,8 @@ namespace Umbraco.Web.Templates contentRequest.PublishedContent = doc; //set the template, either based on the AltTemplate found or the standard template of the doc contentRequest.TemplateModel = UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates || AltTemplate.HasValue == false - ? _umbracoContext.Application.Services.FileService.GetTemplate(doc.TemplateId) - : _umbracoContext.Application.Services.FileService.GetTemplate(AltTemplate.Value); + ? _fileService.GetTemplate(doc.TemplateId) + : _fileService.GetTemplate(AltTemplate.Value); //if there is not template then exit if (!contentRequest.HasTemplate) diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index c2a52e1211..2d19c95511 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -1,13 +1,10 @@ using System; using System.Globalization; using System.Linq; -using System.Management.Instrumentation; using System.Net; using System.Net.Http.Formatting; using System.Threading.Tasks; using System.Web.Http; -using System.Web.Mvc; -using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; @@ -16,8 +13,6 @@ using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; -using umbraco; - namespace Umbraco.Web.Trees { [AngularJsonOnlyConfiguration] @@ -39,11 +34,11 @@ namespace Umbraco.Web.Trees var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture); //find all tree definitions that have the current application alias - var appTrees = ApplicationContext.Current.Services.ApplicationTreeService.GetApplicationTrees(application, true).ToArray(); + var appTrees = Current.Services.ApplicationTreeService.GetApplicationTrees(application, true).ToArray(); if (appTrees.Length == 1 || string.IsNullOrEmpty(tree) == false ) { - var apptree = string.IsNullOrEmpty(tree) == false + var apptree = string.IsNullOrEmpty(tree) == false ? appTrees.SingleOrDefault(x => x.Alias == tree) : appTrees.SingleOrDefault(); @@ -52,7 +47,7 @@ namespace Umbraco.Web.Trees var result = await GetRootForSingleAppTree( apptree, Constants.System.Root.ToString(CultureInfo.InvariantCulture), - queryStrings, + queryStrings, application); return result; @@ -67,7 +62,7 @@ namespace Umbraco.Web.Trees //This could be null if the tree decides not to return it's root (i.e. the member type tree does this when not in umbraco membership mode) if (rootNode != null) { - collection.Add(rootNode); + collection.Add(rootNode); } } @@ -122,9 +117,9 @@ namespace Umbraco.Web.Trees } var sectionRoot = SectionRootNode.CreateSingleTreeSectionRoot( - rootId, - rootNode.Result.ChildNodesUrl, - rootNode.Result.MenuUrl, + rootId, + rootNode.Result.ChildNodesUrl, + rootNode.Result.MenuUrl, rootNode.Result.Name, byControllerAttempt.Result); @@ -148,16 +143,16 @@ namespace Umbraco.Web.Trees "", //TODO: I think we'll need this in this situation! legacyAttempt.Result); - + sectionRoot.AdditionalData.Add("treeAlias", configTree.Alias); return sectionRoot; } throw new ApplicationException("Could not render a tree for type " + configTree.Alias); } - + } - + } diff --git a/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs b/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs index 4752e4d068..34239697c6 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeExtensions.cs @@ -161,8 +161,9 @@ namespace Umbraco.Web.Trees return Attempt.Succeed(null); } - var legacyController = new LegacyTreeController(xmlTreeNodeAttempt.Result, appTree.Alias, currentSection, urlHelper); - var newRoot = legacyController.GetRootNode(formCollection); + //var temp = new LegacyTreeController(xmlTreeNodeAttempt.Result, appTree.Alias, currentSection, urlHelper); + var temp = new TreeControllerBaseStuffForLegacy(appTree.Alias, xmlTreeNodeAttempt.Result.Text, urlHelper); + var newRoot = temp.GetRootNode(formCollection); return Attempt.Succeed(newRoot); diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index eaf6faae58..e69d48c702 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -29,7 +29,6 @@ namespace Umbraco.Web.Trees [CoreTree] public class ContentTreeController : ContentTreeControllerBase { - protected override TreeNode CreateRootNode(FormDataCollection queryStrings) { var node = base.CreateRootNode(queryStrings); diff --git a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs index ffe2cd85f8..223fee3c39 100644 --- a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs @@ -13,7 +13,6 @@ using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence; using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi.Filters; -using umbraco; using System.Globalization; using Umbraco.Web._Legacy.Actions; @@ -21,7 +20,6 @@ namespace Umbraco.Web.Trees { public abstract class ContentTreeControllerBase : TreeController { - #region Actions /// @@ -57,7 +55,7 @@ namespace Umbraco.Web.Trees protected abstract TreeNode GetSingleTreeNode(IUmbracoEntity e, string parentId, FormDataCollection queryStrings); /// - /// Returns the + /// Returns the /// protected abstract int RecycleBinId { get; } @@ -76,7 +74,7 @@ namespace Umbraco.Web.Trees /// /// /// - /// + /// protected virtual TreeNodeCollection PerformGetTreeNodes(string id, FormDataCollection queryStrings) { var nodes = new TreeNodeCollection(); @@ -91,17 +89,17 @@ namespace Umbraco.Web.Trees id = altStartId; //we need to verify that the user has access to view this node, otherwise we'll render an empty tree collection - // TODO: in the future we could return a validation statement so we can have some UI to notify the user they don't have access + // TODO: in the future we could return a validation statement so we can have some UI to notify the user they don't have access if (HasPathAccess(id, queryStrings) == false) { LogHelper.Warn("The user " + Security.CurrentUser.Username + " does not have access to the tree node " + id); return new TreeNodeCollection(); } - + // So there's an alt id specified, it's not the root node and the user has access to it, great! But there's one thing we - // need to consider: + // need to consider: // If the tree is being rendered in a dialog view we want to render only the children of the specified id, but - // when the tree is being rendered normally in a section and the current user's start node is not -1, then + // when the tree is being rendered normally in a section and the current user's start node is not -1, then // we want to include their start node in the tree as well. // Therefore, in the latter case, we want to change the id to -1 since we want to render the current user's root node // and the GetChildEntities method will take care of rendering the correct root node. @@ -111,7 +109,7 @@ namespace Umbraco.Web.Trees id = Constants.System.Root.ToString(CultureInfo.InvariantCulture); } } - + var entities = GetChildEntities(id); nodes.AddRange(entities.Select(entity => GetSingleTreeNode(entity, id, queryStrings)).Where(node => node != null)); return nodes; @@ -172,14 +170,14 @@ namespace Umbraco.Web.Trees if (queryStrings.HasKey(TreeQueryStringParameters.StartNodeId)) altStartId = queryStrings.GetValue(TreeQueryStringParameters.StartNodeId); - //check if a request has been made to render from a specific start node + //check if a request has been made to render from a specific start node if (string.IsNullOrEmpty(altStartId) == false && altStartId != "undefined" && altStartId != Constants.System.Root.ToString(CultureInfo.InvariantCulture)) { id = altStartId; } - + var nodes = GetTreeNodesInternal(id, queryStrings); - + //only render the recycle bin if we are not in dialog and the start id id still the root if (IsDialog(queryStrings) == false && id == Constants.System.Root.ToInvariantString()) { @@ -283,7 +281,7 @@ namespace Umbraco.Web.Trees /// The Document to check permissions against /// A list of MenuItems that the user has permissions to execute on the current document /// By default the user must have Browse permissions to see the node in the Content tree - /// + /// internal bool CanUserAccessNode(IUmbracoEntity doc, IEnumerable allowedUserOptions) { return allowedUserOptions.Select(x => x.Action).OfType().Any(); diff --git a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs index 4a20b727f5..7d59619c81 100644 --- a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Net.Http.Formatting; -using umbraco; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Models; @@ -46,7 +45,7 @@ namespace Umbraco.Web.Trees .OrderBy(entity => entity.Name) .Select(dt => { - var node = CreateTreeNode(dt.Id.ToString(), id, queryStrings, dt.Name, "icon-item-arrangement", + var node = CreateTreeNode(dt.Id.ToString(), id, queryStrings, dt.Name, "icon-item-arrangement", //NOTE: This is legacy now but we need to support upgrades. From 7.4+ we don't allow 'child' creations since // this is an organiational thing and we do that with folders now. dt.HasChildren()); @@ -69,7 +68,7 @@ namespace Umbraco.Web.Trees //set the default to create menu.DefaultMenuAlias = ActionNew.Instance.Alias; - // root actions + // root actions menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionImport.Instance.Alias)), true).ConvertLegacyMenuItem(new UmbracoEntity { @@ -95,7 +94,7 @@ namespace Umbraco.Web.Trees //can delete doc type menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)), true); } - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true); + menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true); } else { diff --git a/src/Umbraco.Web/Trees/DataTypeTreeController.cs b/src/Umbraco.Web/Trees/DataTypeTreeController.cs index 8da83604c5..45b29fed43 100644 --- a/src/Umbraco.Web/Trees/DataTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/DataTypeTreeController.cs @@ -1,17 +1,12 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; -using System.Net; using System.Net.Http.Formatting; -using System.Web.Http; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; -using umbraco; -using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Services; using Umbraco.Web._Legacy.Actions; using Constants = Umbraco.Core.Constants; @@ -27,8 +22,8 @@ namespace Umbraco.Web.Trees protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) { var intId = id.TryConvertTo(); - if (intId == false) throw new InvalidOperationException("Id must be an integer"); - + if (intId == false) throw new InvalidOperationException("Id must be an integer"); + var nodes = new TreeNodeCollection(); //Folders first @@ -72,13 +67,13 @@ namespace Umbraco.Web.Trees { var systemIds = new[] { - Constants.DataTypes.DefaultContentListView, - Constants.DataTypes.DefaultMediaListView, + Constants.DataTypes.DefaultContentListView, + Constants.DataTypes.DefaultMediaListView, Constants.DataTypes.DefaultMembersListView }; return systemIds; - } - + } + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { var menu = new MenuItemCollection(); @@ -88,7 +83,7 @@ namespace Umbraco.Web.Trees //set the default to create menu.DefaultMenuAlias = ActionNew.Instance.Alias; - // root actions + // root actions menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); return menu; @@ -106,7 +101,7 @@ namespace Umbraco.Web.Trees { //can delete data type menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias))); - } + } menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), hasSeparator: true); } else @@ -120,7 +115,7 @@ namespace Umbraco.Web.Trees menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionMove.Instance.Alias)), hasSeparator: true); } - + return menu; } } diff --git a/src/Umbraco.Web/Trees/DictionaryTreeController.cs b/src/Umbraco.Web/Trees/DictionaryTreeController.cs index dec233a61e..b058111ad5 100644 --- a/src/Umbraco.Web/Trees/DictionaryTreeController.cs +++ b/src/Umbraco.Web/Trees/DictionaryTreeController.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.Trees protected override TreeNode CreateRootNode(FormDataCollection queryStrings) { var node = base.CreateRootNode(queryStrings); - + // For now, this is using the legacy webforms view but will need refactoring // when the dictionary has been converted to Angular. node.RoutePath = String.Format("{0}/framed/{1}", queryStrings.GetValue("application"), @@ -58,7 +58,7 @@ namespace Umbraco.Web.Trees } else { - + var dictionaryItem = Services.LocalizationService.GetDictionaryItemById(intId); var entity = new UmbracoEntity { diff --git a/src/Umbraco.Web/Trees/FileSystemTreeController.cs b/src/Umbraco.Web/Trees/FileSystemTreeController.cs index 3c612281f5..2fc7fbb8de 100644 --- a/src/Umbraco.Web/Trees/FileSystemTreeController.cs +++ b/src/Umbraco.Web/Trees/FileSystemTreeController.cs @@ -3,12 +3,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http.Formatting; -using System.Text; -using System.Threading.Tasks; -using ClientDependency.Core; using Umbraco.Core; using Umbraco.Core.IO; -using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; using Umbraco.Web._Legacy.Actions; @@ -114,20 +110,20 @@ namespace Umbraco.Web.Trees { return new TreeNodeCollection(); } - + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { var menu = new MenuItemCollection(); - + OnBeforeRenderMenu(menu, id, queryStrings); if (id == Constants.System.Root.ToInvariantString()) { //Create the normal create action menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) - //Since we haven't implemented anything for file systems in angular, this needs to be converted to + //Since we haven't implemented anything for file systems in angular, this needs to be converted to //use the legacy format .ConvertLegacyFileSystemMenuItem("", "init" + TreeAlias, queryStrings.GetValue("application")); @@ -138,14 +134,14 @@ namespace Umbraco.Web.Trees return menu; } - + if (Directory.Exists(IOHelper.MapPath(FilePath + "/" + id))) { if (EnableCreateOnFolder) { //Create the normal create action menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) - //Since we haven't implemented anything for file systems in angular, this needs to be converted to + //Since we haven't implemented anything for file systems in angular, this needs to be converted to //use the legacy format .ConvertLegacyFileSystemMenuItem(id, TreeAlias + "Folder", queryStrings.GetValue("application")); @@ -173,7 +169,7 @@ namespace Umbraco.Web.Trees protected virtual void OnAfterRenderMenu(MenuItemCollection menu, string id, FormDataCollection queryStrings) { - + } } } diff --git a/src/Umbraco.Web/Trees/LanguageTreeController.cs b/src/Umbraco.Web/Trees/LanguageTreeController.cs index 42721672fb..176f7a01b8 100644 --- a/src/Umbraco.Web/Trees/LanguageTreeController.cs +++ b/src/Umbraco.Web/Trees/LanguageTreeController.cs @@ -1,13 +1,9 @@ using System; -using System.Data.SqlClient; using System.Globalization; using System.Net.Http.Formatting; -using System.Web.Services.Description; -using umbraco; using Umbraco.Core; using Umbraco.Core.Services; using Umbraco.Core.Models; -using umbraco.presentation.actions; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; @@ -63,15 +59,15 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { var menu = new MenuItemCollection(); - + if (id == Constants.System.Root.ToInvariantString()) { //Create the normal create action menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) - //Since we haven't implemented anything for languages in angular, this needs to be converted to + //Since we haven't implemented anything for languages in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(null, "initlanguages", queryStrings.GetValue("application")); - + //refresh action menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); @@ -83,14 +79,14 @@ namespace Umbraco.Web.Trees //add delete option for all languages menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)) - //Since we haven't implemented anything for languages in angular, this needs to be converted to + //Since we haven't implemented anything for languages in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(new UmbracoEntity { Id = lang.Id, Level = 1, ParentId = -1, - Name = lang.CultureInfo.DisplayName + Name = lang.CultureInfo.DisplayName }, "language", queryStrings.GetValue("application")); return menu; diff --git a/src/Umbraco.Web/Trees/LegacyTreeController.cs b/src/Umbraco.Web/Trees/LegacyTreeController.cs index f1bf0489d2..04edcb8063 100644 --- a/src/Umbraco.Web/Trees/LegacyTreeController.cs +++ b/src/Umbraco.Web/Trees/LegacyTreeController.cs @@ -2,44 +2,24 @@ using System.Globalization; using System.Linq; using System.Net.Http.Formatting; -using System.Web.Http.Routing; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; using umbraco.cms.presentation.Trees; namespace Umbraco.Web.Trees { - /// /// This is used to output JSON from legacy trees /// - [PluginController("UmbracoTrees")] - [LegacyTreeAuthorizeAttribute] + [PluginController("UmbracoTrees"), LegacyTreeAuthorizeAttribute] public class LegacyTreeController : TreeControllerBase { private readonly XmlTreeNode _xmlTreeNode; - private readonly string _treeAlias; private readonly string _currentSection; - private readonly string _rootDisplay; - - public LegacyTreeController() - { - - } - - public LegacyTreeController(XmlTreeNode xmlTreeNode, string treeAlias, string currentSection, UrlHelper urlHelper) - { - _xmlTreeNode = xmlTreeNode; - _treeAlias = treeAlias; - _currentSection = currentSection; - _rootDisplay = xmlTreeNode.Text; - Url = urlHelper; - } protected override TreeNode CreateRootNode(FormDataCollection queryStrings) { @@ -47,8 +27,8 @@ namespace Umbraco.Web.Trees _xmlTreeNode.NodeID, _xmlTreeNode, Url, - _currentSection, - queryStrings, + _currentSection, + queryStrings, isRoot: true); } @@ -110,18 +90,12 @@ namespace Umbraco.Web.Trees menuItem.Name = Services.TextService.Localize("actions", menuItem.Alias); } return attempt.Result; - } + } } - public override string RootNodeDisplayName - { - get { return _rootDisplay; } - } + public override string RootNodeDisplayName { get; } - public override string TreeAlias - { - get { return _treeAlias; } - } + public override string TreeAlias { get; } private ApplicationTree GetTree(FormDataCollection queryStrings) { diff --git a/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs b/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs index 69a07811ad..7f17b4d0ba 100644 --- a/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs +++ b/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs @@ -123,7 +123,7 @@ namespace Umbraco.Web.Trees } else { - var menuItem = collection.Items.Add(t, ApplicationContext.Current.Services.TextService.Localize("actions", t.Alias)); + var menuItem = collection.Items.Add(t, Current.Services.TextService.Localize("actions", t.Alias)); var currentAction = t; @@ -141,7 +141,7 @@ namespace Umbraco.Web.Trees if (attempt2) { var view = attempt2.Result; - var textService = ApplicationContext.Current.Services.TextService; + var textService = Current.Services.TextService; menuItem.LaunchDialogView(view, textService.Localize("defaultdialogs/confirmdelete") + " '" + xmlTreeNode.Text + "' ?"); } else @@ -213,52 +213,52 @@ namespace Umbraco.Web.Trees return Attempt.Succeed( new LegacyUrlAction( "create.aspx?nodeId=" + nodeId + "&nodeType=" + nodeType + "&nodeName=" + nodeName + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/create"))); + Current.Services.TextService.Localize("actions/create"))); case "UmbClientMgr.appActions().actionNewFolder()": return Attempt.Succeed( new LegacyUrlAction( "createFolder.aspx?nodeId=" + nodeId + "&nodeType=" + nodeType + "&nodeName=" + nodeName + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/create"))); + Current.Services.TextService.Localize("actions/create"))); case "UmbClientMgr.appActions().actionSort()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/sort.aspx?id=" + nodeId + "&nodeType=" + nodeType + "&app=" + currentSection + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/sort"))); + Current.Services.TextService.Localize("actions/sort"))); case "UmbClientMgr.appActions().actionRights()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/cruds.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/rights"))); + Current.Services.TextService.Localize("actions/rights"))); case "UmbClientMgr.appActions().actionProtect()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/protectPage.aspx?mode=cut&nodeId=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/protect"))); + Current.Services.TextService.Localize("actions/protect"))); case "UmbClientMgr.appActions().actionRollback()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/rollback.aspx?nodeId=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/rollback"))); + Current.Services.TextService.Localize("actions/rollback"))); case "UmbClientMgr.appActions().actionNotify()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/notifications.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/notify"))); + Current.Services.TextService.Localize("actions/notify"))); case "UmbClientMgr.appActions().actionPublish()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/publish.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/publish"))); + Current.Services.TextService.Localize("actions/publish"))); case "UmbClientMgr.appActions().actionChangeDocType()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/ChangeDocType.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/changeDocType"))); + Current.Services.TextService.Localize("actions/changeDocType"))); case "UmbClientMgr.appActions().actionToPublish()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/SendPublish.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/sendtopublish"))); + Current.Services.TextService.Localize("actions/sendtopublish"))); case "UmbClientMgr.appActions().actionRePublish()": return Attempt.Succeed( new LegacyUrlAction( @@ -268,22 +268,22 @@ namespace Umbraco.Web.Trees return Attempt.Succeed( new LegacyUrlAction( "dialogs/assignDomain2.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/assignDomain"))); + Current.Services.TextService.Localize("actions/assignDomain"))); case "UmbClientMgr.appActions().actionSendToTranslate()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/sendToTranslation.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/sendToTranslate"))); + Current.Services.TextService.Localize("actions/sendToTranslate"))); case "UmbClientMgr.appActions().actionEmptyTranscan()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/emptyTrashcan.aspx?type=" + currentSection, - ApplicationContext.Current.Services.TextService.Localize("actions/emptyTrashcan"))); + Current.Services.TextService.Localize("actions/emptyTrashcan"))); case "UmbClientMgr.appActions().actionImport()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/importDocumentType.aspx", - ApplicationContext.Current.Services.TextService.Localize("actions/importDocumentType"))); + Current.Services.TextService.Localize("actions/importDocumentType"))); case "UmbClientMgr.appActions().actionExport()": return Attempt.Succeed( new LegacyUrlAction( @@ -293,17 +293,17 @@ namespace Umbraco.Web.Trees return Attempt.Succeed( new LegacyUrlAction( "dialogs/viewAuditTrail.aspx?nodeId=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/auditTrail"))); + Current.Services.TextService.Localize("actions/auditTrail"))); case "UmbClientMgr.appActions().actionMove()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/moveOrCopy.aspx?app=" + currentSection + "&mode=cut&id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/move"))); + Current.Services.TextService.Localize("actions/move"))); case "UmbClientMgr.appActions().actionCopy()": return Attempt.Succeed( new LegacyUrlAction( "dialogs/moveOrCopy.aspx?app=" + currentSection + "&mode=copy&id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks, - ApplicationContext.Current.Services.TextService.Localize("actions/copy"))); + Current.Services.TextService.Localize("actions/copy"))); } return Attempt.Fail(); } diff --git a/src/Umbraco.Web/Trees/MacrosTreeController.cs b/src/Umbraco.Web/Trees/MacrosTreeController.cs index 3ee054dee5..f7026d9580 100644 --- a/src/Umbraco.Web/Trees/MacrosTreeController.cs +++ b/src/Umbraco.Web/Trees/MacrosTreeController.cs @@ -1,17 +1,10 @@ using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net; using System.Net.Http.Formatting; -using System.Web.Http; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; -using umbraco; -using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Services; using Umbraco.Web._Legacy.Actions; using Constants = Umbraco.Core.Constants; @@ -33,11 +26,11 @@ namespace Umbraco.Web.Trees foreach (var macro in Services.MacroService.GetAll()) { nodes.Add(CreateTreeNode( - macro.Id.ToString(), - id, - queryStrings, - macro.Name, - "icon-settings-alt", + macro.Id.ToString(), + id, + queryStrings, + macro.Name, + "icon-settings-alt", false, //TODO: Rebuild the macro editor in angular, then we dont need to have this at all (which is just a path to the legacy editor) "/" + queryStrings.GetValue("application") + "/framed/" + @@ -56,7 +49,7 @@ namespace Umbraco.Web.Trees { //Create the normal create action menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) - //Since we haven't implemented anything for macros in angular, this needs to be converted to + //Since we haven't implemented anything for macros in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(null, "initmacros", queryStrings.GetValue("application")); @@ -72,7 +65,7 @@ namespace Umbraco.Web.Trees //add delete option for all macros menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)) - //Since we haven't implemented anything for macros in angular, this needs to be converted to + //Since we haven't implemented anything for macros in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(new UmbracoEntity { diff --git a/src/Umbraco.Web/Trees/MediaTreeController.cs b/src/Umbraco.Web/Trees/MediaTreeController.cs index 2827f0152a..4db0128ca3 100644 --- a/src/Umbraco.Web/Trees/MediaTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTreeController.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Net; using System.Net.Http.Formatting; -using System.Web; using System.Web.Http; using Umbraco.Core; using Umbraco.Core.Models; @@ -11,7 +10,6 @@ using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; -using umbraco; using Umbraco.Web._Legacy.Actions; using Constants = Umbraco.Core.Constants; @@ -105,7 +103,7 @@ namespace Umbraco.Web.Trees return menu; } - // root actions + // root actions menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)); menu.Items.Add(Services.TextService.Localize("actions", ActionSort.Instance.Alias), true).ConvertLegacyMenuItem(null, "media", "media"); menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); diff --git a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs index ab9aa74f70..5208aaec89 100644 --- a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs @@ -1,13 +1,8 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Net.Http.Formatting; -using System.Text; -using System.Threading.Tasks; -using umbraco; using Umbraco.Core; using Umbraco.Core.Models; -using Umbraco.Core.Models.EntityBase; using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Services; @@ -66,7 +61,7 @@ namespace Umbraco.Web.Trees //set the default to create menu.DefaultMenuAlias = ActionNew.Instance.Alias; - // root actions + // root actions menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias))); return menu; @@ -79,16 +74,16 @@ namespace Umbraco.Web.Trees menu.DefaultMenuAlias = ActionNew.Instance.Alias; menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); - + if (container.HasChildren() == false) { //can delete doc type menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias))); - } + } menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), hasSeparator: true); } else - { + { menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias))); menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionMove.Instance.Alias)), hasSeparator: true); menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionCopy.Instance.Alias))); diff --git a/src/Umbraco.Web/Trees/MemberTreeController.cs b/src/Umbraco.Web/Trees/MemberTreeController.cs index ccbfb35826..46c9ca310d 100644 --- a/src/Umbraco.Web/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web/Trees/MemberTreeController.cs @@ -11,7 +11,6 @@ using Umbraco.Core.Security; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; -using umbraco; using Umbraco.Web._Legacy.Actions; using Constants = Umbraco.Core.Constants; @@ -45,7 +44,7 @@ namespace Umbraco.Web.Trees /// [HttpQueryStringFilter("queryStrings")] public TreeNode GetTreeNode(string id, FormDataCollection queryStrings) - { + { var node = GetSingleTreeNode(id, queryStrings); //add the tree alias to the node since it is standalone (has no root for which this normally belongs) @@ -105,10 +104,10 @@ namespace Umbraco.Web.Trees "icon-user", false); - return node; + return node; } - + } protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) @@ -144,7 +143,7 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { - // root actions + // root actions if (_provider.IsUmbracoMembershipProvider()) { //set default @@ -162,7 +161,7 @@ namespace Umbraco.Web.Trees createMenuItem.NavigateToRoute("/member/member/edit/-1?create=true"); menu.Items.Add(createMenuItem); } - + menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); return menu; } diff --git a/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs b/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs index c89b94670e..a710b52595 100644 --- a/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/MemberTypeAndGroupTreeControllerBase.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { - // root actions + // root actions menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)); menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); return menu; diff --git a/src/Umbraco.Web/Trees/PackagesTreeController.cs b/src/Umbraco.Web/Trees/PackagesTreeController.cs index 5f4a7796df..049da62917 100644 --- a/src/Umbraco.Web/Trees/PackagesTreeController.cs +++ b/src/Umbraco.Web/Trees/PackagesTreeController.cs @@ -41,7 +41,7 @@ namespace Umbraco.Web.Trees var nodes = new TreeNodeCollection(); var createdPackages = CreatedPackage.GetAllCreatedPackages(); - + if (id == "created") { nodes.AddRange( @@ -52,7 +52,7 @@ namespace Umbraco.Web.Trees var node = CreateTreeNode(dt.Data.Id.ToString(), id, queryStrings, dt.Data.Name, "icon-inbox", false, string.Format("/{0}/framed/{1}", queryStrings.GetValue("application"), - Uri.EscapeDataString("developer/Packages/EditPackage.aspx?id=" + dt.Data.Id))); + Uri.EscapeDataString("developer/Packages/EditPackage.aspx?id=" + dt.Data.Id))); return node; })); } @@ -68,7 +68,7 @@ namespace Umbraco.Web.Trees createdPackages.Count > 0, string.Empty); - + //TODO: This isn't the best way to ensure a noop process for clicking a node but it works for now. node.AdditionalData["jsClickCallback"] = "javascript:void(0);"; @@ -76,7 +76,7 @@ namespace Umbraco.Web.Trees nodes.Add(node); } - + return nodes; } diff --git a/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs b/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs index d4213c7996..51f4a168af 100644 --- a/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs +++ b/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs @@ -1,6 +1,4 @@ -using System.Text; -using Umbraco.Core.IO; -using umbraco.cms.presentation.Trees; +using Umbraco.Core.IO; using Umbraco.Core; namespace Umbraco.Web.Trees @@ -11,7 +9,7 @@ namespace Umbraco.Web.Trees [Tree(Constants.Applications.Developer, Constants.Trees.PartialViewMacros, "Partial View Macro Files", sortOrder: 6)] public class PartialViewMacrosTreeController : PartialViewsTreeController { - protected override string FilePath + protected override string FilePath { get { return SystemDirectories.MvcViews + "/MacroPartials/"; } } diff --git a/src/Umbraco.Web/Trees/PartialViewsTreeController.cs b/src/Umbraco.Web/Trees/PartialViewsTreeController.cs index 3255c87e40..c0e2d3bf1a 100644 --- a/src/Umbraco.Web/Trees/PartialViewsTreeController.cs +++ b/src/Umbraco.Web/Trees/PartialViewsTreeController.cs @@ -1,17 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Web; using Umbraco.Core; -using Umbraco.Core.Configuration; using Umbraco.Core.IO; - -using umbraco.cms.businesslogic.template; -using umbraco.cms.presentation.Trees; using Umbraco.Web.Models.Trees; -using Umbraco.Web._Legacy.Actions; namespace Umbraco.Web.Trees { diff --git a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs index 2ed71b68e9..f0b977e11a 100644 --- a/src/Umbraco.Web/Trees/RelationTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/RelationTypeTreeController.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Trees { //Create the normal create action menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) - //Since we haven't implemented anything for relationtypes in angular, this needs to be converted to + //Since we haven't implemented anything for relationtypes in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(null, "initrelationTypes", queryStrings.GetValue("application")); //refresh action @@ -38,7 +38,7 @@ namespace Umbraco.Web.Trees //add delete option for all macros menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias)) - //Since we haven't implemented anything for relationtypes in angular, this needs to be converted to + //Since we haven't implemented anything for relationtypes in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(new UmbracoEntity { diff --git a/src/Umbraco.Web/Trees/ScriptsTreeController.cs b/src/Umbraco.Web/Trees/ScriptsTreeController.cs index 7409230d24..767e74e6c8 100644 --- a/src/Umbraco.Web/Trees/ScriptsTreeController.cs +++ b/src/Umbraco.Web/Trees/ScriptsTreeController.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Net.Http.Formatting; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; @@ -40,7 +39,7 @@ namespace Umbraco.Web.Trees { treeNode.Icon = file.Name.EndsWith(".js", StringComparison.OrdinalIgnoreCase) ? - "icon-script" : + "icon-script" : "icon-code"; } diff --git a/src/Umbraco.Web/Trees/StylesheetsTreeController.cs b/src/Umbraco.Web/Trees/StylesheetsTreeController.cs index 786bfe45bc..dfa75b4afa 100644 --- a/src/Umbraco.Web/Trees/StylesheetsTreeController.cs +++ b/src/Umbraco.Web/Trees/StylesheetsTreeController.cs @@ -3,12 +3,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http.Formatting; -using System.Text; -using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.IO; -using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; using Umbraco.Web._Legacy.Actions; @@ -19,7 +15,6 @@ namespace Umbraco.Web.Trees [Tree(Constants.Applications.Settings, Constants.Trees.Stylesheets, "Stylesheets", "icon-folder", "icon-folder", sortOrder: 3)] public class StylesheetsTreeController : FileSystemTreeController { - protected override string FilePath { get { return SystemDirectories.Css + "/"; } @@ -39,14 +34,14 @@ namespace Umbraco.Web.Trees { get { return false; } } - + protected override void OnBeforeRenderMenu(MenuItemCollection menu, string id, FormDataCollection queryStrings) { if (File.Exists((IOHelper.MapPath(FilePath + "/" + id)))) { menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) - //Since we haven't implemented anything for file systems in angular, this needs to be converted to + //Since we haven't implemented anything for file systems in angular, this needs to be converted to //use the legacy format .ConvertLegacyFileSystemMenuItem(id, "stylesheet", queryStrings.GetValue("application")); } @@ -74,7 +69,7 @@ namespace Umbraco.Web.Trees { treeNode.HasChildren = styleSheet.Properties.Any(); } - + } protected override TreeNodeCollection GetTreeNodesForFile(string path, string id, FormDataCollection queryStrings) diff --git a/src/Umbraco.Web/Trees/TemplatesTreeController.cs b/src/Umbraco.Web/Trees/TemplatesTreeController.cs index 3428b4b32e..37a41e8c6b 100644 --- a/src/Umbraco.Web/Trees/TemplatesTreeController.cs +++ b/src/Umbraco.Web/Trees/TemplatesTreeController.cs @@ -1,16 +1,9 @@ using System; -using System.Collections; -using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; using System.Net.Http.Formatting; -using System.Web.Services.Description; -using umbraco; -using umbraco.cms.businesslogic.template; using Umbraco.Core; using Umbraco.Core.Services; -using Umbraco.Core.Configuration; using Umbraco.Core.Models; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; @@ -41,8 +34,8 @@ namespace Umbraco.Web.Trees { var nodes = new TreeNodeCollection(); - var found = id == Constants.System.Root.ToInvariantString() - ? Services.FileService.GetTemplates(-1) + var found = id == Constants.System.Root.ToInvariantString() + ? Services.FileService.GetTemplates(-1) : Services.FileService.GetTemplates(int.Parse(id)); nodes.AddRange(found.Select(template => CreateTreeNode( @@ -72,7 +65,7 @@ namespace Umbraco.Web.Trees { //Create the normal create action menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) - //Since we haven't implemented anything for templates in angular, this needs to be converted to + //Since we haven't implemented anything for templates in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(null, "inittemplates", queryStrings.GetValue("application")); @@ -88,7 +81,7 @@ namespace Umbraco.Web.Trees //Create the create action for creating sub layouts menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) - //Since we haven't implemented anything for templates in angular, this needs to be converted to + //Since we haven't implemented anything for templates in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(entity, "templates", queryStrings.GetValue("application")); @@ -97,14 +90,14 @@ namespace Umbraco.Web.Trees { //add delete option if it doesn't have children menu.Items.Add(Services.TextService.Localize("actions", ActionDelete.Instance.Alias), true) - //Since we haven't implemented anything for languages in angular, this needs to be converted to + //Since we haven't implemented anything for languages in angular, this needs to be converted to //use the legacy format .ConvertLegacyMenuItem(entity, "templates", queryStrings.GetValue("application")); } //add refresh menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); - + return menu; } diff --git a/src/Umbraco.Web/Trees/TreeController.cs b/src/Umbraco.Web/Trees/TreeController.cs index 0f975a9860..b358154a0e 100644 --- a/src/Umbraco.Web/Trees/TreeController.cs +++ b/src/Umbraco.Web/Trees/TreeController.cs @@ -1,14 +1,5 @@ using System; -using System.Collections.Concurrent; -using System.Globalization; using System.Linq; -using System.Net.Http.Formatting; -using System.Threading; -using System.Web.Security; -using Umbraco.Core; -using Umbraco.Core.Models; -using Umbraco.Web.Models.Trees; -using Umbraco.Web.Mvc; using Umbraco.Core.Services; namespace Umbraco.Web.Trees @@ -25,16 +16,6 @@ namespace Umbraco.Web.Trees Initialize(); } - protected TreeController(UmbracoContext umbracoContext) : base(umbracoContext) - { - Initialize(); - } - - protected TreeController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) : base(umbracoContext, umbracoHelper) - { - Initialize(); - } - /// /// The name to display on the root node /// diff --git a/src/Umbraco.Web/Trees/TreeControllerBase.cs b/src/Umbraco.Web/Trees/TreeControllerBase.cs index 91191a165d..a51393c336 100644 --- a/src/Umbraco.Web/Trees/TreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/TreeControllerBase.cs @@ -1,13 +1,12 @@ -using System; -using System.Globalization; +using System.Globalization; using System.Linq; using System.Net.Http.Formatting; +using System.Web.Http.Routing; using Umbraco.Core; using Umbraco.Core.Events; using Umbraco.Web.Models.Trees; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; -using Umbraco.Core.Models; namespace Umbraco.Web.Trees { @@ -18,18 +17,6 @@ namespace Umbraco.Web.Trees [AngularJsonOnlyConfiguration] public abstract class TreeControllerBase : UmbracoAuthorizedApiController { - protected TreeControllerBase() - { - } - - protected TreeControllerBase(UmbracoContext umbracoContext) : base(umbracoContext) - { - } - - protected TreeControllerBase(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) : base(umbracoContext, umbracoHelper) - { - } - /// /// The method called to render the contents of the tree structure /// @@ -83,7 +70,7 @@ namespace Umbraco.Web.Trees node.AdditionalData.Add("searchable", "true"); } - //now update all data based on some of the query strings, like if we are running in dialog mode + //now update all data based on some of the query strings, like if we are running in dialog mode if (IsDialog(queryStrings)) { node.RoutePath = "#"; @@ -101,7 +88,7 @@ namespace Umbraco.Web.Trees /// /// All of the query string parameters passed from jsTree /// - /// JSON markup for jsTree + /// JSON markup for jsTree /// /// We are allowing an arbitrary number of query strings to be pased in so that developers are able to persist custom data from the front-end /// to the back end to be used in the query for model data. @@ -117,7 +104,7 @@ namespace Umbraco.Web.Trees AddQueryStringsToAdditionalData(node, queryStrings); } - //now update all data based on some of the query strings, like if we are running in dialog mode + //now update all data based on some of the query strings, like if we are running in dialog mode if (IsDialog((queryStrings))) { foreach (var node in nodes) @@ -204,7 +191,7 @@ namespace Umbraco.Web.Trees var menuUrl = Url.GetMenuUrl(GetType(), id, queryStrings); var node = new TreeNode(id, parentId, jsonUrl, menuUrl) { - Name = title, + Name = title, Icon = icon, NodeType = TreeAlias }; @@ -310,7 +297,8 @@ namespace Umbraco.Web.Trees ///
public static event TypedEventHandler RootNodeRendering; - private static void OnRootNodeRendering(TreeControllerBase instance, TreeNodeRenderingEventArgs e) + // internal for temp class below - kill eventually! + internal static void OnRootNodeRendering(TreeControllerBase instance, TreeNodeRenderingEventArgs e) { var handler = RootNodeRendering; if (handler != null) handler(instance, e); @@ -330,4 +318,77 @@ namespace Umbraco.Web.Trees if (handler != null) handler(instance, e); } } + + internal class TreeControllerBaseStuffForLegacy + { + private readonly string _treeAlias; + private readonly string _rootNodeDisplayName; + private readonly UrlHelper _url; + + public TreeControllerBaseStuffForLegacy(string treeAlias, string rootNodeDisplayName, UrlHelper url) + { + _treeAlias = treeAlias; + _rootNodeDisplayName = rootNodeDisplayName; + _url = url; + } + + public TreeNode GetRootNode(FormDataCollection queryStrings) + { + if (queryStrings == null) queryStrings = new FormDataCollection(""); + var node = CreateRootNode(queryStrings); + + //add the tree alias to the root + node.AdditionalData["treeAlias"] = _treeAlias; + + AddQueryStringsToAdditionalData(node, queryStrings); + + //check if the tree is searchable and add that to the meta data as well + if (this is ISearchableTree) + { + node.AdditionalData.Add("searchable", "true"); + } + + //now update all data based on some of the query strings, like if we are running in dialog mode + if (IsDialog(queryStrings)) + { + node.RoutePath = "#"; + } + + TreeControllerBase.OnRootNodeRendering(null, new TreeNodeRenderingEventArgs(node, queryStrings)); + + return node; + } + + protected virtual TreeNode CreateRootNode(FormDataCollection queryStrings) + { + var rootNodeAsString = Constants.System.Root.ToString(CultureInfo.InvariantCulture); + var currApp = queryStrings.GetValue(TreeQueryStringParameters.Application); + + var node = new TreeNode( + rootNodeAsString, + null, //this is a root node, there is no parent + _url.GetTreeUrl(GetType(), rootNodeAsString, queryStrings), + _url.GetMenuUrl(GetType(), rootNodeAsString, queryStrings)) + { + HasChildren = true, + RoutePath = currApp, + Name = _rootNodeDisplayName + }; + + return node; + } + + protected void AddQueryStringsToAdditionalData(TreeNode node, FormDataCollection queryStrings) + { + foreach (var q in queryStrings.Where(x => node.AdditionalData.ContainsKey(x.Key) == false)) + { + node.AdditionalData.Add(q.Key, q.Value); + } + } + + protected bool IsDialog(FormDataCollection queryStrings) + { + return queryStrings.GetValue(TreeQueryStringParameters.IsDialog); + } + } } \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs b/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs index 0d546d6a42..fd56989fe6 100644 --- a/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs +++ b/src/Umbraco.Web/Trees/UserPermissionsTreeController.cs @@ -24,11 +24,11 @@ namespace Umbraco.Web.Trees nodes.AddRange( Services.UserService.GetAll(0, int.MaxValue, out totalUsers) .Where(x => x.Id > 0 && x.IsApproved) - .Select(x => CreateTreeNode(x.Id.ToString(), - id, - queryStrings, - x.Name, - "icon-user", + .Select(x => CreateTreeNode(x.Id.ToString(), + id, + queryStrings, + x.Name, + "icon-user", false, "/" + queryStrings.GetValue("application") + "/framed/" + Uri.EscapeDataString("users/PermissionEditor.aspx?id=" + x.Id)))); @@ -42,7 +42,7 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { - // root actions + // root actions menu.Items.Add(Services.TextService.Localize("actions", ActionRefresh.Instance.Alias), true); return menu; } diff --git a/src/Umbraco.Web/Trees/UserTypesTreeController.cs b/src/Umbraco.Web/Trees/UserTypesTreeController.cs index ab0bcef8b4..fb19796425 100644 --- a/src/Umbraco.Web/Trees/UserTypesTreeController.cs +++ b/src/Umbraco.Web/Trees/UserTypesTreeController.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { - // root actions + // root actions menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) .ConvertLegacyMenuItem(null, "userTypes", queryStrings.GetValue("application")); diff --git a/src/Umbraco.Web/Trees/UsersTreeController.cs b/src/Umbraco.Web/Trees/UsersTreeController.cs index cd3bf66649..60eb2cfbc8 100644 --- a/src/Umbraco.Web/Trees/UsersTreeController.cs +++ b/src/Umbraco.Web/Trees/UsersTreeController.cs @@ -74,7 +74,7 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { - // Root actions + // Root actions menu.Items.Add(Services.TextService.Localize("actions", ActionNew.Instance.Alias)) .ConvertLegacyMenuItem(null, "users", queryStrings.GetValue("application")); @@ -91,7 +91,7 @@ namespace Umbraco.Web.Trees { Name = Services.TextService.Localize("actions", "disable") }); - + return menu; } } diff --git a/src/Umbraco.Web/Trees/XsltTreeController.cs b/src/Umbraco.Web/Trees/XsltTreeController.cs index 0c0bb8f637..c4c9a96c82 100644 --- a/src/Umbraco.Web/Trees/XsltTreeController.cs +++ b/src/Umbraco.Web/Trees/XsltTreeController.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Web.Models.Trees; diff --git a/src/Umbraco.Web/UI/Controls/InsertMacroSplitButton.cs b/src/Umbraco.Web/UI/Controls/InsertMacroSplitButton.cs index 4a97eac6d1..13fa0f6a32 100644 --- a/src/Umbraco.Web/UI/Controls/InsertMacroSplitButton.cs +++ b/src/Umbraco.Web/UI/Controls/InsertMacroSplitButton.cs @@ -138,7 +138,7 @@ namespace Umbraco.Web.UI.Controls private bool DoesMacroHaveParameters(int macroId) { - return ApplicationContext.DatabaseContext.Database.ExecuteScalar(string.Format("SELECT COUNT(*) from cmsMacroProperty where macro = {0}", macroId)) > 0; + return DatabaseContext.Database.ExecuteScalar(string.Format("SELECT COUNT(*) from cmsMacroProperty where macro = {0}", macroId)) > 0; } } } diff --git a/src/Umbraco.Web/UI/Controls/UmbracoControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoControl.cs index 9c75a80c9a..1e51bafb83 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoControl.cs @@ -4,10 +4,9 @@ using System.Web.Mvc; using System.Web.Routing; using System.Web.UI; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Services; -using umbraco.BusinessLogic; -using umbraco.DataLayer; namespace Umbraco.Web.UI.Controls { @@ -16,73 +15,62 @@ namespace Umbraco.Web.UI.Controls /// public abstract class UmbracoControl : Control { + private UrlHelper _url; - /// - /// Default constructor - /// - /// - protected UmbracoControl(UmbracoContext umbracoContext) + protected UmbracoControl(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); UmbracoContext = umbracoContext; - Umbraco = new UmbracoHelper(umbracoContext); + Umbraco = new UmbracoHelper(umbracoContext, services, appCache); + + // fixme inject somehow + Logger = Current.Logger; + ProfilingLogger = Current.ProfilingLogger; + DatabaseContext = Current.DatabaseContext; + Services = Current.Services; } /// - /// Empty constructor, uses Singleton to resolve the UmbracoContext + /// Empty constructor, uses Singleton to resolve the UmbracoContext. /// protected UmbracoControl() - : this(UmbracoContext.Current) - { - } + : this(Current.UmbracoContext, Current.Services, Current.ApplicationCache) + { } /// /// Returns an UmbracoHelper object /// - public UmbracoHelper Umbraco { get; private set; } + public UmbracoHelper Umbraco { get; } /// - /// Returns an ILogger + /// Gets the logger. /// - public ILogger Logger - { - get { return ProfilingLogger.Logger; } - } + public ILogger Logger { get; } + + /// + /// Gets the profiling logger. + /// + public ProfilingLogger ProfilingLogger { get; } /// - /// Returns a ProfilingLogger + /// Gets the Umbraco context. /// - public ProfilingLogger ProfilingLogger - { - get { return UmbracoContext.Application.ProfilingLogger; } - } + public UmbracoContext UmbracoContext { get; } - public UmbracoContext UmbracoContext { get; private set; } + /// + /// Gets the database context. + /// + protected DatabaseContext DatabaseContext { get; } - protected ApplicationContext ApplicationContext - { - get { return UmbracoContext.Application; } - } - protected DatabaseContext DatabaseContext - { - get { return ApplicationContext.DatabaseContext; } - } - protected ServiceContext Services - { - get { return ApplicationContext.Services; } - } + /// + /// Gets the services context. + /// + protected ServiceContext Services { get; } - private UrlHelper _url; /// - /// Returns a UrlHelper + /// Gets a Url helper. /// - /// - /// This URL helper is created without any route data and an empty request context - /// - public UrlHelper Url - { - get { return _url ?? (_url = new UrlHelper(new RequestContext(new HttpContextWrapper(Context), new RouteData()))); } - } - + /// This URL helper is created without any route data and an empty request context. + public UrlHelper Url => _url ?? (_url = new UrlHelper(new RequestContext(new HttpContextWrapper(Context), new RouteData()))); } } \ No newline at end of file diff --git a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs index 2b2c89df7c..50f4659d70 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs @@ -4,10 +4,10 @@ using System.Web.Mvc; using System.Web.Routing; using System.Web.UI; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; -using umbraco.DataLayer; using Umbraco.Web.UI.Pages; namespace Umbraco.Web.UI.Controls @@ -17,124 +17,95 @@ namespace Umbraco.Web.UI.Controls /// public abstract class UmbracoUserControl : UserControl { + private ClientTools _clientTools; + private UrlHelper _url; + /// /// Default constructor /// /// - protected UmbracoUserControl(UmbracoContext umbracoContext) + /// + /// + protected UmbracoUserControl(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); UmbracoContext = umbracoContext; - InstanceId = Guid.NewGuid(); - Umbraco = new UmbracoHelper(umbracoContext); - _membershipHelper = new MembershipHelper(umbracoContext); + Umbraco = new UmbracoHelper(umbracoContext, services, appCache); + Members = new MembershipHelper(umbracoContext); + + // fixme inject somehow + Logger = Current.Logger; + ProfilingLogger = Current.ProfilingLogger; + DatabaseContext = Current.DatabaseContext; + Services = Current.Services; } /// /// Empty constructor, uses Singleton to resolve the UmbracoContext /// protected UmbracoUserControl() - : this(UmbracoContext.Current) - { - } + : this(Current.UmbracoContext, Current.Services, Current.ApplicationCache) + { } + + // for debugging purposes + internal Guid InstanceId { get; } = Guid.NewGuid(); - private ClientTools _clientTools; /// - /// Returns a refernce of an instance of ClientTools for access to the pages client API + /// Gets the Umbraco helper. + /// + public UmbracoHelper Umbraco { get; } + + /// + /// Gets the membership helper; + /// + public MembershipHelper Members { get; } + + /// + /// Gets the web security helper. + /// + public WebSecurity Security => UmbracoContext.Security; + + /// + /// Gets the logger. + /// + public ILogger Logger { get; } + + /// + /// Gets the ProfilingLogger. + /// + public ProfilingLogger ProfilingLogger { get; } + + /// + /// Gets the Umbraco context. + /// + public UmbracoContext UmbracoContext { get; } + + /// + /// Gets the services context. + /// + public ServiceContext Services { get; } + + /// + /// Gets the database context. + /// + public DatabaseContext DatabaseContext { get; } + + /// + /// Gets an instance of ClientTools for access to the pages client API. /// public ClientTools ClientTools { get { var page = Page as BasePage; - return _clientTools ?? (_clientTools = (page != null) ? page.ClientTools : new ClientTools(Page)); + return _clientTools ?? (_clientTools = page != null ? page.ClientTools : new ClientTools(Page)); } } - private readonly MembershipHelper _membershipHelper; - /// - /// Useful for debugging + /// Gets a Url helper. /// - internal Guid InstanceId { get; private set; } - - /// - /// Returns an UmbracoHelper object - /// - public UmbracoHelper Umbraco { get; private set; } - - /// - /// Returns the MemberHelper instance - /// - public MembershipHelper Members - { - get { return _membershipHelper; } - } - - /// - /// Returns the current WebSecurity instance - /// - public WebSecurity Security - { - get { return UmbracoContext.Security; } - } - - /// - /// Returns an ILogger - /// - public ILogger Logger - { - get { return ProfilingLogger.Logger; } - } - - /// - /// Returns a ProfilingLogger - /// - public ProfilingLogger ProfilingLogger - { - get { return UmbracoContext.Application.ProfilingLogger; } - } - - /// - /// Returns the current UmbracoContext - /// - public UmbracoContext UmbracoContext { get; private set; } - - /// - /// Returns the current ApplicationContext - /// - public ApplicationContext ApplicationContext - { - get { return UmbracoContext.Application; } - } - - /// - /// Returns a ServiceContext - /// - public ServiceContext Services - { - get { return ApplicationContext.Services; } - } - - /// - /// Returns a DatabaseContext - /// - public DatabaseContext DatabaseContext - { - get { return ApplicationContext.DatabaseContext; } - } - - private UrlHelper _url; - /// - /// Returns a UrlHelper - /// - /// - /// This URL helper is created without any route data and an empty request context - /// - public UrlHelper Url - { - get { return _url ?? (_url = new UrlHelper(new RequestContext(new HttpContextWrapper(Context), new RouteData()))); } - } - + /// This URL helper is created without any route data and an empty request context. + public UrlHelper Url => _url ?? (_url = new UrlHelper(new RequestContext(new HttpContextWrapper(Context), new RouteData()))); } } \ No newline at end of file diff --git a/src/Umbraco.Web/UI/Pages/BasePage.cs b/src/Umbraco.Web/UI/Pages/BasePage.cs index 70d387fcd5..ecb4abda66 100644 --- a/src/Umbraco.Web/UI/Pages/BasePage.cs +++ b/src/Umbraco.Web/UI/Pages/BasePage.cs @@ -1,19 +1,12 @@ using System; -using System.Data; using System.Web; -using System.Linq; using System.Web.Mvc; using System.Web.Routing; -using System.Web.Security; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.IO; using Umbraco.Core.Logging; -using Umbraco.Core.Profiling; using Umbraco.Core.Services; using Umbraco.Web.Security; -using umbraco.BusinessLogic; -using umbraco.DataLayer; using System.Web.UI; namespace Umbraco.Web.UI.Pages @@ -26,113 +19,56 @@ namespace Umbraco.Web.UI.Pages /// public class BasePage : Page { - - private ClientTools _clientTools; - - - //We won't expose this... people should be using the DatabaseContext for custom queries if they need them. - - ///// - ///// Gets the SQL helper. - ///// - ///// The SQL helper. - //protected ISqlHelper SqlHelper - //{ - // get { return global::umbraco.BusinessLogic.Application.SqlHelper; } - //} - - /// - /// Returns an ILogger - /// - public ILogger Logger - { - get { return ProfilingLogger.Logger; } - } - - /// - /// Returns a ProfilingLogger - /// - public ProfilingLogger ProfilingLogger - { - get { return _logger ?? (_logger = new ProfilingLogger(Current.Logger, Current.Profiler)); } - } - - private ProfilingLogger _logger; - - - private UrlHelper _url; - /// - /// Returns a UrlHelper - /// - /// - /// This URL helper is created without any route data and an empty request context - /// - public UrlHelper Url - { - get { return _url ?? (_url = new UrlHelper(new RequestContext(new HttpContextWrapper(Context), new RouteData()))); } - } - + private UrlHelper _url; private HtmlHelper _html; + private ClientTools _clientTools; + /// - /// Returns a HtmlHelper + /// Gets the logger. + /// + public ILogger Logger => Current.Logger; + + /// + /// Gets the profiling helper. + /// + public ProfilingLogger ProfilingLogger => Current.ProfilingLogger; + + /// + /// Gets the Url helper. + /// + /// This URL helper is created without any route data and an empty request context. + public UrlHelper Url => _url ?? (_url = new UrlHelper(new RequestContext(new HttpContextWrapper(Context), new RouteData()))); + + /// + /// Gets the Html helper. /// - /// - /// This html helper is created with an empty context and page so it may not have all of the functionality expected. - /// - public HtmlHelper Html - { - get { return _html ?? (_html = new HtmlHelper(new ViewContext(), new ViewPage())); } - } + /// This html helper is created with an empty context and page so it may not have all of the functionality expected. + public HtmlHelper Html => _html ?? (_html = new HtmlHelper(new ViewContext(), new ViewPage())); /// - /// Returns the current ApplicationContext + /// Gets the Umbraco context. /// - public ApplicationContext ApplicationContext - { - get { return ApplicationContext.Current; } - } + public UmbracoContext UmbracoContext => Current.UmbracoContext; /// - /// Returns the current UmbracoContext + /// Gets the web security helper. /// - public UmbracoContext UmbracoContext - { - get { return UmbracoContext.Current; } - } + public WebSecurity Security => UmbracoContext.Security; /// - /// Returns the current WebSecurity instance + /// Gets the services context. /// - public WebSecurity Security - { - get { return UmbracoContext.Security; } - } + public ServiceContext Services => Current.Services; /// - /// Returns a ServiceContext + /// Gets the database context. /// - public ServiceContext Services - { - get { return ApplicationContext.Services; } - } + public DatabaseContext DatabaseContext => Current.DatabaseContext; /// - /// Returns a DatabaseContext + /// Gets an instance of ClientTools for access to the pages client API. /// - public DatabaseContext DatabaseContext - { - get { return ApplicationContext.DatabaseContext; } - } - - /// - /// Returns a refernce of an instance of ClientTools for access to the pages client API - /// - public ClientTools ClientTools - { - get { return _clientTools ?? (_clientTools = new ClientTools(this)); } - } - - + public ClientTools ClientTools => _clientTools ?? (_clientTools = new ClientTools(this)); /// /// Raises the event. @@ -142,12 +78,10 @@ namespace Umbraco.Web.UI.Pages { base.OnLoad(e); - if (!Request.IsSecureConnection && GlobalSettings.UseSSL) - { - string serverName = HttpUtility.UrlEncode(Request.ServerVariables["SERVER_NAME"]); - Response.Redirect(string.Format("https://{0}{1}", serverName, Request.FilePath)); - } - } + if (Request.IsSecureConnection || GlobalSettings.UseSSL == false) return; + var serverName = HttpUtility.UrlEncode(Request.ServerVariables["SERVER_NAME"]); + Response.Redirect($"https://{serverName}{Request.FilePath}"); + } } } diff --git a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs index 93810fd7f7..d1f9e282bd 100644 --- a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs +++ b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.UI.Pages var treeAuth = this.GetType().GetCustomAttribute(true); if (treeAuth != null) { - var treeByAlias = ApplicationContext.Current.Services.ApplicationTreeService + var treeByAlias = Current.Services.ApplicationTreeService .GetByAlias(treeAuth.TreeAlias); if (treeByAlias != null) { diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index d56393086d..e1f1f85129 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -156,7 +156,6 @@ Properties\SolutionInfo.cs - @@ -198,7 +197,6 @@ - @@ -656,7 +654,7 @@ - + @@ -939,7 +937,7 @@ ASPXCodeBehind - + @@ -988,7 +986,7 @@ - + diff --git a/src/Umbraco.Web/UmbracoComponentRenderer.cs b/src/Umbraco.Web/UmbracoComponentRenderer.cs index 08f938067f..34408fd973 100644 --- a/src/Umbraco.Web/UmbracoComponentRenderer.cs +++ b/src/Umbraco.Web/UmbracoComponentRenderer.cs @@ -104,7 +104,7 @@ namespace Umbraco.Web if (alias == null) throw new ArgumentNullException("alias"); if (umbracoPage == null) throw new ArgumentNullException("umbracoPage"); - var m = ApplicationContext.Current.Services.MacroService.GetByAlias(alias); + var m = Current.Services.MacroService.GetByAlias(alias); if (m == null) throw new KeyNotFoundException("Could not find macro with alias " + alias); @@ -131,14 +131,14 @@ namespace Umbraco.Web var macroProps = new Hashtable(); foreach (var i in parameters) { - //TODO: We are doing at ToLower here because for some insane reason the UpdateMacroModel method of macro.cs + //TODO: We are doing at ToLower here because for some insane reason the UpdateMacroModel method of macro.cs // looks for a lower case match. WTF. the whole macro concept needs to be rewritten. //NOTE: the value could have html encoded values, so we need to deal with that macroProps.Add(i.Key.ToLowerInvariant(), (i.Value is string) ? HttpUtility.HtmlDecode(i.Value.ToString()) : i.Value); } - var renderer = new MacroRenderer(ApplicationContext.Current.ProfilingLogger); + var renderer = new MacroRenderer(Current.ProfilingLogger); var macroControl = renderer.Render(m, umbracoPage.Elements, _umbracoContext.PageId.Value, macroProps).GetAsControl(); string html; @@ -164,9 +164,9 @@ namespace Umbraco.Web // within Razor since it will never be inserted into the page pipeline (which may even not exist at all // if we're running MVC). // - // I'm sure there's more things that will get lost with this context changing but I guess we'll figure + // I'm sure there's more things that will get lost with this context changing but I guess we'll figure // those out as we go along. One thing we lose is the content type response output. - // http://issues.umbraco.org/issue/U4-1599 if it is setup during the macro execution. So + // http://issues.umbraco.org/issue/U4-1599 if it is setup during the macro execution. So // here we'll save the content type response and reset it after execute is called. var contentType = _umbracoContext.HttpContext.Response.ContentType; @@ -272,7 +272,7 @@ namespace Umbraco.Web LegacyAttributes = attributesForItem }; - //here we are going to check if we are in the context of an Umbraco routed page, if we are we + //here we are going to check if we are in the context of an Umbraco routed page, if we are we //will leave the NodeId empty since the underlying ItemRenderer will work ever so slightly faster //since it already knows about the current page. Otherwise, we'll assign the id based on our //currently assigned node. The PublishedContentRequest will be null if: diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index 8b5b20be97..fc07c6c55f 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -47,7 +47,6 @@ namespace Umbraco.Web /// public static UmbracoContext EnsureContext( HttpContextBase httpContext, - ApplicationContext applicationContext, IFacadeService facadeService, WebSecurity webSecurity, IUmbracoSettingsSection umbracoSettings, @@ -55,7 +54,6 @@ namespace Umbraco.Web bool replaceContext) { if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); - if (applicationContext == null) throw new ArgumentNullException(nameof(applicationContext)); if (webSecurity == null) throw new ArgumentNullException(nameof(webSecurity)); if (umbracoSettings == null) throw new ArgumentNullException(nameof(umbracoSettings)); if (urlProviders == null) throw new ArgumentNullException(nameof(urlProviders)); @@ -66,7 +64,7 @@ namespace Umbraco.Web return umbracoContext; // create, assign the singleton, and return - umbracoContext = CreateContext(httpContext, applicationContext, facadeService, webSecurity, umbracoSettings, urlProviders); + umbracoContext = CreateContext(httpContext, facadeService, webSecurity, umbracoSettings, urlProviders); Web.Current.SetUmbracoContext(umbracoContext, replaceContext); // will dispose the one that is being replaced return umbracoContext; } @@ -85,14 +83,12 @@ namespace Umbraco.Web /// internal static UmbracoContext CreateContext( HttpContextBase httpContext, - ApplicationContext applicationContext, IFacadeService facadeService, WebSecurity webSecurity, IUmbracoSettingsSection umbracoSettings, IEnumerable urlProviders) { if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); - if (applicationContext == null) throw new ArgumentNullException(nameof(applicationContext)); if (webSecurity == null) throw new ArgumentNullException(nameof(webSecurity)); if (umbracoSettings == null) throw new ArgumentNullException(nameof(umbracoSettings)); if (urlProviders == null) throw new ArgumentNullException(nameof(urlProviders)); @@ -100,7 +96,6 @@ namespace Umbraco.Web // create the context var umbracoContext = new UmbracoContext( httpContext, - applicationContext, facadeService, webSecurity); @@ -126,12 +121,10 @@ namespace Umbraco.Web } /// An HttpContext. - /// An Umbraco application context. /// A facade service. /// A web security. private UmbracoContext( HttpContextBase httpContext, - ApplicationContext applicationContext, IFacadeService facadeService, WebSecurity webSecurity) { @@ -146,13 +139,11 @@ namespace Umbraco.Web httpContext.DisposeOnPipelineCompleted(this); if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); - if (applicationContext == null) throw new ArgumentNullException(nameof(applicationContext)); ObjectCreated = DateTime.Now; UmbracoRequestId = Guid.NewGuid(); HttpContext = httpContext; - Application = applicationContext; Security = webSecurity; // beware - we cannot expect a current user here, so detecting preview mode must be a lazy thing @@ -189,11 +180,6 @@ namespace Umbraco.Web /// internal Guid UmbracoRequestId { get; private set; } - /// - /// Gets the current ApplicationContext - /// - public ApplicationContext Application { get; private set; } - /// /// Gets the WebSecurity class /// diff --git a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs index addcfea651..a2a229c9a0 100644 --- a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs +++ b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs @@ -1,18 +1,11 @@ using System; -using System.Linq; -using System.Web; using Microsoft.AspNet.SignalR; using Microsoft.Owin; -using Microsoft.Owin.Extensions; -using Microsoft.Owin.Logging; using Owin; using Umbraco.Core; -using Umbraco.Core.Logging; using Umbraco.Core.Security; using Umbraco.Core.Services; -using Umbraco.Core.Sync; using Umbraco.Web; -using Umbraco.Web.Cache; using Umbraco.Web.Security.Identity; using Umbraco.Web.SignalR; @@ -35,8 +28,7 @@ namespace Umbraco.Web public virtual void Configuration(IAppBuilder app) { app.SanitizeThreadCulture(); - - ConfigureServices(app); + ConfigureServices(app, Current.Services); ConfigureMiddleware(app); ConfigureSignalR(app); } @@ -45,14 +37,15 @@ namespace Umbraco.Web /// Configures services to be created in the OWIN context (CreatePerOwinContext) /// /// - protected virtual void ConfigureServices(IAppBuilder app) + /// + protected virtual void ConfigureServices(IAppBuilder app, ServiceContext services) { app.SetUmbracoLoggerFactory(); //Configure the Identity user manager for use with Umbraco Back office // (EXPERT: an overload accepts a custom BackOfficeUserStore implementation) app.ConfigureUserManagerForUmbracoBackOffice( - ApplicationContext, + services, Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider().AsUmbracoMembershipProvider()); } @@ -65,9 +58,9 @@ namespace Umbraco.Web //Ensure owin is configured for Umbraco back office authentication. If you have any front-end OWIN // cookie configuration, this must be declared after it. app - .UseUmbracoBackOfficeCookieAuthentication(ApplicationContext, PipelineStage.Authenticate) - .UseUmbracoBackOfficeExternalCookieAuthentication(ApplicationContext, PipelineStage.Authenticate) - .UseUmbracoPreviewAuthentication(ApplicationContext, PipelineStage.Authorize) + .UseUmbracoBackOfficeCookieAuthentication(Current.RuntimeState, PipelineStage.Authenticate) + .UseUmbracoBackOfficeExternalCookieAuthentication(Current.RuntimeState, PipelineStage.Authenticate) + .UseUmbracoPreviewAuthentication(Current.RuntimeState, PipelineStage.Authorize) .FinalizeMiddlewareConfiguration(); } @@ -85,8 +78,6 @@ namespace Umbraco.Web PreviewHub.Initialize(_previewHubContext); } - protected virtual ApplicationContext ApplicationContext => ApplicationContext.Current; - public static event EventHandler MiddlewareConfigured; internal static void OnMiddlewareConfigured(OwinMiddlewareConfiguredEventArgs args) diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index 92e27f1e0a..93d2b3ab29 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -23,10 +23,13 @@ namespace Umbraco.Web /// public class UmbracoHelper : IUmbracoComponentRenderer { - private readonly UmbracoContext _umbracoContext; + private static readonly HtmlStringUtilities StringUtilities = new HtmlStringUtilities(); + + private readonly UmbracoContext _umbracoContext; private readonly IPublishedContent _currentPage; private readonly IPublishedContentQuery _iQuery; - private readonly HtmlStringUtilities _stringUtilities = new HtmlStringUtilities(); + private readonly ServiceContext _services; + private readonly CacheHelper _appCache; private IUmbracoComponentRenderer _componentRenderer; private PublishedContentQuery _query; @@ -36,90 +39,22 @@ namespace Umbraco.Web private UrlProvider _urlProvider; private ICultureDictionary _cultureDictionary; - /// - /// Lazy instantiates the tag context - /// - public ITagQuery TagQuery => _tag ?? - (_tag = new TagQuery(UmbracoContext.Application.Services.TagService, - _iQuery ?? ContentQuery)); - - /// - /// Lazy instantiates the query context if not specified in the constructor - /// - public PublishedContentQuery ContentQuery => _query ?? - (_query = _iQuery != null - ? new PublishedContentQuery(_iQuery) - : new PublishedContentQuery(UmbracoContext.ContentCache, UmbracoContext.MediaCache)); - - /// - /// Helper method to ensure an umbraco context is set when it is needed - /// - public UmbracoContext UmbracoContext - { - get - { - if (_umbracoContext == null) - { - throw new NullReferenceException("No " + typeof(UmbracoContext) + " reference has been set for this " + typeof(UmbracoHelper) + " instance"); - } - return _umbracoContext; - } - } - - /// - /// Lazy instantiates the membership helper if not specified in the constructor - /// - public MembershipHelper MembershipHelper => _membershipHelper ?? (_membershipHelper = new MembershipHelper(UmbracoContext)); - - /// - /// Lazy instantiates the UrlProvider if not specified in the constructor - /// - public UrlProvider UrlProvider => _urlProvider ?? - (_urlProvider = UmbracoContext.UrlProvider); - - /// - /// Lazy instantiates the IDataTypeService if not specified in the constructor - /// - public IDataTypeService DataTypeService => _dataTypeService ?? - (_dataTypeService = UmbracoContext.Application.Services.DataTypeService); - - /// - /// Lazy instantiates the IUmbracoComponentRenderer if not specified in the constructor - /// - public IUmbracoComponentRenderer UmbracoComponentRenderer => _componentRenderer ?? - (_componentRenderer = new UmbracoComponentRenderer(UmbracoContext)); - #region Constructors - /// - /// Empty constructor to create an umbraco helper for access to methods that don't have dependencies - /// - public UmbracoHelper() - { - } /// - /// Constructor accepting all dependencies + /// Initializes a new instance of the class. /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// This constructor can be used to create a testable UmbracoHelper - /// - public UmbracoHelper(UmbracoContext umbracoContext, IPublishedContent content, + /// For tests. + internal UmbracoHelper(UmbracoContext umbracoContext, IPublishedContent content, IPublishedContentQuery query, ITagQuery tagQuery, IDataTypeService dataTypeService, UrlProvider urlProvider, ICultureDictionary cultureDictionary, IUmbracoComponentRenderer componentRenderer, - MembershipHelper membershipHelper) + MembershipHelper membershipHelper, + ServiceContext services, + CacheHelper appCache) { if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); if (content == null) throw new ArgumentNullException(nameof(content)); @@ -130,6 +65,8 @@ namespace Umbraco.Web if (cultureDictionary == null) throw new ArgumentNullException(nameof(cultureDictionary)); if (componentRenderer == null) throw new ArgumentNullException(nameof(componentRenderer)); if (membershipHelper == null) throw new ArgumentNullException(nameof(membershipHelper)); + if (services == null) throw new ArgumentNullException(nameof(services)); + if (appCache == null) throw new ArgumentNullException(nameof(appCache)); _umbracoContext = umbracoContext; _tag = new TagQuery(tagQuery); @@ -140,38 +77,108 @@ namespace Umbraco.Web _membershipHelper = membershipHelper; _currentPage = content; _iQuery = query; + _services = services; + _appCache = appCache; } /// - /// Custom constructor setting the current page to the parameter passed in + /// Initializes a new instance of the class. /// - /// - /// - public UmbracoHelper(UmbracoContext umbracoContext, IPublishedContent content) - : this(umbracoContext) + /// For tests - nothing is initialized. + internal UmbracoHelper() + { } + + + /// + /// Initializes a new instance of the class with an Umbraco context + /// and a specific content item. + /// + /// An Umbraco context. + /// A content item. + /// A services context. + /// An application cache helper. + /// Sets the current page to the supplied content item. + public UmbracoHelper(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache, IPublishedContent content) + : this(umbracoContext, services, appCache) { if (content == null) throw new ArgumentNullException(nameof(content)); _currentPage = content; } /// - /// Standard constructor setting the current page to the page that has been routed to + /// Initializes a new instance of the class with an Umbraco context. /// - /// - public UmbracoHelper(UmbracoContext umbracoContext) + /// An Umbraco context. + /// A services context. + /// An application cache helper. + /// Sets the current page to the context's published content request's content item. + public UmbracoHelper(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) { if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); - if (umbracoContext.RoutingContext == null) throw new NullReferenceException("The RoutingContext on the UmbracoContext cannot be null"); + if (services == null) throw new ArgumentNullException(nameof(services)); + if (appCache == null) throw new ArgumentNullException(nameof(appCache)); + if (umbracoContext.RoutingContext == null) throw new NullReferenceException("The RoutingContext on the UmbracoContext cannot be null."); _umbracoContext = umbracoContext; if (_umbracoContext.IsFrontEndUmbracoRequest) - { _currentPage = _umbracoContext.PublishedContentRequest.PublishedContent; - } + _services = services; + _appCache = appCache; } #endregion + /// + /// Gets the tag context. + /// + public ITagQuery TagQuery => _tag ?? + (_tag = new TagQuery(_services.TagService, _iQuery ?? ContentQuery)); + + /// + /// Gets the query context. + /// + public PublishedContentQuery ContentQuery => _query ?? + (_query = _iQuery != null + ? new PublishedContentQuery(_iQuery) + : new PublishedContentQuery(UmbracoContext.ContentCache, UmbracoContext.MediaCache)); + + /// + /// Gets the Umbraco context. + /// + public UmbracoContext UmbracoContext + { + get + { + if (_umbracoContext == null) + throw new NullReferenceException("UmbracoContext has not been set."); + return _umbracoContext; + } + } + + /// + /// Gets the membership helper. + /// + public MembershipHelper MembershipHelper => _membershipHelper + ?? (_membershipHelper = new MembershipHelper(UmbracoContext)); + + /// + /// Gets the url provider. + /// + public UrlProvider UrlProvider => _urlProvider + ?? (_urlProvider = UmbracoContext.UrlProvider); + + /// + /// Gets the datatype service. + /// + private IDataTypeService DataTypeService => _dataTypeService + ?? (_dataTypeService = _services.DataTypeService); + + /// + /// Gets the component renderer. + /// + public IUmbracoComponentRenderer UmbracoComponentRenderer => _componentRenderer + ?? (_componentRenderer = new UmbracoComponentRenderer(UmbracoContext)); + /// /// Returns the current IPublishedContent item assigned to the UmbracoHelper /// @@ -195,7 +202,7 @@ namespace Umbraco.Web } /// - /// Renders the template for the specified pageId and an optional altTemplateId + /// Renders the template for the specified pageId and an optional altTemplateId. /// /// /// If not specified, will use the template assigned to the node @@ -256,19 +263,10 @@ namespace Umbraco.Web /// /// Returns the ICultureDictionary for access to dictionary items /// - public ICultureDictionary CultureDictionary - { - get - { - if (_cultureDictionary == null) - { - _cultureDictionary = Current.CultureDictionaryFactory.CreateDictionary(); - } - return _cultureDictionary; - } - } + public ICultureDictionary CultureDictionary => _cultureDictionary + ?? (_cultureDictionary = Current.CultureDictionaryFactory.CreateDictionary()); - #endregion + #endregion #region Membership @@ -286,7 +284,7 @@ namespace Umbraco.Web /// True if the document object is protected public bool IsProtected(string path) { - return UmbracoContext.Application.Services.PublicAccessService.IsProtected(path); + return _services.PublicAccessService.IsProtected(path); } [EditorBrowsable(EditorBrowsableState.Never)] @@ -306,7 +304,7 @@ namespace Umbraco.Web if (IsProtected(path)) { return MembershipHelper.IsLoggedIn() - && UmbracoContext.Application.Services.PublicAccessService.HasAccess(path, GetCurrentMember(), Roles.Provider); + && _services.PublicAccessService.HasAccess(path, GetCurrentMember(), Roles.Provider); } return true; } @@ -316,12 +314,11 @@ namespace Umbraco.Web /// private MembershipUser GetCurrentMember() { - return UmbracoContext.Application.ApplicationCache.RequestCache - .GetCacheItem("UmbracoHelper.GetCurrentMember", () => - { - var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); - return provider.GetCurrentUser(); - }); + return _appCache.RequestCache.GetCacheItem("UmbracoHelper.GetCurrentMember", () => + { + var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); + return provider.GetCurrentUser(); + }); } /// @@ -683,7 +680,7 @@ namespace Umbraco.Web /// The text with text line breaks replaced with html linebreaks (
)
public string ReplaceLineBreaksForHtml(string text) { - return _stringUtilities.ReplaceLineBreaksForHtml(text); + return StringUtilities.ReplaceLineBreaksForHtml(text); } /// @@ -709,7 +706,7 @@ namespace Umbraco.Web /// public HtmlString StripHtml(string html, params string[] tags) { - return _stringUtilities.StripHtmlTags(html, tags); + return StringUtilities.StripHtmlTags(html, tags); } /// @@ -717,7 +714,7 @@ namespace Umbraco.Web /// public string Coalesce(params object[] args) { - return _stringUtilities.Coalesce(args); + return StringUtilities.Coalesce(args); } /// @@ -725,7 +722,7 @@ namespace Umbraco.Web /// public string Concatenate(params object[] args) { - return _stringUtilities.Concatenate(args); + return StringUtilities.Concatenate(args); } /// @@ -733,7 +730,7 @@ namespace Umbraco.Web /// public string Join(string separator, params object[] args) { - return _stringUtilities.Join(separator, args); + return StringUtilities.Join(separator, args); } /// @@ -781,7 +778,7 @@ namespace Umbraco.Web /// public IHtmlString Truncate(string html, int length, bool addElipsis, bool treatTagsAsContent) { - return _stringUtilities.Truncate(html, length, addElipsis, treatTagsAsContent); + return StringUtilities.Truncate(html, length, addElipsis, treatTagsAsContent); } diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index 0e878da5e6..b65eb5ed80 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -34,7 +34,7 @@ namespace Umbraco.Web static void BeginRequest(HttpContextBase httpContext) { // ensure application url is initialized - ApplicationUrlHelper.EnsureApplicationUrl(ApplicationContext.Current, httpContext.Request); + ((RuntimeState)Current.RuntimeState).EnsureApplicationUrl(httpContext.Request); // do not process if client-side request if (httpContext.Request.Url.IsClientSideRequest()) @@ -53,9 +53,9 @@ namespace Umbraco.Web // create the UmbracoContext singleton, one per request, and assign // NOTE: we assign 'true' to ensure the context is replaced if it is already set (i.e. during app startup) UmbracoContext.EnsureContext( - httpContext, ApplicationContext.Current, + httpContext, Current.FacadeService, - new WebSecurity(httpContext, ApplicationContext.Current), + new WebSecurity(httpContext, Current.Services.UserService), UmbracoConfig.For.UmbracoSettings(), Current.UrlProviders, true); @@ -86,20 +86,18 @@ namespace Umbraco.Web var umbracoContext = UmbracoContext.Current; - //re-write for the default back office path + // re-write for the default back office path if (httpContext.Request.Url.IsDefaultBackOfficeRequest()) { - if (EnsureIsConfigured(httpContext, umbracoContext.OriginalRequestUrl)) - { + if (EnsureRuntime(httpContext, umbracoContext.OriginalRequestUrl)) RewriteToBackOfficeHandler(httpContext); - } return; } - // do not process if this request is not a front-end routable page var isRoutableAttempt = EnsureUmbracoRoutablePage(umbracoContext, httpContext); - //raise event here + + // raise event here OnRouteAttempt(new RoutableAttemptEventArgs(isRoutableAttempt.Result, umbracoContext, httpContext)); if (isRoutableAttempt.Success == false) return; @@ -149,16 +147,12 @@ namespace Umbraco.Web { reason = EnsureRoutableOutcome.NotDocumentRequest; } - // ensure Umbraco is ready to serve documents - else if (EnsureIsReady(httpContext, uri) == false) + // ensure the runtime is in the proper state + // and deal with needed redirects, etc + else if (EnsureRuntime(httpContext, uri) == false) { reason = EnsureRoutableOutcome.NotReady; } - // ensure Umbraco is properly configured to serve documents - else if (EnsureIsConfigured(httpContext, uri) == false) - { - reason = EnsureRoutableOutcome.NotConfigured; - } // ensure Umbraco has documents to serve else if (EnsureHasContent(context, httpContext) == false) { @@ -174,7 +168,7 @@ namespace Umbraco.Web /// /// /// - bool EnsureDocumentRequest(HttpContextBase httpContext, Uri uri) + private bool EnsureDocumentRequest(HttpContextBase httpContext, Uri uri) { var maybeDoc = true; var lpath = uri.AbsolutePath.ToLowerInvariant(); @@ -221,31 +215,66 @@ namespace Umbraco.Web return maybeDoc; } - // ensures Umbraco is ready to handle requests - // if not, set status to 503 and transfer request, and return false - // if yes, return true - static bool EnsureIsReady(HttpContextBase httpContext, Uri uri) - { - var ready = ApplicationContext.Current.IsReady; + private static bool EnsureRuntime(HttpContextBase httpContext, Uri uri) + { + var debug = Current.RuntimeState.Debug; + var level = Current.RuntimeState.Level; + switch (level) + { + case RuntimeLevel.Unknown: + case RuntimeLevel.Boot: + // not ready yet, but wait + ReportRuntime(level, "Umbraco is booting."); - // ensure we are ready - if (ready) return true; - LogHelper.Warn("Umbraco is not ready"); + // let requests pile up and wait for 10s then show the splash anyway + if (UmbracoConfig.For.UmbracoSettings().Content.EnableSplashWhileLoading == false + && ((RuntimeState) Current.RuntimeState).WaitForRunLevel(TimeSpan.FromSeconds(10))) return true; - if (UmbracoConfig.For.UmbracoSettings().Content.EnableSplashWhileLoading == false) - { - // let requests pile up and wait for 10s then show the splash anyway - ready = ApplicationContext.Current.WaitForReady(10 * 1000); - } + // redirect to booting page + httpContext.Response.StatusCode = 503; // temp not available + const string bootUrl = "~/config/splashes/booting.aspx"; + httpContext.Response.AddHeader("Retry-After", debug ? "1" : "30"); // seconds + httpContext.RewritePath(UriUtility.ToAbsolute(bootUrl) + "?url=" + HttpUtility.UrlEncode(uri.ToString())); + return false; // cannot serve content - if (ready) return true; + case RuntimeLevel.Failed: + // redirect to death page + ReportRuntime(level, "Umbraco has failed."); - httpContext.Response.StatusCode = 503; - const string bootUrl = "~/config/splashes/booting.aspx"; - httpContext.RewritePath(UriUtility.ToAbsolute(bootUrl) + "?url=" + HttpUtility.UrlEncode(uri.ToString())); + httpContext.Response.StatusCode = 503; // temp not available + const string deathUrl = "~/config/splashes/death.aspx"; + httpContext.Response.AddHeader("Retry-After", debug ? "1" : "300"); // seconds + httpContext.RewritePath(UriUtility.ToAbsolute(deathUrl) + "?url=" + HttpUtility.UrlEncode(uri.ToString())); + return false; // cannot serve content - return false; - } + case RuntimeLevel.Run: + // ok + return true; + + case RuntimeLevel.Install: + case RuntimeLevel.Upgrade: + // redirect to install + ReportRuntime(level, "Umbraco must install or upgrade."); + var installPath = UriUtility.ToAbsolute(SystemDirectories.Install); + var installUrl = $"{installPath}/?redir=true&url={HttpUtility.UrlEncode(uri.ToString())}"; + httpContext.Response.Redirect(installUrl, true); + return false; // cannot serve content + + default: + throw new NotSupportedException($"Unexpected runtime level: {Current.RuntimeState.Level}."); + } + } + + private static bool _reported; + private static RuntimeLevel _reportedLevel; + + private static void ReportRuntime(RuntimeLevel level, string message) + { + if (_reported && _reportedLevel == level) return; + _reported = true; + _reportedLevel = level; + Current.Logger.Warn(message); + } // ensures Umbraco has at least one published node // if not, rewrites to splash and return false @@ -263,30 +292,6 @@ namespace Umbraco.Web return false; } - private bool _notConfiguredReported; - - // ensures Umbraco is configured - // if not, redirect to install and return false - // if yes, return true - private bool EnsureIsConfigured(HttpContextBase httpContext, Uri uri) - { - if (ApplicationContext.Current.IsConfigured) - return true; - - if (_notConfiguredReported) - { - // remember it's been reported so we don't flood the log - // no thread-safety so there may be a few log entries, doesn't matter - _notConfiguredReported = true; - LogHelper.Warn("Umbraco is not configured"); - } - - var installPath = UriUtility.ToAbsolute(SystemDirectories.Install); - var installUrl = $"{installPath}/?redir=true&url={HttpUtility.UrlEncode(uri.ToString())}"; - httpContext.Response.Redirect(installUrl, true); - return false; - } - // returns a value indicating whether redirection took place and the request has // been completed - because we don't want to Response.End() here to terminate // everything properly. diff --git a/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs b/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs index 882ba278f4..1d7db6a849 100644 --- a/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs +++ b/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs @@ -18,6 +18,7 @@ using Newtonsoft.Json.Serialization; using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Models; +using Umbraco.Core.Services; using Umbraco.Web.Editors; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.PublishedCache; @@ -40,16 +41,7 @@ namespace Umbraco.Web.WebApi.Binders where TPersisted : class, IContentBase where TModelSave : ContentBaseItemSave { - protected ApplicationContext ApplicationContext { get; private set; } - - /// - /// Constructor - /// - /// - internal ContentItemBaseBinder(ApplicationContext applicationContext) - { - ApplicationContext = applicationContext; - } + protected ServiceContext Services => Current.Services; // fixme - inject public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { @@ -212,7 +204,7 @@ namespace Umbraco.Web.WebApi.Binders foreach (var propertyDto in dto.Properties) { if (propertyDto.Alias != p.Alias) continue; - propertyDto.Value = p.Value; + propertyDto.Value = p.Value; break; } } diff --git a/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs b/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs index d832f743c3..3515361c0b 100644 --- a/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs +++ b/src/Umbraco.Web/WebApi/Binders/ContentItemBinder.cs @@ -7,35 +7,21 @@ using Umbraco.Web.Models.Mapping; namespace Umbraco.Web.WebApi.Binders { - internal class ContentItemBinder : ContentItemBaseBinder + internal class ContentItemBinder : ContentItemBaseBinder { - - public ContentItemBinder(ApplicationContext applicationContext) - : base(applicationContext) - { - } - - /// - /// Constructor - /// - public ContentItemBinder() - : this(ApplicationContext.Current) - { - } - protected override IContent GetExisting(ContentItemSave model) { - return ApplicationContext.Services.ContentService.GetById(Convert.ToInt32(model.Id)); + return Services.ContentService.GetById(Convert.ToInt32(model.Id)); } protected override IContent CreateNew(ContentItemSave model) { - var contentType = ApplicationContext.Services.ContentTypeService.Get(model.ContentTypeAlias); + var contentType = Services.ContentTypeService.Get(model.ContentTypeAlias); if (contentType == null) { throw new InvalidOperationException("No content type found wth alias " + model.ContentTypeAlias); } - return new Content(model.Name, model.ParentId, contentType); + return new Content(model.Name, model.ParentId, contentType); } protected override ContentItemDto MapFromPersisted(ContentItemSave model) diff --git a/src/Umbraco.Web/WebApi/Binders/MediaItemBinder.cs b/src/Umbraco.Web/WebApi/Binders/MediaItemBinder.cs index 2a335fdc98..be64a0b690 100644 --- a/src/Umbraco.Web/WebApi/Binders/MediaItemBinder.cs +++ b/src/Umbraco.Web/WebApi/Binders/MediaItemBinder.cs @@ -8,28 +8,15 @@ using Umbraco.Web.Models.Mapping; namespace Umbraco.Web.WebApi.Binders { internal class MediaItemBinder : ContentItemBaseBinder - { - public MediaItemBinder(ApplicationContext applicationContext) - : base(applicationContext) - { - } - - /// - /// Constructor - /// - public MediaItemBinder() - : this(ApplicationContext.Current) - { - } - + { protected override IMedia GetExisting(MediaItemSave model) { - return ApplicationContext.Services.MediaService.GetById(Convert.ToInt32(model.Id)); + return Services.MediaService.GetById(Convert.ToInt32(model.Id)); } protected override IMedia CreateNew(MediaItemSave model) { - var contentType = ApplicationContext.Services.MediaTypeService.Get(model.ContentTypeAlias); + var contentType = Services.MediaTypeService.Get(model.ContentTypeAlias); if (contentType == null) { throw new InvalidOperationException("No content type found wth alias " + model.ContentTypeAlias); diff --git a/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs b/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs index 49669fd427..a96c2f9eb8 100644 --- a/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs +++ b/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs @@ -21,19 +21,6 @@ namespace Umbraco.Web.WebApi.Binders { internal class MemberBinder : ContentItemBaseBinder { - public MemberBinder(ApplicationContext applicationContext) - : base(applicationContext) - { - } - - /// - /// Constructor - /// - public MemberBinder() - : this(ApplicationContext.Current) - { - } - protected override ContentItemValidationHelper GetValidationHelper() { return new MemberValidationHelper(); @@ -46,7 +33,7 @@ namespace Umbraco.Web.WebApi.Binders /// protected override IMember GetExisting(MemberSave model) { - var scenario = ApplicationContext.Services.MemberService.GetMembershipScenario(); + var scenario = Services.MemberService.GetMembershipScenario(); var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); switch (scenario) { @@ -71,12 +58,12 @@ namespace Umbraco.Web.WebApi.Binders // { // var existing = GetExisting(model.Key); // FilterContentTypeProperties(existing.ContentType, existing.ContentType.PropertyTypes.Select(x => x.Alias).ToArray()); - // } + // } //} //generate a member for a generic membership provider //NOTE: We don't care about the password here, so just generate something - //var member = MemberService.CreateGenericMembershipProviderMember(model.Name, model.Email, model.Username, Guid.NewGuid().ToString("N")); + //var member = MemberService.CreateGenericMembershipProviderMember(model.Name, model.Email, model.Username, Guid.NewGuid().ToString("N")); //var convertResult = membershipUser.ProviderUserKey.TryConvertTo(); //if (convertResult.Success == false) @@ -93,7 +80,7 @@ namespace Umbraco.Web.WebApi.Binders private IMember GetExisting(Guid key) { - var member = ApplicationContext.Services.MemberService.GetByKey(key); + var member = Services.MemberService.GetByKey(key); if (member == null) { throw new InvalidOperationException("Could not find member with key " + key); @@ -125,7 +112,7 @@ namespace Umbraco.Web.WebApi.Binders if (provider.IsUmbracoMembershipProvider()) { - var contentType = ApplicationContext.Services.MemberTypeService.Get(model.ContentTypeAlias); + var contentType = Services.MemberTypeService.Get(model.ContentTypeAlias); if (contentType == null) { throw new InvalidOperationException("No member type found wth alias " + model.ContentTypeAlias); @@ -146,7 +133,7 @@ namespace Umbraco.Web.WebApi.Binders //If the default Member type exists, we'll use that to create the IMember - that way we can associate the custom membership // provider to our data - eventually we can support editing custom properties with a custom provider. - var memberType = ApplicationContext.Services.MemberTypeService.Get(Constants.Conventions.MemberTypes.DefaultAlias); + var memberType = Services.MemberTypeService.Get(Constants.Conventions.MemberTypes.DefaultAlias); if (memberType != null) { FilterContentTypeProperties(memberType, memberType.PropertyTypes.Select(x => x.Alias).ToArray()); @@ -203,7 +190,7 @@ namespace Umbraco.Web.WebApi.Binders ///
/// /// - /// + /// protected override bool ValidatePropertyData(ContentItemBasic postedItem, HttpActionContext actionContext) { var memberSave = (MemberSave)postedItem; @@ -212,14 +199,14 @@ namespace Umbraco.Web.WebApi.Binders { actionContext.ModelState.AddPropertyError( new ValidationResult("Invalid user name", new[] { "value" }), - string.Format("{0}login", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); + string.Format("{0}login", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); } if (memberSave.Email.IsNullOrWhiteSpace() || new EmailAddressAttribute().IsValid(memberSave.Email) == false) { actionContext.ModelState.AddPropertyError( new ValidationResult("Invalid email", new[] { "value" }), - string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); + string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); } //default provider! diff --git a/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs b/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs index 1a21c90f96..63c27a77b9 100644 --- a/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs @@ -17,12 +17,12 @@ using Umbraco.Web._Legacy.Actions; namespace Umbraco.Web.WebApi.Filters { /// - /// Auth filter to check if the current user has access to the content item (by id). + /// Auth filter to check if the current user has access to the content item (by id). /// /// - /// + /// /// This first checks if the user can access this based on their start node, and then checks node permissions - /// + /// /// By default the permission that is checked is browse but this can be specified in the ctor. /// NOTE: This cannot be an auth filter because that happens too soon and we don't have access to the action params. /// @@ -51,7 +51,7 @@ namespace Umbraco.Web.WebApi.Filters { _permissionToCheck = permissionToCheck; } - + public override bool AllowMultiple { get { return true; } @@ -88,7 +88,7 @@ namespace Umbraco.Web.WebApi.Filters { throw new InvalidOperationException("No argument found for the current action with the name: " + _paramName); } - nodeId = (int)prop.GetValue(actionContext.ActionArguments[parts[0]]); + nodeId = (int)prop.GetValue(actionContext.ActionArguments[parts[0]]); } } else @@ -99,8 +99,8 @@ namespace Umbraco.Web.WebApi.Filters if (ContentController.CheckPermissions( actionContext.Request.Properties, UmbracoContext.Current.Security.CurrentUser, - ApplicationContext.Current.Services.UserService, - ApplicationContext.Current.Services.ContentService, nodeId, _permissionToCheck.HasValue ? new[]{_permissionToCheck.Value}: null)) + Current.Services.UserService, + Current.Services.ContentService, nodeId, _permissionToCheck.HasValue ? new[]{_permissionToCheck.Value}: null)) { base.OnActionExecuting(actionContext); } @@ -108,10 +108,10 @@ namespace Umbraco.Web.WebApi.Filters { throw new HttpResponseException(actionContext.Request.CreateUserNoAccessResponse()); } - + } - + } } \ No newline at end of file diff --git a/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForMediaAttribute.cs b/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForMediaAttribute.cs index 869fcb0af8..bee07c1017 100644 --- a/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForMediaAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForMediaAttribute.cs @@ -15,7 +15,7 @@ namespace Umbraco.Web.WebApi.Filters /// Auth filter to check if the current user has access to the content item /// /// - /// Since media doesn't have permissions, this simply checks start node access + /// Since media doesn't have permissions, this simply checks start node access /// internal sealed class EnsureUserPermissionForMediaAttribute : ActionFilterAttribute { @@ -42,16 +42,16 @@ namespace Umbraco.Web.WebApi.Filters { Mandate.ParameterNotNullOrEmpty(paramName, "paramName"); _paramName = paramName; - _source = DictionarySource.ActionArguments; + _source = DictionarySource.ActionArguments; } public EnsureUserPermissionForMediaAttribute(string paramName, DictionarySource source) { Mandate.ParameterNotNullOrEmpty(paramName, "paramName"); _paramName = paramName; - _source = source; + _source = source; } - + public override bool AllowMultiple { get { return true; } @@ -97,8 +97,8 @@ namespace Umbraco.Web.WebApi.Filters if (MediaController.CheckPermissions( actionContext.Request.Properties, - UmbracoContext.Current.Security.CurrentUser, - ApplicationContext.Current.Services.MediaService, nodeId)) + UmbracoContext.Current.Security.CurrentUser, + Current.Services.MediaService, nodeId)) { base.OnActionExecuting(actionContext); } @@ -106,7 +106,7 @@ namespace Umbraco.Web.WebApi.Filters { throw new HttpResponseException(System.Net.HttpStatusCode.Unauthorized); } - + } //private object GetValueFromSource(HttpActionContext actionContext, string key) @@ -124,7 +124,7 @@ namespace Umbraco.Web.WebApi.Filters // } //} - + } } \ No newline at end of file diff --git a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs index 7dd33ae0c7..197aeafbfa 100644 --- a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs @@ -12,14 +12,14 @@ using Umbraco.Web._Legacy.Actions; namespace Umbraco.Web.WebApi.Filters { /// - /// This inspects the result of the action that returns a collection of content and removes + /// This inspects the result of the action that returns a collection of content and removes /// any item that the current user doesn't have access to /// internal sealed class FilterAllowedOutgoingContentAttribute : FilterAllowedOutgoingMediaAttribute { private readonly char _permissionToCheck; - public FilterAllowedOutgoingContentAttribute(Type outgoingType) + public FilterAllowedOutgoingContentAttribute(Type outgoingType) : base(outgoingType) { _permissionToCheck = ActionBrowse.Instance.Letter; @@ -41,7 +41,7 @@ namespace Umbraco.Web.WebApi.Filters { base.FilterItems(user, items); - FilterBasedOnPermissions(items, user, ApplicationContext.Current.Services.UserService); + FilterBasedOnPermissions(items, user, Current.Services.UserService); } protected override int GetUserStartNode(IUser user) diff --git a/src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs index a337b36989..aa641dfa18 100644 --- a/src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/LegacyTreeAuthorizeAttribute.cs @@ -14,7 +14,7 @@ namespace Umbraco.Web.WebApi.Filters var treeRequest = httpContext.Result.Request.QueryString["treeType"]; if (treeRequest.IsNullOrWhiteSpace()) return false; - var tree = ApplicationContext.Current.Services.ApplicationTreeService.GetByAlias(treeRequest); + var tree = Current.Services.ApplicationTreeService.GetByAlias(treeRequest); if (tree == null) return false; return UmbracoContext.Current.Security.CurrentUser != null @@ -22,7 +22,7 @@ namespace Umbraco.Web.WebApi.Filters } return false; - + } } } \ No newline at end of file diff --git a/src/Umbraco.Web/WebApi/Filters/UmbracoApplicationAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/UmbracoApplicationAuthorizeAttribute.cs index 23e0fde1c2..54cba655b9 100644 --- a/src/Umbraco.Web/WebApi/Filters/UmbracoApplicationAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/UmbracoApplicationAuthorizeAttribute.cs @@ -34,9 +34,9 @@ namespace Umbraco.Web.WebApi.Filters return true; } - return UmbracoContext.Current.Security.CurrentUser != null - && _appNames.Any(app => UmbracoContext.Current.Security.UserHasAppAccess( - app, UmbracoContext.Current.Security.CurrentUser)); + return Current.UmbracoContext.Security.CurrentUser != null + && _appNames.Any(app => Current.UmbracoContext.Security.UserHasAppAccess( + app, Current.UmbracoContext.Security.CurrentUser)); } } } \ No newline at end of file diff --git a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs index 685f32cc8c..02d1d5c287 100644 --- a/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/UmbracoTreeAuthorizeAttribute.cs @@ -39,16 +39,16 @@ namespace Umbraco.Web.WebApi.Filters return true; } - var apps = _treeAliases.Select(x => ApplicationContext.Current.Services.ApplicationTreeService + var apps = _treeAliases.Select(x => Current.Services.ApplicationTreeService .GetByAlias(x)) .WhereNotNull() .Select(x => x.ApplicationAlias) .Distinct() .ToArray(); - return UmbracoContext.Current.Security.CurrentUser != null - && apps.Any(app => UmbracoContext.Current.Security.UserHasAppAccess( - app, UmbracoContext.Current.Security.CurrentUser)); + return Current.UmbracoContext.Security.CurrentUser != null + && apps.Any(app => Current.UmbracoContext.Security.UserHasAppAccess( + app, Current.UmbracoContext.Security.CurrentUser)); } } } \ No newline at end of file diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index b850532011..177d872b7a 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -1,28 +1,8 @@ -using System.ComponentModel; -using System.Linq; -using System.Web.Http; -using System.Web.Http.ModelBinding; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Validation; -using Umbraco.Web.Models.ContentEditing; - -namespace Umbraco.Web.WebApi +namespace Umbraco.Web.WebApi { /// - /// The base class for auto-routed API controllers for Umbraco + /// Provides a base class for auto-routed Umbraco API controllers. /// public abstract class UmbracoApiController : UmbracoApiControllerBase - { - protected UmbracoApiController() - { - } - - protected UmbracoApiController(UmbracoContext umbracoContext) : base(umbracoContext) - { - } - - protected UmbracoApiController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) : base(umbracoContext, umbracoHelper) - { - } - } + { } } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index f82d73edf7..e91121a77e 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -1,8 +1,10 @@ using System; using System.Web; using System.Web.Http; +using LightInject; using Microsoft.Owin; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; @@ -10,124 +12,89 @@ using Umbraco.Web.Security; namespace Umbraco.Web.WebApi { /// - /// The base class for API controllers that expose Umbraco services - THESE ARE NOT AUTO ROUTED + /// Provides a base class for Umbraco API controllers. /// + /// These controllers are NOT auto-routed. public abstract class UmbracoApiControllerBase : ApiController { - protected UmbracoApiControllerBase() - : this(UmbracoContext.Current) - { + private UmbracoHelper _umbracoHelper; - } + // for debugging purposes + internal Guid InstanceId { get; } = Guid.NewGuid(); - protected UmbracoApiControllerBase(UmbracoContext umbracoContext) - { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); - UmbracoContext = umbracoContext; - InstanceId = Guid.NewGuid(); - } - - protected UmbracoApiControllerBase(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) - { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); - if (umbracoHelper == null) throw new ArgumentNullException("umbracoHelper"); - UmbracoContext = umbracoContext; - InstanceId = Guid.NewGuid(); - _umbraco = umbracoHelper; - } - - private UmbracoHelper _umbraco; + // note + // properties marked as [Inject] below will be property-injected (vs constructor-injected) in + // order to keep the constuctor as light as possible, so that ppl implementing eg a SurfaceController + // don't need to implement complex constructors + need to refactor them each time we change ours. + // this means that these properties have a setter. + // what can go wrong? /// - /// Tries to retrieve the current HttpContext if one exists. + /// Gets or sets the Umbraco context. + /// + [Inject] + public virtual UmbracoContext UmbracoContext { get; set; } + + /// + /// Gets or sets the database context. + /// + [Inject] + public DatabaseContext DatabaseContext { get; set; } + + /// + /// Gets or sets the services context. + /// + [Inject] + public ServiceContext Services { get; set; } + + /// + /// Gets or sets the application cache. + /// + [Inject] + public CacheHelper ApplicationCache { get; set; } + + /// + /// Gets or sets the logger. + /// + [Inject] + public ILogger Logger { get; set; } + + /// + /// Gets or sets the profiling logger. + /// + [Inject] + public ProfilingLogger ProfilingLogger { get; set; } + + /// + /// Gets the membership helper. + /// + public MembershipHelper Members => Umbraco.MembershipHelper; + + /// + /// Gets the Umbraco helper. + /// + public UmbracoHelper Umbraco => _umbracoHelper + ?? (_umbracoHelper = new UmbracoHelper(UmbracoContext, Services, ApplicationCache)); + + /// + /// Gets the web security helper. + /// + public WebSecurity Security => UmbracoContext.Security; + + /// + /// Tries to get the current HttpContext. /// - /// protected Attempt TryGetHttpContext() { return Request.TryGetHttpContext(); } /// - /// Tries to retrieve the current HttpContext if one exists. + /// Tries to get the current OWIN context. /// - /// protected Attempt TryGetOwinContext() { return Request.TryGetOwinContext(); - } - - /// - /// Returns an ILogger - /// - public ILogger Logger - { - get { return ProfilingLogger.Logger; } - } - - /// - /// Returns a ProfilingLogger - /// - public virtual ProfilingLogger ProfilingLogger - { - get { return UmbracoContext.Application.ProfilingLogger; } - } - - /// - /// Returns the current ApplicationContext - /// - public virtual ApplicationContext ApplicationContext - { - get { return UmbracoContext.Application; } - } - - /// - /// Returns a ServiceContext - /// - public ServiceContext Services - { - get { return ApplicationContext.Services; } - } - - /// - /// Returns a DatabaseContext - /// - public DatabaseContext DatabaseContext - { - get { return ApplicationContext.DatabaseContext; } - } - - /// - /// Returns an UmbracoHelper object - /// - public virtual UmbracoHelper Umbraco - { - get { return _umbraco ?? (_umbraco = new UmbracoHelper(UmbracoContext)); } - } - - /// - /// Returns the current UmbracoContext - /// - public virtual UmbracoContext UmbracoContext { get; private set; } - - /// - /// Returns the WebSecurity instance - /// - public WebSecurity Security - { - get { return UmbracoContext.Security; } - } - - /// - /// Returns the MemberHelper instance - /// - public MembershipHelper Members - { - get { return Umbraco.MembershipHelper; } - } - - /// - /// Useful for debugging - /// - internal Guid InstanceId { get; private set; } + } } } \ No newline at end of file diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs index 028c835d90..f05240bea0 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs @@ -6,8 +6,8 @@ namespace Umbraco.Web.WebApi { /// - /// Ensures authorization is successful for a back office user - /// + /// Ensures authorization is successful for a back office user. + /// public sealed class UmbracoAuthorizeAttribute : AuthorizeAttribute { /// @@ -15,33 +15,29 @@ namespace Umbraco.Web.WebApi /// internal static bool Enable = true; - private readonly ApplicationContext _applicationContext; + // fixme - inject! private readonly UmbracoContext _umbracoContext; + private readonly IRuntimeState _runtimeState; - private ApplicationContext GetApplicationContext() - { - return _applicationContext ?? ApplicationContext.Current; - } + private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private UmbracoContext GetUmbracoContext() - { - return _umbracoContext ?? UmbracoContext.Current; - } + private UmbracoContext UmbracoContext => _umbracoContext ?? Current.UmbracoContext; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS /// /// - public UmbracoAuthorizeAttribute(UmbracoContext umbracoContext) + /// + public UmbracoAuthorizeAttribute(UmbracoContext umbracoContext, IRuntimeState runtimeState) { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); + if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); _umbracoContext = umbracoContext; - _applicationContext = _umbracoContext.Application; + _runtimeState = runtimeState; } public UmbracoAuthorizeAttribute() - { - } + { } protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext) { @@ -52,16 +48,11 @@ namespace Umbraco.Web.WebApi try { - var appContext = GetApplicationContext(); - var umbContext = GetUmbracoContext(); - - //we need to that the app is configured and that a user is logged in - if (appContext.IsConfigured == false) - return false; - - var isLoggedIn = umbContext.Security.ValidateCurrentUser(); - - return isLoggedIn; + // if not configured (install or upgrade) then we can continue + // otherwise we need to ensure that a user is logged in + return RuntimeState.Level == RuntimeLevel.Install + || RuntimeState.Level == RuntimeLevel.Upgrade + || UmbracoContext.Security.ValidateCurrentUser(); } catch (Exception) { diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs index 6f9abcbdcb..c396b6ab55 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs @@ -1,18 +1,12 @@ -using System; -using System.Web; -using System.Web.Http; -using Umbraco.Core.Configuration; -using Umbraco.Web.Security; -using Umbraco.Web.WebApi.Filters; -using umbraco.BusinessLogic; +using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.WebApi { /// - /// A base controller that ensures all requests are authorized - the user is logged in. + /// Provides a base class for autorized auto-routed Umbraco API controllers. /// /// - /// This controller will also append a custom header to the response if the user is logged in using forms authentication + /// This controller will also append a custom header to the response if the user is logged in using forms authentication /// which indicates the seconds remaining before their timeout expires. /// [IsBackOffice] @@ -21,18 +15,5 @@ namespace Umbraco.Web.WebApi [DisableBrowserCache] [UmbracoWebApiRequireHttps] public abstract class UmbracoAuthorizedApiController : UmbracoApiController - { - protected UmbracoAuthorizedApiController() - { - } - - protected UmbracoAuthorizedApiController(UmbracoContext umbracoContext) : base(umbracoContext) - { - } - - protected UmbracoAuthorizedApiController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper) : base(umbracoContext, umbracoHelper) - { - } - - } + { } } \ No newline at end of file diff --git a/src/Umbraco.Web/WebRuntime.cs b/src/Umbraco.Web/WebRuntime.cs index a19e826d5d..2065f443ca 100644 --- a/src/Umbraco.Web/WebRuntime.cs +++ b/src/Umbraco.Web/WebRuntime.cs @@ -1,63 +1,19 @@ using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Configuration; -using System.Linq; using System.Web; -using System.Web.Configuration; -using System.Web.Http; -using System.Web.Http.Dispatcher; -using System.Web.Mvc; -using System.Web.Routing; -using ClientDependency.Core.Config; -using Examine; using LightInject; using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.Dictionary; using Umbraco.Core.Logging; -using Umbraco.Core.Macros; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.PropertyEditors.ValueConverters; -using Umbraco.Core.Sync; -using Umbraco.Web.Dictionary; -using Umbraco.Web.Install; -using Umbraco.Web.Media; -using Umbraco.Web.Media.ThumbnailProviders; -using Umbraco.Web.Mvc; -using Umbraco.Web.PublishedCache; -using Umbraco.Web.Routing; -using Umbraco.Web.Security; -using Umbraco.Web.UI.JavaScript; -using Umbraco.Web.WebApi; -using Umbraco.Core.Events; using Umbraco.Core.Cache; -using Umbraco.Core.Services; -using Umbraco.Web.Services; -using Umbraco.Web.Editors; using Umbraco.Core.DependencyInjection; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.UnitOfWork; -using Umbraco.Core.Plugins; -using Umbraco.Core.Services.Changes; -using Umbraco.Web.Cache; -using Umbraco.Web.DependencyInjection; -using Umbraco.Web.HealthCheck; -using Umbraco.Web.HealthCheck.Checks.DataIntegrity; -using Umbraco.Web._Legacy.Actions; -using UmbracoExamine; -using Action = System.Action; -using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings; -using ProfilingViewEngine = Umbraco.Core.Profiling.ProfilingViewEngine; -using TypeHelper = Umbraco.Core.Plugins.TypeHelper; namespace Umbraco.Web { /// /// Represents the Web Umbraco runtime. /// - /// On top of CoreRuntime, handles all of the web-related aspects of Umbraco (startup, etc). - public class WebRuntime : CoreRuntime // fixme - probably crazy but... could it be a component?! + /// On top of CoreRuntime, handles all of the web-related runtime aspects of Umbraco. + public class WebRuntime : CoreRuntime { /// /// Initializes a new instance of the class. @@ -72,29 +28,22 @@ namespace Umbraco.Web { base.Boot(container); - // now is the time to switch over to perWebRequest scopes + // now (and only now) is the time to switch over to perWebRequest scopes var smp = container.ScopeManagerProvider as MixedScopeManagerProvider; if (smp == null) throw new Exception("Container.ScopeManagerProvider is not MixedScopeManagerProvider."); smp.EnablePerWebRequestScope(); } - /// - public override void Terminate() - { - base.Terminate(); - } - /// public override void Compose(ServiceContainer container) { base.Compose(container); - } - #region Getters + // replace CoreRuntime's IProfiler registration + container.RegisterSingleton(); - protected override IProfiler GetProfiler() => new WebProfiler(); - - protected override CacheHelper GetApplicationCache() => new CacheHelper( + // replace CoreRuntime's CacheHelper registration + container.RegisterSingleton(_ => new CacheHelper( // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), @@ -104,261 +53,29 @@ namespace Umbraco.Web new IsolatedRuntimeCache(type => // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); + + container.RegisterSingleton(); // required for hybrid accessors + container.RegisterSingleton(); // replace CoreRuntime's accessor + } + + #region Getters + + //protected override IProfiler GetProfiler() => new WebProfiler(); + + //protected override CacheHelper GetApplicationCache() => new CacheHelper( + // // we need to have the dep clone runtime cache provider to ensure + // // all entities are cached properly (cloned in and cloned out) + // new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), + // new StaticCacheProvider(), + // // we need request based cache when running in web-based context + // new HttpRequestCacheProvider(), + // new IsolatedRuntimeCache(type => + // // we need to have the dep clone runtime cache provider to ensure + // // all entities are cached properly (cloned in and cloned out) + // new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); #endregion - - #region Web - - internal static void ConfigureGlobalFilters() - { - GlobalFilters.Filters.Add(new EnsurePartialViewMacroViewContextFilterAttribute()); - } - - internal static void WrapViewEngines(IList viewEngines) - { - if (viewEngines == null || viewEngines.Count == 0) return; - - var originalEngines = viewEngines.Select(e => e).ToArray(); - viewEngines.Clear(); - foreach (var engine in originalEngines) - { - var wrappedEngine = engine is ProfilingViewEngine ? engine : new ProfilingViewEngine(engine); - viewEngines.Add(wrappedEngine); - } - } - - protected internal void CreateRoutes() - { - var umbracoPath = GlobalSettings.UmbracoMvcArea; - - //Create the front-end route - var defaultRoute = RouteTable.Routes.MapRoute( - "Umbraco_default", - umbracoPath + "/RenderMvc/{action}/{id}", - new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional } - ); - defaultRoute.RouteHandler = new RenderRouteHandler(ControllerBuilder.Current.GetControllerFactory()); - - //register install routes - RouteTable.Routes.RegisterArea(); - - //register all back office routes - RouteTable.Routes.RegisterArea(); - - //plugin controllers must come first because the next route will catch many things - RoutePluginControllers(); - } - - private static void RoutePluginControllers() - { - var umbracoPath = GlobalSettings.UmbracoMvcArea; - - // need to find the plugin controllers and route them - var pluginControllers = Current.SurfaceControllerTypes - .Concat(Current.UmbracoApiControllerTypes) - .ToArray(); - - // local controllers do not contain the attribute - var localControllers = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace()); - foreach (var s in localControllers) - { - if (TypeHelper.IsTypeAssignableFrom(s)) - RouteLocalSurfaceController(s, umbracoPath); - else if (TypeHelper.IsTypeAssignableFrom(s)) - RouteLocalApiController(s, umbracoPath); - } - - // need to get the plugin controllers that are unique to each area (group by) - var pluginSurfaceControlleres = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace() == false); - var groupedAreas = pluginSurfaceControlleres.GroupBy(controller => PluginController.GetMetadata(controller).AreaName); - // loop through each area defined amongst the controllers - foreach (var g in groupedAreas) - { - // create & register an area for the controllers (this will throw an exception if all controllers are not in the same area) - var pluginControllerArea = new PluginControllerArea(g.Select(PluginController.GetMetadata)); - RouteTable.Routes.RegisterArea(pluginControllerArea); - } - } - - private static void RouteLocalApiController(Type controller, string umbracoPath) - { - var meta = PluginController.GetMetadata(controller); - var url = umbracoPath + (meta.IsBackOffice ? "/BackOffice" : "") + "/Api/" + meta.ControllerName + "/{action}/{id}"; - var route = RouteTable.Routes.MapHttpRoute( - $"umbraco-api-{meta.ControllerName}", - url, // url to match - new { controller = meta.ControllerName, id = UrlParameter.Optional }, - new[] { meta.ControllerNamespace }); - if (route.DataTokens == null) // web api routes don't set the data tokens object - route.DataTokens = new RouteValueDictionary(); - route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "api"); //ensure the umbraco token is set - } - - private static void RouteLocalSurfaceController(Type controller, string umbracoPath) - { - var meta = PluginController.GetMetadata(controller); - var url = umbracoPath + "/Surface/" + meta.ControllerName + "/{action}/{id}"; - var route = RouteTable.Routes.MapRoute( - $"umbraco-surface-{meta.ControllerName}", - url, // url to match - new { controller = meta.ControllerName, action = "Index", id = UrlParameter.Optional }, - new[] { meta.ControllerNamespace }); // look in this namespace to create the controller - route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "surface"); // ensure the umbraco token is set - route.DataTokens.Add("UseNamespaceFallback", false); // don't look anywhere else except this namespace! - // make it use our custom/special SurfaceMvcHandler - route.RouteHandler = new SurfaceRouteHandler(); - } - - #endregion - - /// - /// Initialize objects before anything during the boot cycle happens - /// - /// - public override IRuntime Initialize() - { - //TODO: Fix this - we need to manually perform re-indexing on startup when necessary Examine lib no longer does this - ////This is basically a hack for this item: http://issues.umbraco.org/issue/U4-5976 - // // when Examine initializes it will try to rebuild if the indexes are empty, however in many cases not all of Examine's - // // event handlers will be assigned during bootup when the rebuilding starts which is a problem. So with the examine 0.1.58.2941 build - // // it has an event we can subscribe to in order to cancel this rebuilding process, but what we'll do is cancel it and postpone the rebuilding until the - // // boot process has completed. It's a hack but it works. - //ExamineManager.Instance.BuildingEmptyIndexOnStartup += OnInstanceOnBuildingEmptyIndexOnStartup; - - base.Initialize(); - - // fixme - only here so that everything above can have its OWN scope => must come AFTER?? we have initialized all the components... OR?! - // so that should basically happen AFTER we have Compose() and Initialize() each component = wtf? - // this is all completely fucked - //Container.EnablePerWebRequestScope(); // THAT ONE is causing the issue - // the rest is moving to Compose? - //Container.EnableMvc(); - //Container.RegisterMvcControllers(PluginManager, GetType().Assembly); - //Container.EnableWebApi(GlobalConfiguration.Configuration); - //Container.RegisterApiControllers(PluginManager, GetType().Assembly); - - //setup mvc and webapi services - SetupMvcAndWebApi(); - - // Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK] - ClientDependency.Core.CompositeFiles.Providers.XmlFileMapper.FileMapVirtualFolder = "~/App_Data/TEMP/ClientDependency"; - ClientDependency.Core.CompositeFiles.Providers.BaseCompositeFileProcessingProvider.UrlTypeDefault = ClientDependency.Core.CompositeFiles.Providers.CompositeUrlType.Base64QueryStrings; - - var section = ConfigurationManager.GetSection("system.web/httpRuntime") as HttpRuntimeSection; - if (section != null) - { - //set the max url length for CDF to be the smallest of the max query length, max request length - ClientDependency.Core.CompositeFiles.CompositeDependencyHandler.MaxHandlerUrlLength = Math.Min(section.MaxQueryStringLength, section.MaxRequestLength); - } - - //Register a custom renderer - used to process property editor dependencies - var renderer = new DependencyPathRenderer(); - renderer.Initialize("Umbraco.DependencyPathRenderer", new NameValueCollection - { - { "compositeFileHandlerPath", ClientDependencySettings.Instance.CompositeFileHandlerPath } - }); - ClientDependencySettings.Instance.MvcRendererCollection.Add(renderer); - - // Disable the X-AspNetMvc-Version HTTP Header - MvcHandler.DisableMvcResponseHeader = true; - - InstallHelper.DeleteLegacyInstaller(); - - return this; - } - - /// - /// Override this method in order to ensure that the UmbracoContext is also created, this can only be - /// created after resolution is frozen! - /// - protected override void Complete2() - { - base.Complete2(); - - //before we do anything, we'll ensure the umbraco context - //see: http://issues.umbraco.org/issue/U4-1717 - var httpContext = new HttpContextWrapper(UmbracoApplication.Context); - UmbracoContext.EnsureContext( // fixme - refactor! UmbracoContext & UmbracoRequestContext! - httpContext, Current.ApplicationContext, - Current.FacadeService, - new WebSecurity(httpContext, Current.ApplicationContext), - UmbracoConfig.For.UmbracoSettings(), - Current.UrlProviders, - false); - } - - /// - /// Ensure that the OnApplicationStarted methods of the IApplicationEvents are called - /// - /// - /// - public override IRuntime Complete(Action afterComplete) - { - //Wrap viewengines in the profiling engine - WrapViewEngines(ViewEngines.Engines); - - //add global filters - ConfigureGlobalFilters(); - - //set routes - CreateRoutes(); // fixme - throws, wtf?! - - base.Complete(afterComplete); - - //rebuild any empty indexes - //TODO: Do we want to make this optional? otherwise the only way to disable this on startup - // would be to implement a custom WebBootManager and override this method - RebuildIndexes(true); - - //Now ensure webapi is initialized after everything - GlobalConfiguration.Configuration.EnsureInitialized(); - - return this; - } - - - /// - /// Sets up MVC/WebApi services - /// - private void SetupMvcAndWebApi() - { - //don't output the MVC version header (security) - MvcHandler.DisableMvcResponseHeader = true; - - // set master controller factory - var controllerFactory = new MasterControllerFactory(() => Current.FilteredControllerFactories); - ControllerBuilder.Current.SetControllerFactory(controllerFactory); - - // set the render & plugin view engines - ViewEngines.Engines.Add(new RenderViewEngine()); - ViewEngines.Engines.Add(new PluginViewEngine()); - - //set model binder - ModelBinderProviders.BinderProviders.Add(new ContentModelBinder()); // is a provider - - ////add the profiling action filter - //GlobalFilters.Filters.Add(new ProfilingActionFilter()); - - GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), - new NamespaceHttpControllerSelector(GlobalConfiguration.Configuration)); - } - - protected virtual void RebuildIndexes(bool onlyEmptyIndexes) - { - if (Current.ApplicationContext.IsConfigured == false || Current.ApplicationContext.DatabaseContext.IsDatabaseConfigured == false) - { - return; - } - - foreach (var indexer in ExamineManager.Instance.IndexProviders) - { - if (onlyEmptyIndexes == false || indexer.Value.IsIndexNew()) - { - indexer.Value.RebuildIndex(); - } - } - } } } diff --git a/src/Umbraco.Web/WebRuntimeComponent.cs b/src/Umbraco.Web/WebRuntimeComponent.cs index fd4473237c..0696d68f5b 100644 --- a/src/Umbraco.Web/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/WebRuntimeComponent.cs @@ -1,6 +1,15 @@ using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Configuration; +using System.Linq; using System.Web; +using System.Web.Configuration; using System.Web.Http; +using System.Web.Http.Dispatcher; +using System.Web.Mvc; +using System.Web.Routing; +using ClientDependency.Core.Config; using Examine; using LightInject; using Umbraco.Core; @@ -13,6 +22,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Macros; using Umbraco.Core.Persistence; using Umbraco.Core.Plugins; +using Umbraco.Core.Profiling; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Core.Services; @@ -24,12 +34,15 @@ using Umbraco.Web.Dictionary; using Umbraco.Web.Editors; using Umbraco.Web.HealthCheck; using Umbraco.Web.HealthCheck.Checks.DataIntegrity; +using Umbraco.Web.Install; using Umbraco.Web.Media; using Umbraco.Web.Media.ThumbnailProviders; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; +using Umbraco.Web.Security; using Umbraco.Web.Services; +using Umbraco.Web.UI.JavaScript; using Umbraco.Web.WebApi; using Umbraco.Web._Legacy.Actions; using UmbracoExamine; @@ -40,7 +53,7 @@ namespace Umbraco.Web [RequireComponent(typeof(CoreRuntimeComponent))] public class WebRuntimeComponent : UmbracoComponentBase, IRuntimeComponent { - public override void Compose(ServiceContainer container) + public override void Compose(ServiceContainer container, RuntimeLevel runtimeLevel) { base.Compose(container); @@ -48,14 +61,19 @@ namespace Umbraco.Web var pluginManager = container.GetInstance(); var logger = container.GetInstance(); + var proflog = container.GetInstance(); // register the http context and umbraco context accessors // we *should* use the HttpContextUmbracoContextAccessor, however there are cases when // we have no http context, eg when booting Umbraco or in background threads, so instead // let's use an hybrid accessor that can fall back to a ThreadStatic context. - container.RegisterSingleton(); // replaces HttpContext.Current + // fixme - move that one to runtime + //container.RegisterSingleton(); // replaces HttpContext.Current container.RegisterSingleton(); + // register the 'current' umbraco context - transient - for eg controllers + container.Register(factory => factory.GetInstance().UmbracoContext); + // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request container.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), new PerRequestLifeTime()); @@ -65,13 +83,15 @@ namespace Umbraco.Web // register the umbraco database accessor // have to use the hybrid thing... - container.RegisterSingleton(); + // fixme moving to runtime + //container.RegisterSingleton(); // register a per-request UmbracoContext object // no real need to be per request but assuming it is faster container.Register(factory => factory.GetInstance().UmbracoContext, new PerRequestLifeTime()); // register the umbraco helper + // fixme - FUCK! how can this even work, it's not a singleton! container.RegisterSingleton(); // replace some services @@ -105,72 +125,13 @@ namespace Umbraco.Web // set the default RenderMvcController Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! - //Override the default server messenger, we need to check if the legacy dist calls is enabled, if that is the + // override the default server messenger, we need to check if the legacy dist calls is enabled, if that is the // case, then we'll set the default messenger to be the old one, otherwise we'll set it to the db messenger // which will always be on. if (UmbracoConfig.For.UmbracoSettings().DistributedCall.Enabled) - { - //set the legacy one by default - this maintains backwards compat - container.Register(factory => new BatchedWebServiceServerMessenger(() => - { - var applicationContext = factory.GetInstance(); - //we should not proceed to change this if the app/database is not configured since there will - // be no user, plus we don't need to have server messages sent if this is the case. - if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured) - { - //disable if they are not enabled - if (UmbracoConfig.For.UmbracoSettings().DistributedCall.Enabled == false) - { - return null; - } - - try - { - var user = applicationContext.Services.UserService.GetUserById(UmbracoConfig.For.UmbracoSettings().DistributedCall.UserId); - return new Tuple(user.Username, user.RawPasswordValue); - } - catch (Exception e) - { - logger.Error("An error occurred trying to set the IServerMessenger during application startup", e); - return null; - } - } - logger.Warn("Could not initialize the DefaultServerMessenger, the application is not configured or the database is not configured"); - return null; - }), new PerContainerLifetime()); - } + ComposeLegacyMessenger(container, runtimeLevel, logger); else - { - container.Register(factory => new BatchedDatabaseServerMessenger( - factory.GetInstance(), - true, - //Default options for web including the required callbacks to build caches - new DatabaseServerMessengerOptions - { - //These callbacks will be executed if the server has not been synced - // (i.e. it is a new server or the lastsynced.txt file has been removed) - InitializingCallbacks = new Action[] - { - //rebuild the xml cache file if the server is not synced - () => - { - // rebuild the facade caches entirely, if the server is not synced - // this is equivalent to DistributedCache RefreshAllFacade but local only - // (we really should have a way to reuse RefreshAllFacade... locally) - // note: refresh all content & media caches does refresh content types too - var svc = Current.FacadeService; - bool ignored1, ignored2; - svc.Notify(new[] { new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll) }); - svc.Notify(new[] { new ContentCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out ignored1, out ignored2); - svc.Notify(new[] { new MediaCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out ignored1); - }, - //rebuild indexes if the server is not synced - // NOTE: This will rebuild ALL indexes including the members, if developers want to target specific - // indexes then they can adjust this logic themselves. - () => RebuildIndexes(false) - } - }), new PerContainerLifetime()); - } + ComposeMessenger(container, logger, proflog); ActionCollectionBuilder.Register(container) .SetProducer(() => pluginManager.ResolveActions()); @@ -229,22 +190,279 @@ namespace Umbraco.Web .AddProducer(() => pluginManager.ResolveTypes()) .Exclude(); // fixme must remove else NuCache dies! // but we should also have one for NuCache AND NuCache should be a component that does all this + + // fixme - will this work? others? + container.RegisterAuto(typeof(UmbracoViewPage<>)); } - protected virtual void RebuildIndexes(bool onlyEmptyIndexes) + private void ComposeLegacyMessenger(ServiceContainer container, RuntimeLevel runtimeLevel, ILogger logger) { - if (Current.ApplicationContext.IsConfigured == false || Current.ApplicationContext.DatabaseContext.IsDatabaseConfigured == false) + //set the legacy one by default - this maintains backwards compat + container.Register(factory => { - return; + var userService = factory.GetInstance(); + return new BatchedWebServiceServerMessenger(() => + { + // we should not proceed to change this if the app/database is not configured since there will + // be no user, plus we don't need to have server messages sent if this is the case. + if (runtimeLevel == RuntimeLevel.Run) + { + try + { + var user = userService.GetUserById(UmbracoConfig.For.UmbracoSettings().DistributedCall.UserId); + return Tuple.Create(user.Username, user.RawPasswordValue); + } + catch (Exception e) + { + logger.Error("An error occurred trying to set the IServerMessenger during application startup", e); + return null; + } + } + logger.Warn("Could not initialize the DefaultServerMessenger, the application is not configured or the database is not configured"); + return null; + }); + }, new PerContainerLifetime()); + } + + private void ComposeMessenger(ServiceContainer container, ILogger logger, ProfilingLogger proflog) + { + container.Register(factory => + { + var runtime = factory.GetInstance(); + var databaseContext = factory.GetInstance(); + return new BatchedDatabaseServerMessenger( + runtime, databaseContext, logger, proflog, + true, + //Default options for web including the required callbacks to build caches + new DatabaseServerMessengerOptions + { + //These callbacks will be executed if the server has not been synced + // (i.e. it is a new server or the lastsynced.txt file has been removed) + InitializingCallbacks = new Action[] + { + //rebuild the xml cache file if the server is not synced + () => + { + // rebuild the facade caches entirely, if the server is not synced + // this is equivalent to DistributedCache RefreshAllFacade but local only + // (we really should have a way to reuse RefreshAllFacade... locally) + // note: refresh all content & media caches does refresh content types too + var svc = Current.FacadeService; + bool ignored1, ignored2; + svc.Notify(new[] { new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll) }); + svc.Notify(new[] { new ContentCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out ignored1, out ignored2); + svc.Notify(new[] { new MediaCacheRefresher.JsonPayload(0, TreeChangeTypes.RefreshAll) }, out ignored1); + }, + //rebuild indexes if the server is not synced + // NOTE: This will rebuild ALL indexes including the members, if developers want to target specific + // indexes then they can adjust this logic themselves. + () => RebuildIndexes(false) + } + }); + }, new PerContainerLifetime()); + } + + internal void Initialize( + UmbracoApplicationBase umbracoApplication, + IRuntimeState runtime, + SurfaceControllerTypeCollection surfaceControllerTypes, + UmbracoApiControllerTypeCollection apiControllerTypes) + { + // fixme - need to review & cleanup + + // setup mvc and webapi services + SetupMvcAndWebApi(); + + // Backwards compatibility - set the path and URL type for ClientDependency 1.5.1 [LK] + ClientDependency.Core.CompositeFiles.Providers.XmlFileMapper.FileMapVirtualFolder = "~/App_Data/TEMP/ClientDependency"; + ClientDependency.Core.CompositeFiles.Providers.BaseCompositeFileProcessingProvider.UrlTypeDefault = ClientDependency.Core.CompositeFiles.Providers.CompositeUrlType.Base64QueryStrings; + + var section = ConfigurationManager.GetSection("system.web/httpRuntime") as HttpRuntimeSection; + if (section != null) + { + //set the max url length for CDF to be the smallest of the max query length, max request length + ClientDependency.Core.CompositeFiles.CompositeDependencyHandler.MaxHandlerUrlLength = Math.Min(section.MaxQueryStringLength, section.MaxRequestLength); } - foreach (var indexer in ExamineManager.Instance.IndexProviders) + //Register a custom renderer - used to process property editor dependencies + var renderer = new DependencyPathRenderer(); + renderer.Initialize("Umbraco.DependencyPathRenderer", new NameValueCollection { - if (onlyEmptyIndexes == false || indexer.Value.IsIndexNew()) - { - indexer.Value.RebuildIndex(); - } + { "compositeFileHandlerPath", ClientDependencySettings.Instance.CompositeFileHandlerPath } + }); + ClientDependencySettings.Instance.MvcRendererCollection.Add(renderer); + + // Disable the X-AspNetMvc-Version HTTP Header + MvcHandler.DisableMvcResponseHeader = true; + + InstallHelper.DeleteLegacyInstaller(); + + // wrap view engines in the profiling engine + WrapViewEngines(ViewEngines.Engines); + + // add global filters + ConfigureGlobalFilters(); + + // set routes + CreateRoutes(surfaceControllerTypes, apiControllerTypes); + + //before we do anything, we'll ensure the umbraco context + //see: http://issues.umbraco.org/issue/U4-1717 + var httpContext = new HttpContextWrapper(umbracoApplication.Context); + UmbracoContext.EnsureContext( // fixme - refactor! UmbracoContext & UmbracoRequestContext! + inject, accessor, etc + httpContext, + Current.FacadeService, + new WebSecurity(httpContext, Current.Services.UserService), + UmbracoConfig.For.UmbracoSettings(), + Current.UrlProviders, + false); + + // rebuild any empty indexes + // do we want to make this optional? otherwise the only way to disable this on startup + // would be to implement a custom WebBootManager and override this method + // fixme - move to its own component! and then it could be disabled >> ExamineComponent + // fixme - configuration? + if (runtime.Level == RuntimeLevel.Run) + RebuildIndexes(true); + + // ensure WebAPI is initialized, after everything + GlobalConfiguration.Configuration.EnsureInitialized(); + } + + private static void RebuildIndexes(bool onlyEmptyIndexes) + { + var indexers = (IEnumerable>) ExamineManager.Instance.IndexProviders; + if (onlyEmptyIndexes) + indexers = indexers.Where(x => x.Value.IsIndexNew()); + foreach (var indexer in indexers) + indexer.Value.RebuildIndex(); + } + + private static void ConfigureGlobalFilters() + { + GlobalFilters.Filters.Add(new EnsurePartialViewMacroViewContextFilterAttribute()); + } + + // internal for tests + internal static void WrapViewEngines(IList viewEngines) + { + if (viewEngines == null || viewEngines.Count == 0) return; + + var originalEngines = viewEngines.Select(e => e).ToArray(); + viewEngines.Clear(); + foreach (var engine in originalEngines) + { + var wrappedEngine = engine is ProfilingViewEngine ? engine : new ProfilingViewEngine(engine); + viewEngines.Add(wrappedEngine); } } + + // internal for tests + internal static void CreateRoutes( + SurfaceControllerTypeCollection surfaceControllerTypes, + UmbracoApiControllerTypeCollection apiControllerTypes) + { + var umbracoPath = GlobalSettings.UmbracoMvcArea; + + // create the front-end route + var defaultRoute = RouteTable.Routes.MapRoute( + "Umbraco_default", + umbracoPath + "/RenderMvc/{action}/{id}", + new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional } + ); + defaultRoute.RouteHandler = new RenderRouteHandler(ControllerBuilder.Current.GetControllerFactory()); + + // register install routes + RouteTable.Routes.RegisterArea(); + + // register all back office routes + RouteTable.Routes.RegisterArea(); + + // plugin controllers must come first because the next route will catch many things + RoutePluginControllers(surfaceControllerTypes, apiControllerTypes); + } + + private static void RoutePluginControllers( + SurfaceControllerTypeCollection surfaceControllerTypes, + UmbracoApiControllerTypeCollection apiControllerTypes) + { + var umbracoPath = GlobalSettings.UmbracoMvcArea; + + // need to find the plugin controllers and route them + var pluginControllers = surfaceControllerTypes.Concat(apiControllerTypes).ToArray(); + + // local controllers do not contain the attribute + var localControllers = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace()); + foreach (var s in localControllers) + { + if (TypeHelper.IsTypeAssignableFrom(s)) + RouteLocalSurfaceController(s, umbracoPath); + else if (TypeHelper.IsTypeAssignableFrom(s)) + RouteLocalApiController(s, umbracoPath); + } + + // get the plugin controllers that are unique to each area (group by) + var pluginSurfaceControlleres = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace() == false); + var groupedAreas = pluginSurfaceControlleres.GroupBy(controller => PluginController.GetMetadata(controller).AreaName); + // loop through each area defined amongst the controllers + foreach (var g in groupedAreas) + { + // create & register an area for the controllers (this will throw an exception if all controllers are not in the same area) + var pluginControllerArea = new PluginControllerArea(g.Select(PluginController.GetMetadata)); + RouteTable.Routes.RegisterArea(pluginControllerArea); + } + } + + private static void RouteLocalApiController(Type controller, string umbracoPath) + { + var meta = PluginController.GetMetadata(controller); + var url = umbracoPath + (meta.IsBackOffice ? "/BackOffice" : "") + "/Api/" + meta.ControllerName + "/{action}/{id}"; + var route = RouteTable.Routes.MapHttpRoute( + $"umbraco-api-{meta.ControllerName}", + url, // url to match + new { controller = meta.ControllerName, id = UrlParameter.Optional }, + new[] { meta.ControllerNamespace }); + if (route.DataTokens == null) // web api routes don't set the data tokens object + route.DataTokens = new RouteValueDictionary(); + route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "api"); //ensure the umbraco token is set + } + + private static void RouteLocalSurfaceController(Type controller, string umbracoPath) + { + var meta = PluginController.GetMetadata(controller); + var url = umbracoPath + "/Surface/" + meta.ControllerName + "/{action}/{id}"; + var route = RouteTable.Routes.MapRoute( + $"umbraco-surface-{meta.ControllerName}", + url, // url to match + new { controller = meta.ControllerName, action = "Index", id = UrlParameter.Optional }, + new[] { meta.ControllerNamespace }); // look in this namespace to create the controller + route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "surface"); // ensure the umbraco token is set + route.DataTokens.Add("UseNamespaceFallback", false); // don't look anywhere else except this namespace! + // make it use our custom/special SurfaceMvcHandler + route.RouteHandler = new SurfaceRouteHandler(); + } + + private static void SetupMvcAndWebApi() + { + //don't output the MVC version header (security) + MvcHandler.DisableMvcResponseHeader = true; + + // set master controller factory + var controllerFactory = new MasterControllerFactory(() => Current.FilteredControllerFactories); + ControllerBuilder.Current.SetControllerFactory(controllerFactory); + + // set the render & plugin view engines + ViewEngines.Engines.Add(new RenderViewEngine()); + ViewEngines.Engines.Add(new PluginViewEngine()); + + //set model binder + ModelBinderProviders.BinderProviders.Add(new ContentModelBinder()); // is a provider + + ////add the profiling action filter + //GlobalFilters.Filters.Add(new ProfilingActionFilter()); + + GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), + new NamespaceHttpControllerSelector(GlobalConfiguration.Configuration)); + } } } diff --git a/src/Umbraco.Web/WebServices/BulkPublishController.cs b/src/Umbraco.Web/WebServices/BulkPublishController.cs index 5411beb61f..540cf37806 100644 --- a/src/Umbraco.Web/WebServices/BulkPublishController.cs +++ b/src/Umbraco.Web/WebServices/BulkPublishController.cs @@ -10,7 +10,7 @@ using Umbraco.Web.Mvc; namespace Umbraco.Web.WebServices { /// - /// A REST controller used for the publish dialog in order to publish bulk items at once + /// Represents a REST controller used for the publish dialog in order to bulk-publish bulk content items. /// [ValidateMvcAngularAntiForgeryToken] public class BulkPublishController : UmbracoAuthorizedController diff --git a/src/Umbraco.Web/WebServices/CoreStringsController.cs b/src/Umbraco.Web/WebServices/CoreStringsController.cs index b66aa1e582..4ca7973c94 100644 --- a/src/Umbraco.Web/WebServices/CoreStringsController.cs +++ b/src/Umbraco.Web/WebServices/CoreStringsController.cs @@ -6,7 +6,7 @@ using Umbraco.Web.Mvc; namespace Umbraco.Web.WebServices { /// - /// A REST controller used for accessing Core.Strings services. + /// Represents a REST controller used for accessing Core.Strings services. /// public class CoreStringsController : UmbracoAuthorizedController { diff --git a/src/Umbraco.Web/WebServices/DomainsApiController.cs b/src/Umbraco.Web/WebServices/DomainsApiController.cs index 89b2e2308e..94c425c8d7 100644 --- a/src/Umbraco.Web/WebServices/DomainsApiController.cs +++ b/src/Umbraco.Web/WebServices/DomainsApiController.cs @@ -1,19 +1,14 @@ using System; using System.Linq; using System.Collections.Generic; -using System.Linq; using System.Net; using System.Net.Http; -using System.Text; using System.Web.Http; -using System.Web.Services.Description; using Umbraco.Core; using Umbraco.Core.Services; using Umbraco.Core.Models; -using Umbraco.Web.Routing; using Umbraco.Web.WebApi; //using umbraco.cms.businesslogic.language; -using umbraco.cms.businesslogic.web; using Umbraco.Web.WebApi.Filters; using Umbraco.Web._Legacy.Actions; @@ -30,7 +25,7 @@ namespace Umbraco.Web.WebServices // can't pass multiple complex args in json post request... public PostBackModel SaveLanguageAndDomains(PostBackModel model) { - var node = ApplicationContext.Current.Services.ContentService.GetById(model.NodeId); + var node = Services.ContentService.GetById(model.NodeId); if (node == null) { diff --git a/src/Umbraco.Web/WebServices/ExamineManagementApiController.cs b/src/Umbraco.Web/WebServices/ExamineManagementApiController.cs index 78ef2b8d2e..73c3d393a3 100644 --- a/src/Umbraco.Web/WebServices/ExamineManagementApiController.cs +++ b/src/Umbraco.Web/WebServices/ExamineManagementApiController.cs @@ -10,8 +10,10 @@ using Examine.LuceneEngine.Providers; using Examine.Providers; using Lucene.Net.Search; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Plugins; +using Umbraco.Core.Services; using Umbraco.Web.Search; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; @@ -113,7 +115,7 @@ namespace Umbraco.Web.WebServices { throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); } - + if (query.IsNullOrWhiteSpace()) return LuceneSearchResults.Empty(); @@ -132,7 +134,7 @@ namespace Umbraco.Web.WebServices } throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); } - throw new HttpResponseException(msg); + throw new HttpResponseException(msg); } /// @@ -178,7 +180,7 @@ namespace Umbraco.Web.WebServices var cacheKey = "temp_indexing_op_" + indexer.Name; //put temp val in cache which is used as a rudimentary way to know when the indexing is done - ApplicationContext.ApplicationCache.RuntimeCache.InsertCacheItem(cacheKey, () => "tempValue", TimeSpan.FromMinutes(5), isSliding: false); + ApplicationCache.RuntimeCache.InsertCacheItem(cacheKey, () => "tempValue", TimeSpan.FromMinutes(5), isSliding: false); try { @@ -207,7 +209,7 @@ namespace Umbraco.Web.WebServices indexer.IndexOperationComplete -= Indexer_IndexOperationComplete; var cacheKey = "temp_indexing_op_" + indexer.Name; - ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(cacheKey); + Current.ApplicationCache.RuntimeCache.ClearCacheItem(cacheKey); } /// @@ -216,7 +218,7 @@ namespace Umbraco.Web.WebServices /// /// /// - /// This is kind of rudimentary since there's no way we can know that the index has rebuilt, we + /// This is kind of rudimentary since there's no way we can know that the index has rebuilt, we /// have a listener for the index op complete so we'll just check if that key is no longer there in the runtime cache /// public ExamineIndexerModel PostCheckRebuildIndex(string indexerName) @@ -226,10 +228,10 @@ namespace Umbraco.Web.WebServices if (msg.IsSuccessStatusCode) { var cacheKey = "temp_indexing_op_" + indexerName; - var found = ApplicationContext.ApplicationCache.RuntimeCache.GetCacheItem(cacheKey); + var found = ApplicationCache.RuntimeCache.GetCacheItem(cacheKey); //if its still there then it's not done return found != null - ? null + ? null : CreateModel(new KeyValuePair(indexerName, indexer)); } throw new HttpResponseException(msg); @@ -265,7 +267,7 @@ namespace Umbraco.Web.WebServices //ignore these properties .Where(x => new[] {"IndexerData", "Description", "WorkingFolder"}.InvariantContains(x.Name) == false) .OrderBy(x => x.Name); - + foreach (var p in props) { var val = p.GetValue(indexer, null); @@ -279,7 +281,7 @@ namespace Umbraco.Web.WebServices var luceneIndexer = indexer.Value as LuceneIndexer; if (luceneIndexer != null) - { + { indexerModel.IsLuceneIndex = true; if (luceneIndexer.IndexExists()) @@ -330,11 +332,11 @@ namespace Umbraco.Web.WebServices indexer = null; if (ExamineManager.Instance.IndexProviders.ContainsKey(indexerName)) - { + { //return Ok! return Request.CreateResponse(HttpStatusCode.OK); } - + var response = Request.CreateResponse(HttpStatusCode.BadRequest); response.Content = new StringContent(string.Format("No indexer found with name = {0}", indexerName)); response.ReasonPhrase = "Indexer Not Found"; diff --git a/src/Umbraco.Web/WebServices/FacadeStatusController.cs b/src/Umbraco.Web/WebServices/FacadeStatusController.cs index f460934a20..821a335827 100644 --- a/src/Umbraco.Web/WebServices/FacadeStatusController.cs +++ b/src/Umbraco.Web/WebServices/FacadeStatusController.cs @@ -1,5 +1,8 @@ using System; using System.Web.Http; +using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Core.Services; using Umbraco.Web.PublishedCache; using Umbraco.Web.WebApi; @@ -11,6 +14,7 @@ namespace Umbraco.Web.WebServices public FacadeStatusController(IFacadeService facadeService) { + if (facadeService == null) throw new ArgumentNullException(nameof(facadeService)); _facadeService = facadeService; } diff --git a/src/Umbraco.Web/WebServices/NuCacheStatusController.cs b/src/Umbraco.Web/WebServices/NuCacheStatusController.cs index c91a5f8823..abbabb286e 100644 --- a/src/Umbraco.Web/WebServices/NuCacheStatusController.cs +++ b/src/Umbraco.Web/WebServices/NuCacheStatusController.cs @@ -13,6 +13,7 @@ namespace Umbraco.Web.WebServices public NuCacheStatusController(IFacadeService facadeService) { + if (facadeService == null) throw new ArgumentNullException(nameof(facadeService)); _facadeService = facadeService; } diff --git a/src/Umbraco.Web/WebServices/SaveFileController.cs b/src/Umbraco.Web/WebServices/SaveFileController.cs index 010e1be2cb..280e924083 100644 --- a/src/Umbraco.Web/WebServices/SaveFileController.cs +++ b/src/Umbraco.Web/WebServices/SaveFileController.cs @@ -1,31 +1,22 @@ using System; -using System.Linq; -using System.Text; using System.Web.Mvc; -using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Services; -using Umbraco.Web.Macros; using Umbraco.Web.Mvc; -using umbraco; -using umbraco.cms.businesslogic.macro; using System.Collections.Generic; using umbraco.cms.presentation.Trees; using Umbraco.Core; -using Umbraco.Core.Configuration; using Template = umbraco.cms.businesslogic.template.Template; namespace Umbraco.Web.WebServices { /// - /// A REST controller used to save files such as templates, partial views, macro files, etc... + /// Represents REST controller used to save files such as templates, partial views, macro files, etc. /// - /// - /// This isn't fully implemented yet but we should migrate all of the logic in the umbraco.presentation.webservices.codeEditorSave - /// over to this controller. - /// + /// This isn't fully implemented yet but we should migrate all of the logic + /// in the umbraco.presentation.webservices.codeEditorSave over to this controller. [ValidateMvcAngularAntiForgeryToken] public class SaveFileController : UmbracoAuthorizedController { diff --git a/src/Umbraco.Web/WebServices/ScheduledPublishController.cs b/src/Umbraco.Web/WebServices/ScheduledPublishController.cs index e47aa4d4b9..c1ba4f4bdb 100644 --- a/src/Umbraco.Web/WebServices/ScheduledPublishController.cs +++ b/src/Umbraco.Web/WebServices/ScheduledPublishController.cs @@ -1,5 +1,6 @@ using System; using System.Web.Mvc; +using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Mvc; @@ -7,13 +8,19 @@ using Umbraco.Web.Mvc; namespace Umbraco.Web.WebServices { /// - /// A REST controller used for running the scheduled publishing, this is called from the background worker timer + /// Represents a REST controller used for running the scheduled publishing. /// [AdminTokenAuthorize] public class ScheduledPublishController : UmbracoController { private static bool _isPublishingRunning; private static readonly object Locker = new object(); + private readonly IRuntimeState _runtime; + + public ScheduledPublishController(IRuntimeState runtime) + { + _runtime = runtime; + } [HttpPost] public JsonResult Index() @@ -28,7 +35,7 @@ namespace Umbraco.Web.WebServices try { // ensure we have everything we need - if (ApplicationContext.IsReady == false) return null; + if (_runtime.Level != RuntimeLevel.Run) return null; Services.ContentService.WithResult().PerformScheduledPublish(); return Json(new { success = true }); } diff --git a/src/Umbraco.Web/WebServices/TagsController.cs b/src/Umbraco.Web/WebServices/TagsController.cs index e314e0a609..6241cfacf0 100644 --- a/src/Umbraco.Web/WebServices/TagsController.cs +++ b/src/Umbraco.Web/WebServices/TagsController.cs @@ -1,10 +1,4 @@ using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using AutoMapper; -using Examine; -using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Web.Models; using Umbraco.Web.WebApi; diff --git a/src/Umbraco.Web/WebServices/UmbracoAuthorizedHttpHandler.cs b/src/Umbraco.Web/WebServices/UmbracoAuthorizedHttpHandler.cs index 92044a21fc..54b3f1f6df 100644 --- a/src/Umbraco.Web/WebServices/UmbracoAuthorizedHttpHandler.cs +++ b/src/Umbraco.Web/WebServices/UmbracoAuthorizedHttpHandler.cs @@ -1,20 +1,20 @@ using System; using System.Security; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Web.Security; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Services; namespace Umbraco.Web.WebServices { public abstract class UmbracoAuthorizedHttpHandler : UmbracoHttpHandler { protected UmbracoAuthorizedHttpHandler() - : base() - { - } + { } - protected UmbracoAuthorizedHttpHandler(UmbracoContext umbracoContext) - : base(umbracoContext) + protected UmbracoAuthorizedHttpHandler(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) + : base(umbracoContext, services, appCache) { } diff --git a/src/Umbraco.Web/WebServices/UmbracoAuthorizedWebService.cs b/src/Umbraco.Web/WebServices/UmbracoAuthorizedWebService.cs index a71b91be62..93f26b9b6a 100644 --- a/src/Umbraco.Web/WebServices/UmbracoAuthorizedWebService.cs +++ b/src/Umbraco.Web/WebServices/UmbracoAuthorizedWebService.cs @@ -2,7 +2,9 @@ using System.Security; using Umbraco.Web.Security; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Services; namespace Umbraco.Web.WebServices { @@ -12,14 +14,11 @@ namespace Umbraco.Web.WebServices public abstract class UmbracoAuthorizedWebService : UmbracoWebService { protected UmbracoAuthorizedWebService() - : base() - { - } + { } - protected UmbracoAuthorizedWebService(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } + protected UmbracoAuthorizedWebService(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) + : base(umbracoContext, services, appCache) + { } private bool _hasValidated = false; diff --git a/src/Umbraco.Web/WebServices/UmbracoHttpHandler.cs b/src/Umbraco.Web/WebServices/UmbracoHttpHandler.cs index d50f28b350..92bfc8fa74 100644 --- a/src/Umbraco.Web/WebServices/UmbracoHttpHandler.cs +++ b/src/Umbraco.Web/WebServices/UmbracoHttpHandler.cs @@ -3,6 +3,7 @@ using System.Web; using System.Web.Mvc; using System.Web.Routing; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; @@ -11,91 +12,68 @@ namespace Umbraco.Web.WebServices { public abstract class UmbracoHttpHandler : IHttpHandler { - public abstract void ProcessRequest(HttpContext context); - public abstract bool IsReusable { get; } - - protected UmbracoHttpHandler() - : this(UmbracoContext.Current) - { - - } - - protected UmbracoHttpHandler(UmbracoContext umbracoContext) - { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); - UmbracoContext = umbracoContext; - Umbraco = new UmbracoHelper(umbracoContext); - } - - /// - /// Returns the current ApplicationContext - /// - public ApplicationContext ApplicationContext - { - get { return UmbracoContext.Application; } - } - - /// - /// Returns an ILogger - /// - public ILogger Logger - { - get { return ProfilingLogger.Logger; } - } - - /// - /// Returns a ProfilingLogger - /// - public ProfilingLogger ProfilingLogger - { - get { return UmbracoContext.Application.ProfilingLogger; } - } - - /// - /// Returns the current UmbracoContext - /// - public UmbracoContext UmbracoContext { get; private set; } - - /// - /// Returns an UmbracoHelper object - /// - public UmbracoHelper Umbraco { get; private set; } - private UrlHelper _url; - /// - /// Returns a UrlHelper - /// - /// - /// This URL helper is created without any route data and an empty request context - /// - public UrlHelper Url + protected UmbracoHttpHandler() + : this(Current.UmbracoContext, Current.Services, Current.ApplicationCache) + { } + + protected UmbracoHttpHandler(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) { - get { return _url ?? (_url = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()))); } + if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); + UmbracoContext = umbracoContext; + Umbraco = new UmbracoHelper(umbracoContext, services, appCache); + + // fixme inject somehow + Logger = Current.Logger; + ProfilingLogger = Current.ProfilingLogger; + DatabaseContext = Current.DatabaseContext; + Services = Current.Services; } - /// - /// Returns a ServiceContext - /// - public ServiceContext Services - { - get { return ApplicationContext.Services; } - } + public abstract void ProcessRequest(HttpContext context); + + public abstract bool IsReusable { get; } /// - /// Returns a DatabaseContext + /// Gets the logger. /// - public DatabaseContext DatabaseContext - { - get { return ApplicationContext.DatabaseContext; } - } + public ILogger Logger { get; } /// - /// Returns a WebSecurity instance + /// Gets the ProfilingLogger. /// - public WebSecurity Security - { - get { return UmbracoContext.Security; } - } + public ProfilingLogger ProfilingLogger { get; } + + /// + /// Gets the Umbraco context. + /// + public UmbracoContext UmbracoContext { get; } + + /// + /// Gets the Umbraco helper. + /// + public UmbracoHelper Umbraco { get; } + + /// + /// Gets the services context. + /// + public ServiceContext Services { get; } + + /// + /// Gets the database context. + /// + public DatabaseContext DatabaseContext { get; } + + /// + /// Gets the web security helper. + /// + public WebSecurity Security => UmbracoContext.Security; + + /// + /// Gets the Url helper. + /// + /// This URL helper is created without any route data and an empty request context. + public UrlHelper Url => _url ?? (_url = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()))); } } \ No newline at end of file diff --git a/src/Umbraco.Web/WebServices/UmbracoWebService.cs b/src/Umbraco.Web/WebServices/UmbracoWebService.cs index e92e85de1e..fe9b43ebb8 100644 --- a/src/Umbraco.Web/WebServices/UmbracoWebService.cs +++ b/src/Umbraco.Web/WebServices/UmbracoWebService.cs @@ -4,6 +4,7 @@ using System.Web.Mvc; using System.Web.Routing; using System.Web.Services; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; @@ -15,88 +16,64 @@ namespace Umbraco.Web.WebServices /// public abstract class UmbracoWebService : WebService { - protected UmbracoWebService() - : this(UmbracoContext.Current) - { - - } - - protected UmbracoWebService(UmbracoContext umbracoContext) - { - if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); - UmbracoContext = umbracoContext; - Umbraco = new UmbracoHelper(umbracoContext); - } - - /// - /// Returns the current ApplicationContext - /// - public ApplicationContext ApplicationContext - { - get { return UmbracoContext.Application; } - } - - /// - /// Returns an ILogger - /// - public ILogger Logger - { - get { return ProfilingLogger.Logger; } - } - - /// - /// Returns a ProfilingLogger - /// - public ProfilingLogger ProfilingLogger - { - get { return UmbracoContext.Application.ProfilingLogger; } - } - - /// - /// Returns the current UmbracoContext - /// - public UmbracoContext UmbracoContext { get; private set; } - - /// - /// Returns an UmbracoHelper object - /// - public UmbracoHelper Umbraco { get; private set; } - private UrlHelper _url; - /// - /// Returns a UrlHelper - /// - /// - /// This URL helper is created without any route data and an empty request context - /// - public UrlHelper Url + protected UmbracoWebService() + : this(Current.UmbracoContext, Current.Services, Current.ApplicationCache) + { } + + protected UmbracoWebService(UmbracoContext umbracoContext, ServiceContext services, CacheHelper appCache) { - get { return _url ?? (_url = new UrlHelper(new RequestContext(new HttpContextWrapper(Context), new RouteData()))); } + if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); + UmbracoContext = umbracoContext; + Umbraco = new UmbracoHelper(umbracoContext, services, appCache); + + // fixme inject somehow + Logger = Current.Logger; + ProfilingLogger = Current.ProfilingLogger; + DatabaseContext = Current.DatabaseContext; + Services = Current.Services; } /// - /// Returns a ServiceContext + /// Gets the logger. /// - public ServiceContext Services - { - get { return ApplicationContext.Services; } - } + public ILogger Logger { get; } /// - /// Returns a DatabaseContext + /// Gets the ProfilingLogger. /// - public DatabaseContext DatabaseContext - { - get { return ApplicationContext.DatabaseContext; } - } + public ProfilingLogger ProfilingLogger { get; } /// - /// Returns a WebSecurity instance + /// Gets the Umbraco context. /// - public WebSecurity Security - { - get { return UmbracoContext.Security; } - } + public UmbracoContext UmbracoContext { get; } + + /// + /// Gets the Umbraco helper. + /// + public UmbracoHelper Umbraco { get; } + + /// + /// Gets the services context. + /// + public ServiceContext Services { get; } + + /// + /// Gets the database context. + /// + public DatabaseContext DatabaseContext { get; } + + /// + /// Gets the web security helper. + /// + public WebSecurity Security => UmbracoContext.Security; + + /// + /// Gets the Url helper. + /// + /// This URL helper is created without any route data and an empty request context. + public UrlHelper Url => _url ?? (_url = new UrlHelper(new RequestContext(new HttpContextWrapper(Context), new RouteData()))); } } \ No newline at end of file diff --git a/src/Umbraco.Web/WebServices/XmlDataIntegrityController.cs b/src/Umbraco.Web/WebServices/XmlDataIntegrityController.cs index 1f68dc7391..ebe0dfff47 100644 --- a/src/Umbraco.Web/WebServices/XmlDataIntegrityController.cs +++ b/src/Umbraco.Web/WebServices/XmlDataIntegrityController.cs @@ -1,9 +1,5 @@ using System; using System.Web.Http; -using NPoco; -using Umbraco.Core; -using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence; using Umbraco.Web.PublishedCache; using Umbraco.Web.PublishedCache.XmlPublishedCache; using Umbraco.Web.WebApi; @@ -18,9 +14,9 @@ namespace Umbraco.Web.WebServices public XmlDataIntegrityController(IFacadeService facadeService) { + if (facadeService == null) throw new ArgumentNullException(nameof(facadeService)); _facadeService = facadeService as FacadeService; - if (_facadeService == null) - throw new NotSupportedException("Unsupported IFacadeService, only the Xml one is supported."); + if (_facadeService == null) throw new NotSupportedException("Unsupported IFacadeService, only the Xml one is supported."); } [HttpPost] diff --git a/src/Umbraco.Web/_Legacy/Actions/Action.cs b/src/Umbraco.Web/_Legacy/Actions/Action.cs index 32a808664b..9da231e1ad 100644 --- a/src/Umbraco.Web/_Legacy/Actions/Action.cs +++ b/src/Umbraco.Web/_Legacy/Actions/Action.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web._Legacy.Actions lock (Lock) { // this will reset the collection - Current.ActionCollectionBuilder.SetProducer(() => TypeFinder.FindClassesOfType(PluginManager.Current.AssembliesToScan)); + Current.ActionCollectionBuilder.SetProducer(() => TypeFinder.FindClassesOfType(Current.PluginManager.AssembliesToScan)); } } @@ -103,7 +103,7 @@ namespace Umbraco.Web._Legacy.Actions icon = "images/" + icon; _actionJsList += string.Format(",\n\tmenuItem(\"{0}\", \"{1}\", \"{2}\", \"{3}\")", - action.Letter, icon, ApplicationContext.Current.Services.TextService.Localize("actions/"+ action.Alias, new[] { language }), action.JsFunctionName); + action.Letter, icon, Current.Services.TextService.Localize("actions/"+ action.Alias, new[] { language }), action.JsFunctionName); } catch (Exception ee) { diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs index 845086fa3a..a360ee0f4f 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/addApplication.cs @@ -29,18 +29,18 @@ namespace Umbraco.Web._Legacy.PackageActions string alias = xmlData.Attributes["appAlias"].Value; string icon = xmlData.Attributes["appIcon"].Value; - ApplicationContext.Current.Services.SectionService.MakeNew(name, alias, icon); - + Current.Services.SectionService.MakeNew(name, alias, icon); + return true; } public bool Undo(string packageName, XmlNode xmlData) { string alias = xmlData.Attributes["appAlias"].Value; - var section = ApplicationContext.Current.Services.SectionService.GetByAlias(alias); + var section = Current.Services.SectionService.GetByAlias(alias); if (section != null) { - ApplicationContext.Current.Services.SectionService.DeleteSection(section); + Current.Services.SectionService.DeleteSection(section); } return true; } diff --git a/src/Umbraco.Web/_Legacy/PackageActions/addApplicationTree.cs b/src/Umbraco.Web/_Legacy/PackageActions/addApplicationTree.cs index 06fa11f011..8df4fed628 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/addApplicationTree.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/addApplicationTree.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web._Legacy.PackageActions /// The XML data. /// /// - /// /// @@ -37,8 +37,8 @@ namespace Umbraco.Web._Legacy.PackageActions string iconOpened = xmlData.Attributes["iconOpened"].Value; string iconClosed = xmlData.Attributes["iconClosed"].Value; string type = xmlData.Attributes["treeHandlerType"].Value; - - ApplicationContext.Current.Services.ApplicationTreeService.MakeNew(initialize, sortOrder, applicationAlias, treeAlias, treeTitle, iconClosed, iconOpened, type); + + Current.Services.ApplicationTreeService.MakeNew(initialize, sortOrder, applicationAlias, treeAlias, treeTitle, iconClosed, iconOpened, type); return true; } @@ -52,10 +52,10 @@ namespace Umbraco.Web._Legacy.PackageActions public bool Undo(string packageName, XmlNode xmlData) { string treeAlias = xmlData.Attributes["treeAlias"].Value; - var found = ApplicationContext.Current.Services.ApplicationTreeService.GetByAlias(treeAlias); + var found = Current.Services.ApplicationTreeService.GetByAlias(treeAlias); if (found != null) { - ApplicationContext.Current.Services.ApplicationTreeService.DeleteTree(found); + Current.Services.ApplicationTreeService.DeleteTree(found); } return true; } diff --git a/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs b/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs index e95cfc219e..596a532974 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs @@ -36,7 +36,7 @@ namespace Umbraco.Web._Legacy.PackageActions if (rootDoc.Text.Trim() == documentName.Trim() && rootDoc != null && rootDoc.ContentType != null) { - rootDoc.PublishWithChildrenWithResult(ApplicationContext.Current.Services.UserService.GetUserById(0)); + rootDoc.PublishWithChildrenWithResult(Current.Services.UserService.GetUserById(0)); break; diff --git a/src/Umbraco.Web/_Legacy/UI/LegacyDialogTask.cs b/src/Umbraco.Web/_Legacy/UI/LegacyDialogTask.cs index d8d95963bd..df0258c172 100644 --- a/src/Umbraco.Web/_Legacy/UI/LegacyDialogTask.cs +++ b/src/Umbraco.Web/_Legacy/UI/LegacyDialogTask.cs @@ -12,12 +12,12 @@ namespace Umbraco.Web._Legacy.UI /// An abstract class that is used to implement all secure ITasks /// /// - /// In the near future we will overhaul how create dialogs work and how deletions work as well. In the meantime - /// if you ever need to create an ITask you should just inherit from this class and do not manually implement + /// In the near future we will overhaul how create dialogs work and how deletions work as well. In the meantime + /// if you ever need to create an ITask you should just inherit from this class and do not manually implement /// ITask or ITaskReturnUrl. If you do, you MUST also implement IAppTask which associates an ITask to an app - /// so we can validate the current user's security with the implementation. If you do not do this then your - /// implementation will not be secure. It means that if someone is logged in and doesn't have access to a - /// specific app, they'd still be able to execute code to create/delete for any ITask regardless of what app + /// so we can validate the current user's security with the implementation. If you do not do this then your + /// implementation will not be secure. It means that if someone is logged in and doesn't have access to a + /// specific app, they'd still be able to execute code to create/delete for any ITask regardless of what app /// they have access to. /// [Obsolete("ITask is used for legacy webforms back office editors, change to using the v7 angular approach")] @@ -26,7 +26,7 @@ namespace Umbraco.Web._Legacy.UI public virtual int ParentID { get; set; } public int TypeID { get; set; } public string Alias { get; set; } - + /// /// Base class first performs authentication for the current app before proceeding /// @@ -35,7 +35,7 @@ namespace Umbraco.Web._Legacy.UI { if (ValidateUserForApplication()) { - return PerformSave(); + return PerformSave(); } throw new AuthenticationException("The current user does not have access to the required application that this task belongs to"); } @@ -70,7 +70,7 @@ namespace Umbraco.Web._Legacy.UI /// int ITask.UserId { - set { User = ApplicationContext.Current.Services.UserService.GetUserById(value); } + set { User = Current.Services.UserService.GetUserById(value); } } /// diff --git a/src/Umbraco.Web/umbraco.presentation/EnsureSystemPathsApplicationStartupHandler.cs b/src/Umbraco.Web/umbraco.presentation/EnsureSystemPathsApplicationStartupHandler.cs index 73e9e7835d..4c06619147 100644 --- a/src/Umbraco.Web/umbraco.presentation/EnsureSystemPathsApplicationStartupHandler.cs +++ b/src/Umbraco.Web/umbraco.presentation/EnsureSystemPathsApplicationStartupHandler.cs @@ -10,9 +10,9 @@ namespace umbraco.presentation { public class EnsureSystemPathsApplicationStartupHandler : ApplicationEventHandler { - protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication) { - base.ApplicationInitialized(umbracoApplication, applicationContext); + base.ApplicationInitialized(umbracoApplication); IOHelper.EnsurePathExists("~/App_Data"); IOHelper.EnsurePathExists(SystemDirectories.Media); diff --git a/src/Umbraco.Web/umbraco.presentation/library.cs b/src/Umbraco.Web/umbraco.presentation/library.cs index 9a30cd7c29..3cf140f56f 100644 --- a/src/Umbraco.Web/umbraco.presentation/library.cs +++ b/src/Umbraco.Web/umbraco.presentation/library.cs @@ -46,7 +46,7 @@ namespace umbraco /// private static UmbracoHelper GetUmbracoHelper() { - return new UmbracoHelper(Umbraco.Web.UmbracoContext.Current); + return new UmbracoHelper(Current.UmbracoContext, Current.Services, Current.ApplicationCache); } #region Declarations @@ -316,7 +316,7 @@ namespace umbraco { if (UmbracoConfig.For.UmbracoSettings().Content.UmbracoLibraryCacheDuration > 0) { - var xml = ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem( + var xml = Current.ApplicationCache.RuntimeCache.GetCacheItem( $"{CacheKeys.MediaCacheKey}_{MediaId}_{deep}", timeout: TimeSpan.FromSeconds(UmbracoConfig.For.UmbracoSettings().Content.UmbracoLibraryCacheDuration), getCacheItem: () => GetMediaDo(MediaId, deep).Item1); @@ -349,13 +349,13 @@ namespace umbraco private static Tuple GetMediaDo(int mediaId, bool deep) { - var media = ApplicationContext.Current.Services.MediaService.GetById(mediaId); + var media = Current.Services.MediaService.GetById(mediaId); if (media == null) return null; var serializer = new EntityXmlSerializer(); var serialized = serializer.Serialize( - ApplicationContext.Current.Services.MediaService, - ApplicationContext.Current.Services.DataTypeService, - ApplicationContext.Current.Services.UserService, + Current.Services.MediaService, + Current.Services.DataTypeService, + Current.Services.UserService, Current.UrlSegmentProviders, media, deep); @@ -375,7 +375,7 @@ namespace umbraco { if (UmbracoConfig.For.UmbracoSettings().Content.UmbracoLibraryCacheDuration > 0) { - var xml = ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem( + var xml = Current.ApplicationCache.RuntimeCache.GetCacheItem( string.Format( "{0}_{1}", CacheKeys.MemberLibraryCacheKey, MemberId), timeout: TimeSpan.FromSeconds(UmbracoConfig.For.UmbracoSettings().Content.UmbracoLibraryCacheDuration), @@ -405,11 +405,11 @@ namespace umbraco private static XElement GetMemberDo(int MemberId) { - var member = ApplicationContext.Current.Services.MemberService.GetById(MemberId); + var member = Current.Services.MemberService.GetById(MemberId); if (member == null) return null; var serializer = new EntityXmlSerializer(); var serialized = serializer.Serialize( - ApplicationContext.Current.Services.DataTypeService, member); + Current.Services.DataTypeService, member); return serialized; } @@ -453,7 +453,7 @@ namespace umbraco private static string[] GetAccessingMembershipRoles(int documentId, string path) { - var entry = ApplicationContext.Current.Services.PublicAccessService.GetEntryForContent(path.EnsureEndsWith("," + documentId)); + var entry = Current.Services.PublicAccessService.GetEntryForContent(path.EnsureEndsWith("," + documentId)); if (entry == null) return new string[] { }; var memberGroupRoleRules = entry.Rules.Where(x => x.RuleType == Constants.Conventions.PublicAccess.MemberRoleRuleType); @@ -1106,7 +1106,7 @@ namespace umbraco XmlDocument xd = new XmlDocument(); xd.LoadXml(""); - foreach (var dr in ApplicationContext.Current.DatabaseContext.Database.Query( + foreach (var dr in Current.DatabaseContext.Database.Query( "Select id, [value] from cmsDataTypeprevalues where DataTypeNodeId = @dataTypeId order by sortorder", new { dataTypeId = DataTypeId })) { @@ -1128,7 +1128,7 @@ namespace umbraco { try { - return ApplicationContext.Current.DatabaseContext.Database.ExecuteScalar( + return Current.DatabaseContext.Database.ExecuteScalar( "select [value] from cmsDataTypePreValues where id = @id", new {id = Id}); } @@ -1158,13 +1158,13 @@ namespace umbraco //int languageId = GetCurrentLanguageId(); int languageId = Language.GetByCultureCode(System.Threading.Thread.CurrentThread.CurrentUICulture.Name).id; - var di = ApplicationContext.Current.Services.LocalizationService.GetDictionaryItemByKey(Key); + var di = Current.Services.LocalizationService.GetDictionaryItemByKey(Key); if (di == null) { return xd.CreateNavigator().Select("/"); } - var children = ApplicationContext.Current.Services.LocalizationService.GetDictionaryItemChildren(di.Key); + var children = Current.Services.LocalizationService.GetDictionaryItemChildren(di.Key); foreach (var item in children) { XmlNode xe; @@ -1630,7 +1630,7 @@ namespace umbraco public static IRelation[] GetRelatedNodes(int nodeId) { - return ApplicationContext.Current.Services.RelationService.GetByParentOrChildId(nodeId).ToArray(); + return Current.Services.RelationService.GetByParentOrChildId(nodeId).ToArray(); } /// @@ -1650,7 +1650,7 @@ namespace umbraco XmlDocument xd = new XmlDocument(); xd.LoadXml(""); - var rels = ApplicationContext.Current.Services.RelationService.GetByParentOrChildId(NodeId); + var rels = Current.Services.RelationService.GetByParentOrChildId(NodeId); foreach (var r in rels) { XmlElement n = xd.CreateElement("relation"); @@ -1664,26 +1664,26 @@ namespace umbraco // Append the node that isn't the one we're getting the related nodes from if (NodeId == r.ChildId) { - var parent = ApplicationContext.Current.Services.ContentService.GetById(r.ParentId); + var parent = Current.Services.ContentService.GetById(r.ParentId); if (parent != null) { var x = xmlSerializer.Serialize( - ApplicationContext.Current.Services.ContentService, - ApplicationContext.Current.Services.DataTypeService, - ApplicationContext.Current.Services.UserService, + Current.Services.ContentService, + Current.Services.DataTypeService, + Current.Services.UserService, Current.UrlSegmentProviders, parent).GetXmlNode(xd); n.AppendChild(x); } } else { - var child = ApplicationContext.Current.Services.ContentService.GetById(r.ChildId); + var child = Current.Services.ContentService.GetById(r.ChildId); if (child != null) { var x = xmlSerializer.Serialize( - ApplicationContext.Current.Services.ContentService, - ApplicationContext.Current.Services.DataTypeService, - ApplicationContext.Current.Services.UserService, + Current.Services.ContentService, + Current.Services.DataTypeService, + Current.Services.UserService, Current.UrlSegmentProviders, child).GetXmlNode(xd); n.AppendChild(x); } diff --git a/src/Umbraco.Web/umbraco.presentation/template.cs b/src/Umbraco.Web/umbraco.presentation/template.cs index 9775094340..855762aae3 100644 --- a/src/Umbraco.Web/umbraco.presentation/template.cs +++ b/src/Umbraco.Web/umbraco.presentation/template.cs @@ -287,7 +287,7 @@ namespace umbraco try { - var renderer = new MacroRenderer(ApplicationContext.Current.ProfilingLogger); + var renderer = new MacroRenderer(Current.ProfilingLogger); var c = renderer.Render(tempMacro, umbPage.Elements, umbPage.PageID, attributes).GetAsControl(); if (c != null) pageContent.Controls.Add(c); @@ -445,7 +445,7 @@ namespace umbraco { HttpContext.Current.Trace.Write("umbracoTemplate", "Starting macro (" + macroId + ")"); // it's all obsolete anyways... - var macro = ApplicationContext.Current.Services.MacroService.GetByAlias(macroId); + var macro = Current.Services.MacroService.GetByAlias(macroId); return macro == null ? null : new MacroModel(macro); } @@ -472,10 +472,10 @@ namespace umbraco { var tId = templateID; - var t = ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem