Merge pull request #7722 from umbraco/netcore/feature/move-more-install-stuff

NetCore: Moved install steps + dashboards
This commit is contained in:
Bjarke Berg
2020-03-02 08:28:01 +01:00
committed by GitHub
43 changed files with 223 additions and 170 deletions
@@ -1,4 +1,5 @@
using System.Configuration;
using Umbraco.Configuration;
using Umbraco.Core.Configuration.HealthChecks;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
@@ -10,6 +11,7 @@ namespace Umbraco.Core.Configuration
public IHostingSettings HostingSettings { get; } = new HostingSettings();
public ICoreDebug CoreDebug { get; } = new CoreDebug();
public IMachineKeyConfig MachineKeyConfig { get; } = new MachineKeyConfig();
public IUmbracoSettingsSection UmbracoSettings { get; }
@@ -27,6 +29,7 @@ namespace Umbraco.Core.Configuration
configs.AddPasswordConfigurations();
configs.Add(() => CoreDebug);
configs.Add(() => MachineKeyConfig);
configs.Add<IConnectionStrings>(() => new ConnectionStrings(ioHelper));
configs.AddCoreConfigs(ioHelper);
return configs;
@@ -0,0 +1,20 @@
using System.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
{
public class MachineKeyConfig : IMachineKeyConfig
{
//TODO all the machineKey stuff should be replaced: https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/compatibility/replacing-machinekey?view=aspnetcore-3.1
public bool HasMachineKey
{
get
{
var machineKeySection =
ConfigurationManager.GetSection("system.web/machineKey") as ConfigurationSection;
return !(machineKeySection?.ElementInformation?.Source is null);
}
}
}
}
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Configuration
{
public interface IMachineKeyConfig
{
bool HasMachineKey { get;}
}
}
@@ -22,11 +22,6 @@ namespace Umbraco.Core.Hosting
string MapPath(string path);
string ToAbsolute(string virtualPath, string root);
/// <summary>
/// Terminates the current application. The application restarts the next time a request is received for it.
/// </summary>
void LazyRestartApplication();
void RegisterObject(IRegisteredObject registeredObject);
void UnregisterObject(IRegisteredObject registeredObject);
}
+5 -4
View File
@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Net;
namespace Umbraco.Core.Manifest
{
@@ -13,13 +14,13 @@ namespace Umbraco.Core.Manifest
private static volatile bool _isRestarting;
private readonly ILogger _logger;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
private readonly List<FileSystemWatcher> _fws = new List<FileSystemWatcher>();
public ManifestWatcher(ILogger logger, IHostingEnvironment hostingEnvironment)
public ManifestWatcher(ILogger logger, IUmbracoApplicationLifetime umbracoApplicationLifetime)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_hostingEnvironment = hostingEnvironment;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
}
public void Start(params string[] packageFolders)
@@ -57,7 +58,7 @@ namespace Umbraco.Core.Manifest
_isRestarting = true;
_logger.Info<ManifestWatcher>("Manifest has changed, app pool is restarting ({Path})", e.FullPath);
_hostingEnvironment.LazyRestartApplication();
_umbracoApplicationLifetime.Restart();
Dispose(); // uh? if the app restarts then this should be disposed anyways?
}
}
@@ -0,0 +1,14 @@
namespace Umbraco.Net
{
public interface IUmbracoApplicationLifetime
{
/// <summary>
/// A value indicating whether the application is restarting after the current request.
/// </summary>
bool IsRestarting { get; }
/// <summary>
/// Terminates the current application. The application restarts the next time a request is received for it.
/// </summary>
void Restart();
}
}
@@ -0,0 +1,7 @@
namespace Umbraco.Net
{
public interface IUserAgentProvider
{
string GetUserAgent();
}
}
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Models.Packaging
/// <remarks>
/// This is used only for conversions and will not 'get' a PackageDefinition from the repository with a valid ID
/// </remarks>
internal static PackageDefinition FromCompiledPackage(CompiledPackage compiled)
public static PackageDefinition FromCompiledPackage(CompiledPackage compiled)
{
return new PackageDefinition
{
@@ -0,0 +1,19 @@
using System;
using Umbraco.Web;
namespace Umbraco.Core
{
public static class UmbracoContextAccessorExtensions
{
public static IUmbracoContext GetRequiredUmbracoContext(this IUmbracoContextAccessor umbracoContextAccessor)
{
if (umbracoContextAccessor == null) throw new ArgumentNullException(nameof(umbracoContextAccessor));
var umbracoContext = umbracoContextAccessor.UmbracoContext;
if(umbracoContext is null) throw new InvalidOperationException("UmbracoContext is null");
return umbracoContext;
}
}
}
@@ -4,6 +4,7 @@ using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Net;
namespace Umbraco.Core.Compose
{
@@ -12,18 +13,18 @@ namespace Umbraco.Core.Compose
private readonly IRuntimeState _runtimeState;
private readonly ILogger _logger;
private readonly IIOHelper _ioHelper;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
// 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 ManifestWatcherComponent(IRuntimeState runtimeState, ILogger logger, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment)
public ManifestWatcherComponent(IRuntimeState runtimeState, ILogger logger, IIOHelper ioHelper, IUmbracoApplicationLifetime umbracoApplicationLifetime)
{
_runtimeState = runtimeState;
_logger = logger;
_ioHelper = ioHelper;
_hostingEnvironment = hostingEnvironment;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
}
public void Initialize()
@@ -36,7 +37,7 @@ namespace Umbraco.Core.Compose
var appPlugins = _ioHelper.MapPath("~/App_Plugins/");
if (Directory.Exists(appPlugins) == false) return;
_mw = new ManifestWatcher(_logger, _hostingEnvironment);
_mw = new ManifestWatcher(_logger, _umbracoApplicationLifetime);
_mw.Start(Directory.GetDirectories(appPlugins));
}
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Cookie;
@@ -11,9 +10,9 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Net;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install
@@ -22,25 +21,28 @@ namespace Umbraco.Web.Install
{
private static HttpClient _httpClient;
private readonly DatabaseBuilder _databaseBuilder;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ILogger _logger;
private readonly IGlobalSettings _globalSettings;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IConnectionStrings _connectionStrings;
private readonly IInstallationService _installationService;
private readonly ICookieManager _cookieManager;
private readonly IUserAgentProvider _userAgentProvider;
private readonly IUmbracoDatabaseFactory _umbracoDatabaseFactory;
private readonly IJsonSerializer _jsonSerializer;
private InstallationType? _installationType;
public InstallHelper(IHttpContextAccessor httpContextAccessor,
DatabaseBuilder databaseBuilder,
public InstallHelper(DatabaseBuilder databaseBuilder,
ILogger logger,
IGlobalSettings globalSettings,
IUmbracoVersion umbracoVersion,
IConnectionStrings connectionStrings,
IInstallationService installationService,
ICookieManager cookieManager)
ICookieManager cookieManager,
IUserAgentProvider userAgentProvider,
IUmbracoDatabaseFactory umbracoDatabaseFactory,
IJsonSerializer jsonSerializer)
{
_httpContextAccessor = httpContextAccessor;
_logger = logger;
_globalSettings = globalSettings;
_umbracoVersion = umbracoVersion;
@@ -48,6 +50,9 @@ namespace Umbraco.Web.Install
_connectionStrings = connectionStrings ?? throw new ArgumentNullException(nameof(connectionStrings));
_installationService = installationService;
_cookieManager = cookieManager;
_userAgentProvider = userAgentProvider;
_umbracoDatabaseFactory = umbracoDatabaseFactory;
_jsonSerializer = jsonSerializer;
}
public InstallationType GetInstallationType()
@@ -57,11 +62,9 @@ namespace Umbraco.Web.Install
public async Task InstallStatus(bool isCompleted, string errorMsg)
{
var httpContext = _httpContextAccessor.GetRequiredHttpContext();
try
{
var userAgent = httpContext.Request.UserAgent;
var userAgent = _userAgentProvider.GetUserAgent();
// Check for current install Id
var installId = Guid.NewGuid();
@@ -88,7 +91,7 @@ namespace Umbraco.Web.Install
{
// we don't have DatabaseProvider anymore... doing it differently
//dbProvider = ApplicationContext.Current.DatabaseContext.DatabaseProvider.ToString();
dbProvider = GetDbProviderString(Current.SqlContext);
dbProvider = _umbracoDatabaseFactory.SqlContext.SqlSyntax.DbProvider;
}
var installLog = new InstallLog(installId: installId, isUpgrade: IsBrandNewInstall == false,
@@ -105,23 +108,6 @@ namespace Umbraco.Web.Install
}
}
internal static string GetDbProviderString(ISqlContext sqlContext)
{
var dbProvider = string.Empty;
// we don't have DatabaseProvider anymore...
//dbProvider = ApplicationContext.Current.DatabaseContext.DatabaseProvider.ToString();
//
// doing it differently
var syntax = sqlContext.SqlSyntax;
if (syntax is SqlCeSyntaxProvider)
dbProvider = "SqlServerCE";
else if (syntax is SqlServerSyntaxProvider)
dbProvider = (syntax as SqlServerSyntaxProvider).ServerVersion.IsAzure ? "SqlAzure" : "SqlServer";
return dbProvider;
}
/// <summary>
/// Checks if this is a brand new install meaning that there is no configured version and there is no configured database connection
/// </summary>
@@ -162,7 +148,10 @@ namespace Umbraco.Web.Install
using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri))
{
var response = _httpClient.SendAsync(request).Result;
packages = response.Content.ReadAsAsync<IEnumerable<Package>>().Result.ToList();
var json = response.Content.ReadAsStringAsync().Result;
packages = _jsonSerializer.Deserialize<IEnumerable<Package>>(json).ToList();
}
}
catch (AggregateException ex)
@@ -1,7 +1,7 @@
using System.Linq;
using System.Threading.Tasks;
using System.Web.Configuration;
using System.Xml.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Security;
using Umbraco.Web.Install.Models;
@@ -12,13 +12,15 @@ namespace Umbraco.Web.Install.InstallSteps
"ConfigureMachineKey", "machinekey", 2,
"Updating some security settings...",
PerformsAppRestart = true)]
internal class ConfigureMachineKey : InstallSetupStep<bool?>
public class ConfigureMachineKey : InstallSetupStep<bool?>
{
private readonly IIOHelper _ioHelper;
private readonly IMachineKeyConfig _machineKeyConfig;
public ConfigureMachineKey(IIOHelper ioHelper)
public ConfigureMachineKey(IIOHelper ioHelper, IMachineKeyConfig machineKeyConfig)
{
_ioHelper = ioHelper;
_machineKeyConfig = machineKeyConfig;
}
public override string View => HasMachineKey() == false ? base.View : "";
@@ -27,10 +29,9 @@ namespace Umbraco.Web.Install.InstallSteps
/// Don't display the view or execute if a machine key already exists
/// </summary>
/// <returns></returns>
private static bool HasMachineKey()
private bool HasMachineKey()
{
var section = (MachineKeySection) WebConfigurationManager.GetSection("system.web/machineKey");
return section.ElementInformation.Source != null;
return _machineKeyConfig.HasMachineKey;
}
/// <summary>
@@ -1,44 +1,31 @@
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Services;
using Umbraco.Web.Cache;
using Umbraco.Web.Composing;
using Umbraco.Web.Install.Models;
using Umbraco.Web.Security;
namespace Umbraco.Web.Install.InstallSteps
{
[InstallSetupStep(InstallationType.NewInstall | InstallationType.Upgrade,
"UmbracoVersion", 50, "Installation is complete!, get ready to be redirected to your new CMS.",
PerformsAppRestart = true)]
internal class SetUmbracoVersionStep : InstallSetupStep<object>
public class SetUmbracoVersionStep : InstallSetupStep<object>
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly InstallHelper _installHelper;
private readonly IGlobalSettings _globalSettings;
private readonly IUserService _userService;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IIOHelper _ioHelper;
public SetUmbracoVersionStep(IHttpContextAccessor httpContextAccessor, InstallHelper installHelper, IGlobalSettings globalSettings, IUserService userService, IUmbracoVersion umbracoVersion, IIOHelper ioHelper)
public SetUmbracoVersionStep(IUmbracoContextAccessor umbracoContextAccessor, InstallHelper installHelper, IGlobalSettings globalSettings, IUmbracoVersion umbracoVersion)
{
_httpContextAccessor = httpContextAccessor;
_umbracoContextAccessor = umbracoContextAccessor;
_installHelper = installHelper;
_globalSettings = globalSettings;
_userService = userService;
_umbracoVersion = umbracoVersion;
_ioHelper = ioHelper;
}
public override Task<InstallSetupResult> ExecuteAsync(object model)
{
var security = new WebSecurity(_httpContextAccessor, _userService, _globalSettings, _ioHelper);
var security = _umbracoContextAccessor.GetRequiredUmbracoContext().Security;
if (security.IsAuthenticated() == false && _globalSettings.ConfigurationStatus.IsNullOrWhiteSpace())
{
security.PerformLogin(-1);
@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core.Services;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.Packaging;
using Umbraco.Web.Composing;
using Umbraco.Net;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install.InstallSteps
@@ -20,14 +18,16 @@ namespace Umbraco.Web.Install.InstallSteps
private readonly InstallHelper _installHelper;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
private readonly IContentService _contentService;
private readonly IPackagingService _packageService;
public StarterKitDownloadStep(IContentService contentService, IPackagingService packageService, InstallHelper installHelper, IUmbracoContextAccessor umbracoContextAccessor, IUmbracoVersion umbracoVersion)
public StarterKitDownloadStep(IContentService contentService, IPackagingService packageService, InstallHelper installHelper, IUmbracoContextAccessor umbracoContextAccessor, IUmbracoVersion umbracoVersion, IUmbracoApplicationLifetime umbracoApplicationLifetime)
{
_installHelper = installHelper;
_umbracoContextAccessor = umbracoContextAccessor;
_umbracoVersion = umbracoVersion;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
_contentService = contentService;
_packageService = packageService;
}
@@ -54,7 +54,7 @@ namespace Umbraco.Web.Install.InstallSteps
var (packageFile, packageId) = await DownloadPackageFilesAsync(starterKitId.Value);
UmbracoApplication.Restart();
_umbracoApplicationLifetime.Restart();
return new InstallSetupResult(new Dictionary<string, object>
{
@@ -2,9 +2,8 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Net;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install.InstallSteps
@@ -14,13 +13,13 @@ namespace Umbraco.Web.Install.InstallSteps
PerformsAppRestart = true)]
internal class StarterKitInstallStep : InstallSetupStep<object>
{
private readonly IHttpContextAccessor _httContextAccessor;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IPackagingService _packagingService;
public StarterKitInstallStep(IHttpContextAccessor httContextAccessor, IUmbracoContextAccessor umbracoContextAccessor, IPackagingService packagingService)
public StarterKitInstallStep(IUmbracoApplicationLifetime umbracoApplicationLifetime, IUmbracoContextAccessor umbracoContextAccessor, IPackagingService packagingService)
{
_httContextAccessor = httContextAccessor;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
_umbracoContextAccessor = umbracoContextAccessor;
_packagingService = packagingService;
}
@@ -34,7 +33,9 @@ namespace Umbraco.Web.Install.InstallSteps
InstallBusinessLogic(packageId);
UmbracoApplication.Restart(_httContextAccessor.GetRequiredHttpContext());
_umbracoApplicationLifetime.Restart();
return Task.FromResult<InstallSetupResult>(null);
}
@@ -77,12 +77,13 @@ namespace Umbraco.Core.Persistence.SqlSyntax
string ConvertIntegerToOrderableString { get; }
string ConvertDateToOrderableString { get; }
string ConvertDecimalToOrderableString { get; }
/// <summary>
/// Returns the default isolation level for the database
/// </summary>
IsolationLevel DefaultIsolationLevel { get; }
string DbProvider { get; }
IEnumerable<string> GetTablesInSchema(IDatabase db);
IEnumerable<ColumnInfo> GetColumnsInSchema(IDatabase db);
@@ -175,6 +175,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return items.Select(x => new Tuple<string, string, string, string>(x.TableName, x.ColumnName, x.Name, x.Definition));
}
public override string DbProvider => ServerVersion.IsAzure ? "SqlAzure" : "SqlServer";
public override IEnumerable<string> GetTablesInSchema(IDatabase db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
@@ -202,6 +202,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
}
public abstract IsolationLevel DefaultIsolationLevel { get; }
public abstract string DbProvider { get; }
public virtual IEnumerable<string> GetTablesInSchema(IDatabase db)
{
@@ -55,6 +55,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
}
public override System.Data.IsolationLevel DefaultIsolationLevel => System.Data.IsolationLevel.RepeatableRead;
public override string DbProvider => "SqlServerCE";
public override string FormatColumnRename(string tableName, string oldName, string newName)
{
@@ -49,11 +49,6 @@ namespace Umbraco.Web.Hosting
}
public string ToAbsolute(string virtualPath, string root) => VirtualPathUtility.ToAbsolute(virtualPath, root);
public void LazyRestartApplication()
{
HttpRuntime.UnloadAppDomain();
}
public void RegisterObject(IRegisteredObject registeredObject)
{
var wrapped = new RegisteredObjectWrapper(registeredObject);
@@ -0,0 +1,34 @@
using System.Threading;
using System.Web;
using Umbraco.Net;
namespace Umbraco.Web.AspNet
{
public class AspNetUmbracoApplicationLifetime : IUmbracoApplicationLifetime
{
private readonly IHttpContextAccessor _httpContextAccessor;
public AspNetUmbracoApplicationLifetime(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public bool IsRestarting { get; set; }
public void Restart()
{
IsRestarting = true;
var httpContext = _httpContextAccessor.HttpContext;
if (httpContext != null)
{
// 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;
}
Thread.CurrentPrincipal = null;
HttpRuntime.UnloadAppDomain();
}
}
}
@@ -0,0 +1,19 @@
using Umbraco.Net;
namespace Umbraco.Web.AspNet
{
public class AspNetUserAgentProvider : IUserAgentProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
public AspNetUserAgentProvider(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public string GetUserAgent()
{
return _httpContextAccessor.GetRequiredHttpContext().Request.UserAgent;
}
}
}
+2 -1
View File
@@ -263,7 +263,8 @@ namespace Umbraco.Web.Composing
public static IUmbracoVersion UmbracoVersion => Factory.GetInstance<IUmbracoVersion>();
public static IPublishedUrlProvider PublishedUrlProvider => Factory.GetInstance<IPublishedUrlProvider>();
public static IMenuItemCollectionFactory MenuItemCollectionFactory => Factory.GetInstance<IMenuItemCollectionFactory>();
public static MembershipHelper MembershipHelper => Factory.GetInstance<MembershipHelper>();
public static MembershipHelper MembershipHelper => Factory.GetInstance<MembershipHelper>();
public static IUmbracoApplicationLifetime UmbracoApplicationLifetime => Factory.GetInstance<IUmbracoApplicationLifetime>();
#endregion
}
@@ -18,6 +18,7 @@ using Umbraco.Core.Packaging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Net;
using Umbraco.Web.JavaScript;
using Umbraco.Web.Models;
using Umbraco.Web.Models.ContentEditing;
@@ -39,6 +40,7 @@ namespace Umbraco.Web.Editors
private readonly IUmbracoVersion _umbracoVersion;
private readonly IIOHelper _ioHelper;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
public PackageInstallController(
IGlobalSettings globalSettings,
@@ -53,11 +55,13 @@ namespace Umbraco.Web.Editors
IUmbracoVersion umbracoVersion,
UmbracoMapper umbracoMapper,
IIOHelper ioHelper,
IPublishedUrlProvider publishedUrlProvider)
IPublishedUrlProvider publishedUrlProvider,
IUmbracoApplicationLifetime umbracoApplicationLifetime)
: base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, shortStringHelper, umbracoMapper, publishedUrlProvider)
{
_umbracoVersion = umbracoVersion;
_ioHelper = ioHelper;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
}
/// <summary>
@@ -325,7 +329,7 @@ namespace Umbraco.Web.Editors
var installedFiles = Services.PackagingService.InstallCompiledPackageFiles(definition, zipFile, Security.GetUserId().ResultOr(0));
//set a restarting marker and reset the app pool
UmbracoApplication.Restart(Request.TryGetHttpContext().Result);
_umbracoApplicationLifetime.Restart();
model.IsRestarting = true;
@@ -337,12 +341,8 @@ namespace Umbraco.Web.Editors
{
if (model.IsRestarting == false) return model;
//check for the key, if it's not there we're are restarted
if (Request.TryGetHttpContext().Result.Application.AllKeys.Contains("AppPoolRestarting") == false)
{
//reset it
model.IsRestarting = false;
}
model.IsRestarting = _umbracoApplicationLifetime.IsRestarting;
return model;
}
@@ -7,6 +7,7 @@ namespace Umbraco.Web
{
public static HttpContextBase GetRequiredHttpContext(this IHttpContextAccessor httpContextAccessor)
{
if (httpContextAccessor == null) throw new ArgumentNullException(nameof(httpContextAccessor));
var httpContext = httpContextAccessor.HttpContext;
if(httpContext is null) throw new InvalidOperationException("HttpContext is null");
+1 -1
View File
@@ -331,7 +331,7 @@ namespace Umbraco.Web.Macros
/// <returns>The text output of the macro execution.</returns>
private MacroContent ExecutePartialView(MacroModel macro, IPublishedContent content)
{
var engine = new PartialViewMacroEngine();
var engine = new PartialViewMacroEngine(_umbracoContextAccessor, _httpContextAccessor, _ioHelper);
return engine.Execute(macro, content);
}
@@ -5,6 +5,7 @@ using System.Web.Routing;
using System.Web.WebPages;
using Umbraco.Web.Mvc;
using Umbraco.Core;
using Umbraco.Core.IO;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.Composing;
@@ -15,37 +16,24 @@ namespace Umbraco.Web.Macros
/// </summary>
public class PartialViewMacroEngine
{
private readonly Func<HttpContextBase> _getHttpContext;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IIOHelper _ioHelper;
private readonly Func<IUmbracoContext> _getUmbracoContext;
public PartialViewMacroEngine()
public PartialViewMacroEngine(IUmbracoContextAccessor umbracoContextAccessor, IHttpContextAccessor httpContextAccessor, IIOHelper ioHelper)
{
_getHttpContext = () =>
{
if (HttpContext.Current == null)
throw new InvalidOperationException($"The {GetType()} cannot execute with a null HttpContext.Current reference.");
return new HttpContextWrapper(HttpContext.Current);
};
_httpContextAccessor = httpContextAccessor;
_ioHelper = ioHelper;
_getUmbracoContext = () =>
{
if (Current.UmbracoContext == null)
var context = umbracoContextAccessor.UmbracoContext;
if (context == null)
throw new InvalidOperationException($"The {GetType()} cannot execute with a null UmbracoContext.Current reference.");
return Current.UmbracoContext;
return context;
};
}
/// <summary>
/// Constructor generally used for unit testing
/// </summary>
/// <param name="httpContext"></param>
/// <param name="umbracoContext"> </param>
internal PartialViewMacroEngine(HttpContextBase httpContext, IUmbracoContext umbracoContext)
{
_getHttpContext = () => httpContext;
_getUmbracoContext = () => umbracoContext;
}
public bool Validate(string code, string tempFileName, IPublishedContent currentPage, out string errorMessage)
{
var temp = GetVirtualPathFromPhysicalPath(tempFileName);
@@ -68,7 +56,7 @@ namespace Umbraco.Web.Macros
if (content == null) throw new ArgumentNullException(nameof(content));
if (macro.MacroSource.IsNullOrWhiteSpace()) throw new ArgumentException("The MacroSource property of the macro object cannot be null or empty");
var http = _getHttpContext();
var httpContext = _httpContextAccessor.GetRequiredHttpContext();
var umbCtx = _getUmbracoContext();
var routeVals = new RouteData();
routeVals.Values.Add("controller", "PartialViewMacro");
@@ -79,13 +67,14 @@ namespace Umbraco.Web.Macros
var viewContext = new ViewContext { ViewData = new ViewDataDictionary() };
//try and extract the current view context from the route values, this would be set in the UmbracoViewPage or in
// the UmbracoPageResult if POSTing to an MVC controller but rendering in Webforms
if (http.Request.RequestContext.RouteData.DataTokens.ContainsKey(Mvc.Constants.DataTokenCurrentViewContext))
if (httpContext.Request.RequestContext.RouteData.DataTokens.ContainsKey(Mvc.Constants.DataTokenCurrentViewContext))
{
viewContext = (ViewContext)http.Request.RequestContext.RouteData.DataTokens[Mvc.Constants.DataTokenCurrentViewContext];
viewContext = (ViewContext)httpContext.Request.RequestContext.RouteData.DataTokens[Mvc.Constants.DataTokenCurrentViewContext];
}
routeVals.DataTokens.Add("ParentActionViewContext", viewContext);
var request = new RequestContext(http, routeVals);
var request = new RequestContext(httpContext, routeVals);
string output;
using (var controller = new PartialViewMacroController(macro, content))
{
@@ -103,7 +92,7 @@ namespace Umbraco.Web.Macros
private string GetVirtualPathFromPhysicalPath(string physicalPath)
{
var rootpath = _getHttpContext().Server.MapPath("~/");
var rootpath = _ioHelper.MapPath("~/");
physicalPath = physicalPath.Replace(rootpath, "");
physicalPath = physicalPath.Replace("\\", "/");
return "~/" + physicalPath;
+7 -1
View File
@@ -151,9 +151,15 @@ namespace Umbraco.Web.Mvc
var context = HttpContext.Current;
if (context == null)
{
AppDomain.Unload(AppDomain.CurrentDomain);
}
else
UmbracoApplication.Restart(new HttpContextWrapper(context));
{
Current.UmbracoApplicationLifetime.Restart();
}
}
throw new ModelBindingException(msg.ToString());
@@ -49,6 +49,7 @@ using Current = Umbraco.Web.Composing.Current;
using Umbraco.Web.PropertyEditors;
using Umbraco.Examine;
using Umbraco.Core.Models;
using Umbraco.Web.AspNet;
using Umbraco.Web.Models;
namespace Umbraco.Web.Runtime
@@ -64,9 +65,11 @@ namespace Umbraco.Web.Runtime
composition.Register<UmbracoInjectedModule>();
composition.Register<IIpResolver, AspNetIpResolver>();
composition.Register<IUserAgentProvider, AspNetUserAgentProvider>();
composition.Register<ISessionIdResolver, AspNetSessionIdResolver>();
composition.Register<IHostingEnvironment, AspNetHostingEnvironment>();
composition.Register<IBackOfficeInfo, AspNetBackOfficeInfo>();
composition.Register<IUmbracoApplicationLifetime, AspNetUmbracoApplicationLifetime>(Lifetime.Singleton);
composition.Register<IPasswordHasher, AspNetPasswordHasher>();
composition.Register<IFilePermissionHelper, FilePermissionHelper>(Lifetime.Singleton);
+2 -5
View File
@@ -134,7 +134,9 @@
<Compile Include="AppBuilderExtensions.cs" />
<Compile Include="AreaRegistrationContextExtensions.cs" />
<Compile Include="AspNet\AspNetHostingEnvironment.cs" />
<Compile Include="AspNet\AspNetUserAgentProvider.cs" />
<Compile Include="AspNet\FrameworkMarchal.cs" />
<Compile Include="AspNet\AspNetUmbracoApplicationLifetime.cs" />
<Compile Include="Cache\WebCachingAppCache.cs" />
<Compile Include="Compose\AuditEventsComponent.cs" />
<Compile Include="Compose\AuditEventsComposer.cs" />
@@ -158,8 +160,6 @@
<Compile Include="HttpContextExtensions.cs" />
<Compile Include="ImageCropperTemplateCoreExtensions.cs" />
<Compile Include="Install\ChangesMonitor.cs" />
<Compile Include="Install\InstallSteps\StarterKitDownloadStep.cs" />
<Compile Include="Install\InstallSteps\StarterKitInstallStep.cs" />
<Compile Include="Logging\OwinLogger.cs" />
<Compile Include="Logging\OwinLoggerFactory.cs" />
<Compile Include="Logging\WebProfiler.cs" />
@@ -270,7 +270,6 @@
<Compile Include="Composing\CompositionExtensions\WebMappingProfiles.cs" />
<Compile Include="Editors\BackOfficeNotificationsController.cs" />
<Compile Include="Install\InstallStepCollection.cs" />
<Compile Include="Install\InstallSteps\ConfigureMachineKey.cs" />
<Compile Include="Editors\MemberGroupController.cs" />
<Compile Include="Composing\CompositionExtensions\Controllers.cs" />
<Compile Include="HealthCheck\HealthCheckController.cs" />
@@ -359,7 +358,6 @@
<Compile Include="Editors\RelationController.cs" />
<Compile Include="GridTemplateExtensions.cs" />
<Compile Include="Editors\TemplateQueryController.cs" />
<Compile Include="Install\InstallSteps\SetUmbracoVersionStep.cs" />
<Compile Include="Install\InstallSteps\NewInstallStep.cs" />
<Compile Include="Install\UmbracoInstallArea.cs" />
<Compile Include="Install\Controllers\InstallApiController.cs" />
@@ -455,7 +453,6 @@
<Compile Include="HttpRequestExtensions.cs" />
<Compile Include="HttpUrlHelperExtensions.cs" />
<Compile Include="Install\FilePermissionHelper.cs" />
<Compile Include="Install\InstallHelper.cs" />
<Compile Include="Install\HttpInstallAuthorizeAttribute.cs" />
<Compile Include="Macros\PartialViewMacroController.cs" />
<Compile Include="Macros\PartialViewMacroEngine.cs" />
-41
View File
@@ -36,46 +36,5 @@ namespace Umbraco.Web
return new WebRuntime(this, configs, umbracoVersion, ioHelper, logger, profiler, hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom);
}
/// <summary>
/// Restarts the Umbraco application.
/// </summary>
public static void Restart()
{
// see notes in overload
var httpContext = HttpContext.Current;
if (httpContext != null)
{
httpContext.Application.Add("AppPoolRestarting", true);
httpContext.User = null;
}
Thread.CurrentPrincipal = null;
HttpRuntime.UnloadAppDomain();
}
/// <summary>
/// Restarts the Umbraco application.
/// </summary>
public static void Restart(HttpContextBase httpContext)
{
if (httpContext != null)
{
// 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();
}
}
}
-1
View File
@@ -70,7 +70,6 @@ namespace Umbraco.Web
_variationContextAccessor.VariationContext = new VariationContext(_defaultCultureAccessor.DefaultCulture);
}
var webSecurity = new WebSecurity(_httpContextAccessor, _userService, _globalSettings, _ioHelper);
return new UmbracoContext(_httpContextAccessor, _publishedSnapshotService, webSecurity, _globalSettings, _variationContextAccessor, _ioHelper, _uriUtility, _cookieManager);
+1 -1
View File
@@ -3,11 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.XPath;
using Umbraco.Composing;
using Umbraco.Core;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Xml;
using Umbraco.Web.Composing;
using Umbraco.Web.Mvc;
namespace Umbraco.Web