Merge branch 'temp8' of https://github.com/umbraco/Umbraco-CMS into temp8

This commit is contained in:
Shannon
2018-11-20 19:31:08 +11:00
9 changed files with 92 additions and 81 deletions

65
src/Umbraco.Core/Runtime/CoreRuntime.cs Normal file → Executable file
View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Reflection;
using System.Threading;
using System.Web;
using LightInject;
@@ -12,6 +13,7 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Exceptions;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Logging.Serilog;
using Umbraco.Core.Migrations.Upgrade;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Dtos;
@@ -29,26 +31,29 @@ namespace Umbraco.Core.Runtime
/// should be possible to use this runtime in console apps.</remarks>
public class CoreRuntime : IRuntime
{
private readonly UmbracoApplicationBase _app;
private BootLoader _bootLoader;
private RuntimeState _state;
/// <summary>
/// Initializes a new instance of the <see cref="CoreRuntime"/> class.
/// </summary>
/// <param name="umbracoApplication">The Umbraco HttpApplication.</param>
public CoreRuntime(UmbracoApplicationBase umbracoApplication)
{
_app = umbracoApplication ?? throw new ArgumentNullException(nameof(umbracoApplication));
}
public CoreRuntime()
{ }
/// <inheritdoc/>
public virtual void Boot(ServiceContainer container)
{
// some components may want to initialize with the UmbracoApplicationBase
// well, they should not - we should not do this
// TODO remove this eventually.
container.RegisterInstance(_app);
container.ConfigureUmbracoCore(); // also sets Current.Container
// register the essential stuff,
// ie the global application logger
// (profiler etc depend on boot manager)
var logger = GetLogger();
container.RegisterInstance(logger);
// now it is ok to use Current.Logger
ConfigureUnhandledException(logger);
ConfigureAssemblyResolve(logger);
Compose(container);
@@ -115,6 +120,46 @@ namespace Umbraco.Core.Runtime
//sa.Scope?.Dispose();
}
/// <summary>
/// Gets a logger.
/// </summary>
protected virtual ILogger GetLogger()
{
return SerilogLogger.CreateWithDefaultConfiguration();
}
protected virtual void ConfigureUnhandledException(ILogger logger)
{
//take care of unhandled exceptions - there is nothing we can do to
// prevent the launch process to go down but at least we can try
// and log the exception
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
{
var exception = (Exception)args.ExceptionObject;
var isTerminating = args.IsTerminating; // always true?
var msg = "Unhandled exception in AppDomain";
if (isTerminating) msg += " (terminating)";
msg += ".";
logger.Error<CoreRuntime>(exception, msg);
};
}
protected virtual void ConfigureAssemblyResolve(ILogger logger)
{
// When an assembly can't be resolved. In here we can do magic with the assembly name and try loading another.
// This is used for loading a signed assembly of AutoMapper (v. 3.1+) without having to recompile old code.
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
if (args.Name.StartsWith("AutoMapper") && args.Name.EndsWith("PublicKeyToken=null"))
return Assembly.Load(args.Name.Replace(", PublicKeyToken=null", ", PublicKeyToken=be96cd2c38ef1005"));
return null;
};
}
private void AquireMainDom(IServiceFactory container)
{
using (var timer = ProfilingLogger.DebugDuration<CoreRuntime>("Acquiring MainDom.", "Aquired."))

4
src/Umbraco.Core/Umbraco.Core.csproj Normal file → Executable file
View File

@@ -602,9 +602,6 @@
<Compile Include="Logging\ProfilerExtensions.cs" />
<Compile Include="Logging\ProfilingLogger.cs" />
<Compile Include="Logging\VoidProfiler.cs" />
<Compile Include="Logging\WebProfiler.cs" />
<Compile Include="Logging\WebProfilerComponent.cs" />
<Compile Include="Logging\WebProfilerProvider.cs" />
<Compile Include="Macros\MacroErrorBehaviour.cs" />
<Compile Include="MainDom.cs" />
<Compile Include="Manifest\ManifestParser.cs" />
@@ -1455,7 +1452,6 @@
<Compile Include="UdiRange.cs" />
<Compile Include="UdiType.cs" />
<Compile Include="UdiTypeConverter.cs" />
<Compile Include="UmbracoApplicationBase.cs" />
<Compile Include="UpgradeableReadLock.cs" />
<Compile Include="UriExtensions.cs" />
<Compile Include="VersionExtensions.cs" />

24
src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs Normal file → Executable file
View File

@@ -14,6 +14,7 @@ using Umbraco.Core.Runtime;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Examine;
using Umbraco.Web;
namespace Umbraco.Tests.Runtimes
{
@@ -63,14 +64,6 @@ namespace Umbraco.Tests.Runtimes
return new TestRuntime(this);
}
// the application's logger is created by the application
// through GetLogger, that custom application can override
protected override ILogger GetLogger()
{
//return Mock.Of<ILogger>();
return new DebugDiagnosticsLogger();
}
// don't register anything against AppDomain
protected override void ConfigureUnhandledException(ILogger logger)
{ }
@@ -80,8 +73,18 @@ namespace Umbraco.Tests.Runtimes
public class TestRuntime : CoreRuntime
{
public TestRuntime(UmbracoApplicationBase umbracoApplication)
: base(umbracoApplication)
{ }
: base()
{
_umbracoApplication = umbracoApplication;
}
// the application's logger is created by the application
// through GetLogger, that custom application can override
protected override ILogger GetLogger()
{
//return Mock.Of<ILogger>();
return new DebugDiagnosticsLogger();
}
public override void Compose(ServiceContainer container)
{
@@ -115,6 +118,7 @@ namespace Umbraco.Tests.Runtimes
}
private MainDom _mainDom;
private readonly UmbracoApplicationBase _umbracoApplication;
public override void Boot(ServiceContainer container)
{

View File

@@ -3,8 +3,10 @@ using System.Threading;
using System.Web;
using StackExchange.Profiling;
using StackExchange.Profiling.SqlFormatters;
using Umbraco.Core;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Logging
namespace Umbraco.Web.Logging
{
/// <summary>
/// Implements <see cref="IProfiler"/> by using the MiniProfiler framework.

View File

@@ -1,8 +1,10 @@
using System;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Components;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Logging
namespace Umbraco.Web.Logging
{
internal class WebProfilerComponent : UmbracoComponentBase, IUmbracoCoreComponent
{

View File

@@ -3,7 +3,7 @@ using System.Threading;
using System.Web;
using StackExchange.Profiling;
namespace Umbraco.Core.Logging
namespace Umbraco.Web.Logging
{
/// <summary>
/// This is a custom MiniProfiler WebRequestProfilerProvider (which is generally the default) that allows

13
src/Umbraco.Web/Runtime/WebRuntime.cs Normal file → Executable file
View File

@@ -1,12 +1,12 @@
using System;
using System.Web;
using LightInject;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Runtime;
using Umbraco.Web.Logging;
namespace Umbraco.Web.Runtime
{
@@ -16,6 +16,7 @@ namespace Umbraco.Web.Runtime
/// <remarks>On top of CoreRuntime, handles all of the web-related runtime aspects of Umbraco.</remarks>
public class WebRuntime : CoreRuntime
{
private readonly UmbracoApplicationBase _umbracoApplication;
private IProfiler _webProfiler;
/// <summary>
@@ -23,8 +24,10 @@ namespace Umbraco.Web.Runtime
/// </summary>
/// <param name="umbracoApplication"></param>
public WebRuntime(UmbracoApplicationBase umbracoApplication)
: base(umbracoApplication)
{ }
: base()
{
_umbracoApplication = umbracoApplication;
}
/// <inheritdoc/>
public override void Boot(ServiceContainer container)
@@ -54,6 +57,10 @@ namespace Umbraco.Web.Runtime
/// <inheritdoc/>
public override void Compose(ServiceContainer container)
{
// some components may want to initialize with the UmbracoApplicationBase
// well, they should not - we should not do this
// TODO remove this eventually.
container.RegisterInstance(_umbracoApplication);
base.Compose(container);
// replace CoreRuntime's IProfiler registration

4
src/Umbraco.Web/Umbraco.Web.csproj Normal file → Executable file
View File

@@ -111,6 +111,9 @@
<Compile Include="Cache\UserGroupCacheRefresher.cs" />
<Compile Include="Components\BackOfficeUserAuditEventsComponent.cs" />
<Compile Include="Editors\BackOfficePreviewModel.cs" />
<Compile Include="Logging\WebProfiler.cs" />
<Compile Include="Logging\WebProfilerComponent.cs" />
<Compile Include="Logging\WebProfilerProvider.cs" />
<Compile Include="Media\Exif\BitConverterEx.cs" />
<Compile Include="Media\Exif\ExifBitConverter.cs" />
<Compile Include="Media\Exif\ExifEnums.cs" />
@@ -181,6 +184,7 @@
<Compile Include="Trees\LegacyTreeDataConverter.cs" />
<Compile Include="UI\JavaScript\ClientDependencyConfiguration.cs" />
<Compile Include="Editors\Binders\BlueprintItemBinder.cs" />
<Compile Include="UmbracoApplicationBase.cs" />
<Compile Include="WebApi\HttpActionContextExtensions.cs" />
<Compile Include="Models\ContentEditing\IContentSave.cs" />
<Compile Include="WebApi\TrimModelBinder.cs" />

View File

@@ -4,11 +4,12 @@ using System.Threading;
using System.Web;
using System.Web.Hosting;
using LightInject;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Core.Logging.Serilog;
namespace Umbraco.Core
namespace Umbraco.Web
{
/// <summary>
/// Provides an abstract base class for the Umbraco HttpApplication.
@@ -22,14 +23,6 @@ namespace Umbraco.Core
/// </summary>
protected abstract IRuntime GetRuntime();
/// <summary>
/// Gets a logger.
/// </summary>
protected virtual ILogger GetLogger()
{
return SerilogLogger.CreateWithDefaultConfiguration();
}
// events - in the order they trigger
// were part of the BootManager architecture, would trigger only for the initial
@@ -61,54 +54,12 @@ namespace Umbraco.Core
// create the container for the application, and configure.
// the boot manager is responsible for registrations
var container = new ServiceContainer();
container.ConfigureUmbracoCore(); // also sets Current.Container
// register the essential stuff,
// ie the global application logger
// (profiler etc depend on boot manager)
var logger = GetLogger();
container.RegisterInstance(logger);
// now it is ok to use Current.Logger
ConfigureUnhandledException(logger);
ConfigureAssemblyResolve(logger);
// get runtime & boot
_runtime = GetRuntime();
_runtime.Boot(container);
}
protected virtual void ConfigureUnhandledException(ILogger logger)
{
//take care of unhandled exceptions - there is nothing we can do to
// prevent the entire w3wp process to go down but at least we can try
// and log the exception
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
{
var exception = (Exception)args.ExceptionObject;
var isTerminating = args.IsTerminating; // always true?
var msg = "Unhandled exception in AppDomain";
if (isTerminating) msg += " (terminating)";
msg += ".";
logger.Error<UmbracoApplicationBase>(exception, msg);
};
}
protected virtual void ConfigureAssemblyResolve(ILogger logger)
{
// When an assembly can't be resolved. In here we can do magic with the assembly name and try loading another.
// This is used for loading a signed assembly of AutoMapper (v. 3.1+) without having to recompile old code.
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
if (args.Name.StartsWith("AutoMapper") && args.Name.EndsWith("PublicKeyToken=null"))
return Assembly.Load(args.Name.Replace(", PublicKeyToken=null", ", PublicKeyToken=be96cd2c38ef1005"));
return null;
};
}
// called by ASP.NET (auto event wireup) once per app domain
// do NOT set instance data here - only static (see docs)
// sender is System.Web.HttpApplicationFactory, evargs is EventArgs.Empty