Moved files from backoffice into Common + Introduced AspNetCoreComponent to invoke the Umbraco Application Init event

This commit is contained in:
Bjarke Berg
2020-03-27 11:39:17 +01:00
parent fe88662f48
commit 681a25b861
26 changed files with 134 additions and 102 deletions
@@ -15,5 +15,7 @@ namespace Umbraco.Net
void Restart();
event EventHandler ApplicationInit;
void InvokeApplicationInit();
}
}
@@ -16,6 +16,7 @@ using Umbraco.Core.Runtime;
using Umbraco.Tests.Common;
using Umbraco.Web.BackOffice;
using Umbraco.Web.BackOffice.AspNetCore;
using Umbraco.Web.Common.AspNetCore;
using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment;
namespace Umbraco.Tests.Integration.Implementations
@@ -1,11 +1,11 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Umbraco.Core.Configuration;
using Umbraco.Web.BackOffice.AspNetCore;
using Umbraco.Web.Common.AspNetCore;
namespace Umbraco.Tests.Integration.Implementations
{
public class TestHostingEnvironment : AspNetCoreHostingEnvironment, Umbraco.Core.Hosting.IHostingEnvironment
{
public TestHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor) : base(hostingSettings, webHostEnvironment, httpContextAccessor)
@@ -22,6 +22,7 @@ using Umbraco.Tests.Common;
using Umbraco.Tests.Integration.Implementations;
using Umbraco.Tests.Integration.Testing;
using Umbraco.Web.BackOffice.AspNetCore;
using Umbraco.Web.Common.AspNetCore;
using static Umbraco.Core.Migrations.Install.DatabaseBuilder;
namespace Umbraco.Tests.Integration
@@ -52,11 +53,11 @@ namespace Umbraco.Tests.Integration
// LightInject / Umbraco
var container = UmbracoServiceProviderFactory.CreateServiceContainer();
var serviceProviderFactory = new UmbracoServiceProviderFactory(container);
var umbracoContainer = serviceProviderFactory.GetContainer();
var umbracoContainer = serviceProviderFactory.GetContainer();
// Special case since we are not using the Generic Host, we need to manually add an AspNetCore service to the container
umbracoContainer.Register(x => Mock.Of<IHostApplicationLifetime>());
var testHelper = new TestHelper();
// Create the core runtime
@@ -70,7 +71,7 @@ namespace Umbraco.Tests.Integration
Assert.IsTrue(coreRuntime.MainDom.IsMainDom);
Assert.IsNull(coreRuntime.State.BootFailedException);
Assert.AreEqual(RuntimeLevel.Install, coreRuntime.State.Level);
Assert.AreEqual(RuntimeLevel.Install, coreRuntime.State.Level);
Assert.IsTrue(MyComposer.IsComposed);
Assert.IsFalse(MyComponent.IsInit);
Assert.IsFalse(MyComponent.IsTerminated);
@@ -88,7 +89,7 @@ namespace Umbraco.Tests.Integration
}
/// <summary>
/// Calling AddUmbracoCore to configure the container
/// Calling AddUmbracoCore to configure the container
/// </summary>
[Test]
public async Task AddUmbracoCore()
@@ -280,5 +281,5 @@ namespace Umbraco.Tests.Integration
}
}
}
@@ -5,7 +5,7 @@ using Microsoft.Extensions.Hosting;
using Umbraco.Core;
using Umbraco.Core.Hosting;
namespace Umbraco.Web.BackOffice.AspNetCore
namespace Umbraco.Web.Common.AspNetCore
{
public class AspNetCoreApplicationShutdownRegistry : IApplicationShutdownRegistry
{
@@ -1,7 +1,7 @@
using Umbraco.Core;
using Umbraco.Core.Configuration;
namespace Umbraco.Web.BackOffice.AspNetCore
namespace Umbraco.Web.Common.AspNetCore
{
public class AspNetCoreBackOfficeInfo : IBackOfficeInfo
{
@@ -6,16 +6,16 @@ using Microsoft.AspNetCore.Http;
using Umbraco.Core;
using Umbraco.Core.Configuration;
namespace Umbraco.Web.BackOffice.AspNetCore
namespace Umbraco.Web.Common.AspNetCore
{
public class AspNetCoreHostingEnvironment : Umbraco.Core.Hosting.IHostingEnvironment
{
private readonly IHostingSettings _hostingSettings;
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly IHttpContextAccessor _httpContextAccessor;
private string _localTempPath;
public AspNetCoreHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor)
@@ -103,7 +103,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
return applicationPath.Add(segment).Value;
}
}
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Http;
using Umbraco.Net;
namespace Umbraco.Web.BackOffice.AspNetCore
namespace Umbraco.Web.Common.AspNetCore
{
public class AspNetIpResolver : IIpResolver
{
@@ -2,7 +2,7 @@ using System;
using System.Runtime.InteropServices;
using Umbraco.Core.Diagnostics;
namespace Umbraco.Web.BackOffice.AspNetCore
namespace Umbraco.Web.Common.AspNetCore
{
public class AspNetCoreMarchal : IMarchal
@@ -2,7 +2,7 @@
using Microsoft.AspNetCore.Http.Features;
using Umbraco.Net;
namespace Umbraco.Web.BackOffice.AspNetCore
namespace Umbraco.Web.Common.AspNetCore
{
internal class AspNetCoreSessionIdResolver : ISessionIdResolver
{
@@ -13,7 +13,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
_httpContextAccessor = httpContextAccessor;
}
public string SessionId
{
get
@@ -15,11 +15,6 @@ namespace Umbraco.Web.Common.AspNetCore
{
_httpContextAccessor = httpContextAccessor;
_hostApplicationLifetime = hostApplicationLifetime;
hostApplicationLifetime.ApplicationStarted.Register(() =>
{
ApplicationInit?.Invoke(this, EventArgs.Empty);
});
}
public bool IsRestarting { get; set; }
@@ -39,6 +34,10 @@ namespace Umbraco.Web.Common.AspNetCore
_hostApplicationLifetime.StopApplication();
}
public void InvokeApplicationInit()
{
ApplicationInit?.Invoke(this, EventArgs.Empty);
}
public event EventHandler ApplicationInit;
}
}
@@ -19,9 +19,8 @@ using Umbraco.Core.Persistence;
using Umbraco.Core.Runtime;
using Umbraco.Web.Common.Runtime.Profiler;
namespace Umbraco.Web.BackOffice.AspNetCore
namespace Umbraco.Web.Common.AspNetCore
{
// TODO: Move to Umbraco.Web.Common
public static class UmbracoCoreServiceCollectionExtensions
{
/// <summary>
@@ -71,7 +70,8 @@ namespace Umbraco.Web.BackOffice.AspNetCore
public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, IRegister umbContainer, Assembly entryAssembly)
{
if (services is null) throw new ArgumentNullException(nameof(services));
if (umbContainer is null) throw new ArgumentNullException(nameof(umbContainer));
var container = umbContainer;
if (container is null) throw new ArgumentNullException(nameof(container));
if (entryAssembly is null) throw new ArgumentNullException(nameof(entryAssembly));
// Special case! The generic host adds a few default services but we need to manually add this one here NOW because
@@ -97,7 +97,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
backOfficeInfo,
typeFinder);
var factory = coreRuntime.Configure(umbContainer);
var factory = coreRuntime.Configure(container);
return services;
}
@@ -0,0 +1,11 @@
using System;
using Microsoft.AspNetCore.Http;
namespace Umbraco.Web.Common.Lifetime
{
public interface IUmbracoRequestLifetime
{
event EventHandler<HttpContext> RequestStart;
event EventHandler<HttpContext> RequestEnd;
}
}
@@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Http;
namespace Umbraco.Web.Common.Lifetime
{
public interface IUmbracoRequestLifetimeManager
{
void InitRequest(HttpContext context);
void EndRequest(HttpContext context);
}
}
@@ -0,0 +1,21 @@
using System;
using Microsoft.AspNetCore.Http;
namespace Umbraco.Web.Common.Lifetime
{
public class UmbracoRequestLifetime : IUmbracoRequestLifetime, IUmbracoRequestLifetimeManager
{
public event EventHandler<HttpContext> RequestStart;
public event EventHandler<HttpContext> RequestEnd;
public void InitRequest(HttpContext context)
{
RequestStart?.Invoke(this, context);
}
public void EndRequest(HttpContext context)
{
RequestEnd?.Invoke(this, context);
}
}
}
@@ -1,6 +1,7 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Umbraco.Web.Common.Lifetime;
namespace Umbraco.Web.Common.Middleware
{
@@ -22,31 +23,4 @@ namespace Umbraco.Web.Common.Middleware
}
}
public interface IUmbracoRequestLifetime
{
event EventHandler<HttpContext> RequestStart;
event EventHandler<HttpContext> RequestEnd;
}
public class UmbracoRequestLifetime : IUmbracoRequestLifetime, IUmbracoRequestLifetimeManager
{
public event EventHandler<HttpContext> RequestStart;
public event EventHandler<HttpContext> RequestEnd;
public void InitRequest(HttpContext context)
{
RequestStart?.Invoke(this, context);
}
public void EndRequest(HttpContext context)
{
RequestEnd?.Invoke(this, context);
}
}
public interface IUmbracoRequestLifetimeManager
{
void InitRequest(HttpContext context);
void EndRequest(HttpContext context);
}
}
@@ -0,0 +1,29 @@
using Microsoft.Extensions.Hosting;
using Umbraco.Core.Composing;
using Umbraco.Net;
namespace Umbraco.Web.Common.Runtime
{
public sealed class AspNetCoreComponent : IComponent
{
private readonly IHostApplicationLifetime _hostApplicationLifetime;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
public AspNetCoreComponent(IHostApplicationLifetime hostApplicationLifetime, IUmbracoApplicationLifetime umbracoApplicationLifetime)
{
_hostApplicationLifetime = hostApplicationLifetime;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
}
public void Initialize()
{
_hostApplicationLifetime.ApplicationStarted.Register(() => {
_umbracoApplicationLifetime.InvokeApplicationInit();
});
}
public void Terminate()
{
}
}
}
@@ -5,24 +5,33 @@ using Umbraco.Core.Hosting;
using Umbraco.Net;
using Umbraco.Core.Runtime;
using Umbraco.Web.Common.AspNetCore;
using Umbraco.Web.Common.Lifetime;
namespace Umbraco.Web.BackOffice.AspNetCore
namespace Umbraco.Web.Common.Runtime
{
/// <summary>
/// Adds/replaces AspNetCore specific services
/// </summary>
[ComposeBefore(typeof(ICoreComposer))]
[ComposeAfter(typeof(CoreInitialComposer))]
public class AspNetCoreComposer : IComposer
public class AspNetCoreComposer : ComponentComposer<AspNetCoreComponent>, IComposer
{
public void Compose(Composition composition)
public new void Compose(Composition composition)
{
base.Compose(composition);
// AspNetCore specific services
composition.RegisterUnique<IHttpContextAccessor, HttpContextAccessor>();
// Our own netcore implementations
composition.RegisterUnique<IUmbracoApplicationLifetime, AspNetCoreUmbracoApplicationLifetime>();
composition.RegisterUnique<IApplicationShutdownRegistry, AspNetCoreApplicationShutdownRegistry>();
// The umbraco request lifetime
var umbracoRequestLifetime = new UmbracoRequestLifetime();
composition.RegisterUnique<IUmbracoRequestLifetimeManager>(factory => umbracoRequestLifetime);
composition.RegisterUnique<IUmbracoRequestLifetime>(factory => umbracoRequestLifetime);
composition.RegisterUnique<IUmbracoApplicationLifetime, AspNetCoreUmbracoApplicationLifetime>();
}
}
}
@@ -1,18 +0,0 @@
using Umbraco.Core.Composing;
namespace Umbraco.Web.Common.Runtime.Profiler
{
public sealed class WebInitialComponent : IComponent
{
public void Initialize()
{
}
public void Terminate()
{
}
}
}
@@ -1,24 +0,0 @@
using Microsoft.AspNetCore.Http;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Net;
using Umbraco.Web.Common.AspNetCore;
using Umbraco.Web.Common.Middleware;
namespace Umbraco.Web.Common.Runtime.Profiler
{
public class WebInitialComposer : ComponentComposer<WebInitialComponent>, ICoreComposer
{
public override void Compose(Composition composition)
{
base.Compose(composition);
var umbracoRequestLifetime = new UmbracoRequestLifetime();
composition.RegisterUnique<IUmbracoRequestLifetimeManager>(factory => umbracoRequestLifetime);
composition.RegisterUnique<IUmbracoRequestLifetime>(factory => umbracoRequestLifetime);
composition.RegisterUnique<IUmbracoApplicationLifetime, AspNetCoreUmbracoApplicationLifetime>();
}
}
}
@@ -22,10 +22,15 @@ namespace Umbraco.Web.Common.Runtime.Profiler
// create our own provider, which can provide a profiler even during boot
_provider = new WebProfilerProvider();
_httpContextAccessor = httpContextAccessor;
MiniProfiler.DefaultOptions.ProfilerProvider = _provider;
}
public string Render() => MiniProfiler.Current
.RenderIncludes(_httpContextAccessor.HttpContext, RenderPosition.Right).ToString();
public string Render()
{
return MiniProfiler.Current
.RenderIncludes(_httpContextAccessor.HttpContext, RenderPosition.Right).ToString();
}
public IDisposable Step(string name) => MiniProfiler.Current?.Step(name);
@@ -2,6 +2,7 @@
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Net;
using Umbraco.Web.Common.Lifetime;
using Umbraco.Web.Common.Middleware;
namespace Umbraco.Web.Common.Runtime.Profiler
@@ -11,6 +11,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Configuration\Umbraco.Configuration.csproj" />
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj" />
<ProjectReference Include="..\Umbraco.Infrastructure\Umbraco.Infrastructure.csproj" />
</ItemGroup>
+7 -1
View File
@@ -8,7 +8,9 @@ using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Umbraco.Composing;
using Umbraco.Web.BackOffice.AspNetCore;
using Umbraco.Web.Common.AspNetCore;
using Umbraco.Web.Common.Extensions;
using Umbraco.Web.Website.AspNetCore;
@@ -52,6 +54,7 @@ namespace Umbraco.Web.UI.BackOffice
app.UseDeveloperExceptionPage();
}
app.UseUmbracoCore();
app.UseUmbracoWebsite();
app.UseUmbracoBackOffice();
@@ -59,7 +62,10 @@ namespace Umbraco.Web.UI.BackOffice
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World!"); });
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync($"<html><body>Hello World!{Current.Profiler.Render()}</body></html>");
});
});
}
}
@@ -35,5 +35,9 @@ namespace Umbraco.Web.AspNet
}
public event EventHandler ApplicationInit;
public void InvokeApplicationInit()
{
}
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ namespace Umbraco.Web.Logging
MiniProfiler.Configure(new MiniProfilerOptions
{
SqlFormatter = new SqlServerFormatter(),
StackMaxLength = 5000,
StackMaxLength = 5000,
ProfilerProvider = _provider
});
}