Add nice error page for boot, like in v8

This commit is contained in:
Bjarke Berg
2021-03-08 10:03:36 +01:00
parent a86054e487
commit 72411aa1a1
5 changed files with 52 additions and 12 deletions

View File

@@ -19,6 +19,12 @@ namespace Umbraco.Cms.Core.Configuration.Models
/// </remarks>
public bool InstallUnattended { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating whether unattended upgrades are enabled.
/// </summary>
public bool UpgradeUnattended { get; set; } = false;
/// <summary>
/// Gets or sets a value to use for creating a user with a name for Unattended Installs
/// </summary>

View File

@@ -14,7 +14,6 @@ using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Migrations.Install;
using Umbraco.Cms.Infrastructure.Migrations.Upgrade;
using Umbraco.Cms.Infrastructure.Persistence;
using Constants = Umbraco.Cms.Core.Constants;
namespace Umbraco.Cms.Infrastructure.Runtime
{
@@ -96,7 +95,7 @@ namespace Umbraco.Cms.Infrastructure.Runtime
if (State.Level <= RuntimeLevel.BootFailed)
{
throw new InvalidOperationException($"Cannot start the runtime if the runtime level is less than or equal to {RuntimeLevel.BootFailed}");
return; // The exception will be rethrown by BootFailedMiddelware
}
IApplicationShutdownRegistry hostingEnvironmentLifetime = _applicationShutdownRegistry;
@@ -110,8 +109,8 @@ namespace Umbraco.Cms.Infrastructure.Runtime
await _eventAggregator.PublishAsync(new UmbracoApplicationStarting(State.Level), cancellationToken);
// if level is Updrade and reason is UpgradeMigrations, that means we need to perform an unattended upgrade
if (State.Reason == RuntimeLevelReason.UpgradeMigrations && State.Level == RuntimeLevel.Upgrade)
// if level is Run and reason is UpgradeMigrations, that means we need to perform an unattended upgrade
if (State.Reason == RuntimeLevelReason.UpgradeMigrations && State.Level == RuntimeLevel.Run)
{
// do the upgrade
DoUnattendedUpgrade();
@@ -181,11 +180,12 @@ namespace Umbraco.Cms.Infrastructure.Runtime
_databaseFactory.ConfigureForUpgrade();
}
}
catch
catch (Exception ex)
{
State.Configure(RuntimeLevel.BootFailed, RuntimeLevelReason.BootFailedOnException);
timer?.Fail();
throw;
_logger.LogError(ex, "Boot Failed");
// We do not throw the exception. It will be rethrown by BootFailedMiddleware
}
}
}

View File

@@ -116,7 +116,8 @@ namespace Umbraco.Cms.Core
// else it is bad enough that we want to throw
Reason = RuntimeLevelReason.BootFailedCannotConnectToDatabase;
throw new BootFailedException("A connection string is configured but Umbraco could not connect to the database.");
BootFailedException =new BootFailedException("A connection string is configured but Umbraco could not connect to the database.");
throw BootFailedException;
}
case UmbracoDatabaseState.NotInstalled:
{
@@ -133,7 +134,7 @@ namespace Umbraco.Cms.Core
// 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.LogDebug("Has not reached the final upgrade step, need to upgrade Umbraco.");
Level = RuntimeLevel.Upgrade;
Level = _unattendedSettings.Value.UpgradeUnattended ? RuntimeLevel.Run : RuntimeLevel.Upgrade;
Reason = RuntimeLevelReason.UpgradeMigrations;
}
break;
@@ -192,7 +193,8 @@ namespace Umbraco.Cms.Core
// else it is bad enough that we want to throw
Reason = RuntimeLevelReason.BootFailedCannotCheckUpgradeState;
throw new BootFailedException("Could not check the upgrade state.", e);
BootFailedException = new BootFailedException("Could not check the upgrade state.", e);
throw BootFailedException;
}
}
@@ -251,9 +253,12 @@ namespace Umbraco.Cms.Core
_logger.LogInformation(ex, "Error during unattended install.");
database.AbortTransaction();
throw new UnattendedInstallException(
var innerException = new UnattendedInstallException(
"The database configuration failed with the following message: " + ex.Message
+ "\n Please check log file for additional information (can be found in '/App_Data/Logs/')");
BootFailedException = new BootFailedException(innerException.Message, innerException);
throw BootFailedException;
}
}
}

View File

@@ -121,6 +121,7 @@ namespace Umbraco.Extensions
if (!app.UmbracoCanBoot())
{
app.UseStaticFiles(); // We need static files to show the nice error page.
app.UseMiddleware<BootFailedMiddleware>();
}
else

View File

@@ -1,7 +1,10 @@
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Exceptions;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Web.Common.Middleware
@@ -12,10 +15,12 @@ namespace Umbraco.Cms.Web.Common.Middleware
public class BootFailedMiddleware : IMiddleware
{
private readonly IRuntimeState _runtimeState;
private readonly IHostingEnvironment _hostingEnvironment;
public BootFailedMiddleware(IRuntimeState runtimeState)
public BootFailedMiddleware(IRuntimeState runtimeState, IHostingEnvironment hostingEnvironment)
{
_runtimeState = runtimeState;
_hostingEnvironment = hostingEnvironment;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
@@ -23,12 +28,35 @@ namespace Umbraco.Cms.Web.Common.Middleware
if (_runtimeState.Level == RuntimeLevel.BootFailed)
{
// short circuit
BootFailedException.Rethrow(_runtimeState.BootFailedException);
//
if (_hostingEnvironment.IsDebugMode)
{
BootFailedException.Rethrow(_runtimeState.BootFailedException);
}
else // Print a nice error page
{
context.Response.Clear();
context.Response.StatusCode = 500;
var file = GetBootErrorFileName();
var viewContent = await File.ReadAllTextAsync(file);
await context.Response.WriteAsync(viewContent, Encoding.UTF8);
}
}
else
{
await next(context);
}
}
private string GetBootErrorFileName()
{
var fileName = _hostingEnvironment.MapPathWebRoot("~/config/errors/BootFailed.html");
if (File.Exists(fileName)) return fileName;
return _hostingEnvironment.MapPathWebRoot("~/umbraco/views/errors/BootFailed.html");
}
}
}