Merge remote-tracking branch 'origin/netcore/netcore' into netcore/feature/AB6586-migrate_controllers
This commit is contained in:
@@ -27,8 +27,6 @@ namespace Umbraco.Extensions
|
||||
return runtime.State.Level > RuntimeLevel.BootFailed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Start Umbraco
|
||||
/// </summary>
|
||||
@@ -38,27 +36,20 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
if (app == null) throw new ArgumentNullException(nameof(app));
|
||||
|
||||
if (app.UmbracoCanBoot())
|
||||
{
|
||||
var runtime = app.ApplicationServices.GetRequiredService<IRuntime>();
|
||||
if (!app.UmbracoCanBoot()) return app;
|
||||
|
||||
// Register a listener for application shutdown in order to terminate the runtime
|
||||
var hostLifetime = app.ApplicationServices.GetRequiredService<IApplicationShutdownRegistry>();
|
||||
var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime);
|
||||
hostLifetime.RegisterObject(runtimeShutdown);
|
||||
var runtime = app.ApplicationServices.GetRequiredService<IRuntime>();
|
||||
// Register a listener for application shutdown in order to terminate the runtime
|
||||
var hostLifetime = app.ApplicationServices.GetRequiredService<IApplicationShutdownRegistry>();
|
||||
var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime);
|
||||
hostLifetime.RegisterObject(runtimeShutdown);
|
||||
|
||||
// Register our global threadabort enricher for logging
|
||||
var threadAbortEnricher = app.ApplicationServices.GetRequiredService<ThreadAbortExceptionEnricher>();
|
||||
LogContext.Push(threadAbortEnricher); // NOTE: We are not in a using clause because we are not removing it, it is on the global context
|
||||
// Register our global threadabort enricher for logging
|
||||
var threadAbortEnricher = app.ApplicationServices.GetRequiredService<ThreadAbortExceptionEnricher>();
|
||||
LogContext.Push(threadAbortEnricher); // NOTE: We are not in a using clause because we are not removing it, it is on the global context
|
||||
|
||||
// Start the runtime!
|
||||
runtime.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Register simple middleware to show the error like we used to in UmbracoModule? Or maybe that's part of a UseUmbracoWebsite/backoffice type thing .. probably :)
|
||||
|
||||
}
|
||||
// Start the runtime!
|
||||
runtime.Start();
|
||||
|
||||
return app;
|
||||
}
|
||||
@@ -73,13 +64,24 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
if (app == null) throw new ArgumentNullException(nameof(app));
|
||||
|
||||
if (!app.UmbracoCanBoot()) return app;
|
||||
if (!app.UmbracoCanBoot())
|
||||
{
|
||||
app.UseMiddleware<BootFailedMiddleware>();
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseMiddleware<UmbracoRequestMiddleware>();
|
||||
app.UseMiddleware<MiniProfilerMiddleware>();
|
||||
}
|
||||
|
||||
app.UseMiddleware<UmbracoRequestMiddleware>();
|
||||
app.UseMiddleware<MiniProfilerMiddleware>();
|
||||
return app;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds request based serilog enrichers to the LogContext for each request
|
||||
/// </summary>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
public static IApplicationBuilder UseUmbracoRequestLogging(this IApplicationBuilder app)
|
||||
{
|
||||
if (app == null) throw new ArgumentNullException(nameof(app));
|
||||
|
||||
@@ -13,6 +13,8 @@ namespace Umbraco.Extensions
|
||||
/// <returns></returns>
|
||||
public static IApplicationBuilder UseUmbracoInstaller(this IApplicationBuilder app)
|
||||
{
|
||||
if (!app.UmbracoCanBoot()) return app;
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
var installerRoutes = app.ApplicationServices.GetRequiredService<InstallAreaRoutes>();
|
||||
|
||||
@@ -34,10 +34,6 @@ namespace Umbraco.Extensions
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddUmbracoWebComponents(this IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<UmbracoRequestLoggingMiddleware>();
|
||||
services.AddTransient<UmbracoRequestMiddleware>();
|
||||
|
||||
services.TryAddSingleton<UmbracoJsonModelBinder>();
|
||||
services.ConfigureOptions<UmbracoMvcConfigureOptions>();
|
||||
services.TryAddEnumerable(ServiceDescriptor.Transient<IApplicationModelProvider, UmbracoApiBehaviorApplicationModelProvider>());
|
||||
|
||||
|
||||
@@ -92,6 +92,10 @@ namespace Umbraco.Web.Common.Install
|
||||
return View();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to perform the redirect to the installer when the runtime level is <see cref="RuntimeLevel.Install"/> or <see cref="RuntimeLevel.Upgrade"/>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public ActionResult Redirect()
|
||||
{
|
||||
|
||||
34
src/Umbraco.Web.Common/Middleware/BootFailedMiddleware.cs
Normal file
34
src/Umbraco.Web.Common/Middleware/BootFailedMiddleware.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Exceptions;
|
||||
|
||||
namespace Umbraco.Web.Common.Middleware
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes when Umbraco booting fails in order to show the problem
|
||||
/// </summary>
|
||||
public class BootFailedMiddleware : IMiddleware
|
||||
{
|
||||
private readonly IRuntimeState _runtimeState;
|
||||
|
||||
public BootFailedMiddleware(IRuntimeState runtimeState)
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
|
||||
{
|
||||
if (_runtimeState.Level == RuntimeLevel.BootFailed)
|
||||
{
|
||||
// short circuit
|
||||
BootFailedException.Rethrow(_runtimeState.BootFailedException);
|
||||
}
|
||||
else
|
||||
{
|
||||
await next(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,9 @@ using Umbraco.Core.Logging.Serilog.Enrichers;
|
||||
|
||||
namespace Umbraco.Web.Common.Middleware
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds request based serilog enrichers to the LogContext for each request
|
||||
/// </summary>
|
||||
public class UmbracoRequestLoggingMiddleware : IMiddleware
|
||||
{
|
||||
private readonly HttpSessionIdEnricher _sessionIdEnricher;
|
||||
|
||||
@@ -6,6 +6,8 @@ using Umbraco.Web.Common.Lifetime;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Cache;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Web.Common.Middleware
|
||||
{
|
||||
@@ -18,22 +20,26 @@ namespace Umbraco.Web.Common.Middleware
|
||||
private readonly ILogger _logger;
|
||||
private readonly IUmbracoRequestLifetimeManager _umbracoRequestLifetimeManager;
|
||||
private readonly IUmbracoContextFactory _umbracoContextFactory;
|
||||
private readonly IRequestCache _requestCache;
|
||||
|
||||
public UmbracoRequestMiddleware(
|
||||
ILogger logger,
|
||||
IUmbracoRequestLifetimeManager umbracoRequestLifetimeManager,
|
||||
IUmbracoContextFactory umbracoContextFactory)
|
||||
IUmbracoContextFactory umbracoContextFactory,
|
||||
IRequestCache requestCache)
|
||||
{
|
||||
_logger = logger;
|
||||
_umbracoRequestLifetimeManager = umbracoRequestLifetimeManager;
|
||||
_umbracoContextFactory = umbracoContextFactory;
|
||||
_requestCache = requestCache;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
|
||||
{
|
||||
// do not process if client-side request
|
||||
var requestUri = new Uri(context.Request.GetEncodedUrl(), UriKind.RelativeOrAbsolute);
|
||||
|
||||
if (new Uri(context.Request.GetEncodedUrl(), UriKind.RelativeOrAbsolute).IsClientSideRequest())
|
||||
// do not process if client-side request
|
||||
if (requestUri.IsClientSideRequest())
|
||||
{
|
||||
await next(context);
|
||||
return;
|
||||
@@ -43,6 +49,12 @@ namespace Umbraco.Web.Common.Middleware
|
||||
|
||||
try
|
||||
{
|
||||
if (umbracoContextReference.UmbracoContext.IsFrontEndUmbracoRequest)
|
||||
{
|
||||
LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, _requestCache);
|
||||
_logger.Verbose<UmbracoRequestMiddleware>("Begin request [{HttpRequestId}]: {RequestUrl}", httpRequestId, requestUri);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_umbracoRequestLifetimeManager.InitRequest(context);
|
||||
@@ -52,15 +64,80 @@ namespace Umbraco.Web.Common.Middleware
|
||||
// try catch so we don't kill everything in all requests
|
||||
_logger.Error<UmbracoRequestMiddleware>(ex);
|
||||
}
|
||||
|
||||
await next(context);
|
||||
|
||||
_umbracoRequestLifetimeManager.EndRequest(context);
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
await next(context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_umbracoRequestLifetimeManager.EndRequest(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
umbracoContextReference.Dispose();
|
||||
if (umbracoContextReference.UmbracoContext.IsFrontEndUmbracoRequest)
|
||||
{
|
||||
LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, _requestCache);
|
||||
_logger.Verbose<UmbracoRequestMiddleware>("End Request [{HttpRequestId}]: {RequestUrl} ({RequestDuration}ms)", httpRequestId, requestUri, DateTime.Now.Subtract(umbracoContextReference.UmbracoContext.ObjectCreated).TotalMilliseconds);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DisposeRequestCacheItems(_logger, _requestCache, requestUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
umbracoContextReference.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Any object that is in the HttpContext.Items collection that is IDisposable will get disposed on the end of the request
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <param name="requestCache"></param>
|
||||
/// <param name="requestUri"></param>
|
||||
private static void DisposeRequestCacheItems(ILogger logger, IRequestCache requestCache, Uri requestUri)
|
||||
{
|
||||
// do not process if client-side request
|
||||
if (requestUri.IsClientSideRequest())
|
||||
return;
|
||||
|
||||
//get a list of keys to dispose
|
||||
var keys = new HashSet<string>();
|
||||
foreach (var i in requestCache)
|
||||
{
|
||||
if (i.Value is IDisposeOnRequestEnd || i.Key is IDisposeOnRequestEnd)
|
||||
{
|
||||
keys.Add(i.Key);
|
||||
}
|
||||
}
|
||||
//dispose each item and key that was found as disposable.
|
||||
foreach (var k in keys)
|
||||
{
|
||||
try
|
||||
{
|
||||
requestCache.Get(k).DisposeIfDisposable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error<UmbracoRequestMiddleware>("Could not dispose item with key " + k, ex);
|
||||
}
|
||||
try
|
||||
{
|
||||
k.DisposeIfDisposable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error<UmbracoRequestMiddleware>("Could not dispose item key " + k, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Web.Common.Middleware;
|
||||
|
||||
namespace Umbraco.Web.Common.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes if the boot fails to ensure critical services are registered
|
||||
/// </summary>
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.BootFailed)]
|
||||
public class AspNetCoreBootFailedComposer : IComposer
|
||||
{
|
||||
public void Compose(Composition composition)
|
||||
{
|
||||
composition.RegisterUnique<BootFailedMiddleware>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,9 +18,13 @@ using Umbraco.Web.Common.Install;
|
||||
using Umbraco.Extensions;
|
||||
using System.Linq;
|
||||
using Umbraco.Web.Common.Controllers;
|
||||
using System;
|
||||
using Umbraco.Web.Common.Middleware;
|
||||
using Umbraco.Web.Common.ModelBinding;
|
||||
|
||||
namespace Umbraco.Web.Common.Runtime
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Adds/replaces AspNetCore specific services
|
||||
/// </summary>
|
||||
@@ -77,6 +81,11 @@ namespace Umbraco.Web.Common.Runtime
|
||||
|
||||
composition.RegisterUnique<InstallAreaRoutes>();
|
||||
|
||||
composition.RegisterUnique<UmbracoRequestLoggingMiddleware>();
|
||||
composition.RegisterUnique<UmbracoRequestMiddleware>();
|
||||
composition.RegisterUnique<BootFailedMiddleware>();
|
||||
|
||||
composition.RegisterUnique<UmbracoJsonModelBinder>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user