Add custom error page for BootFailedException

This commit is contained in:
Rasmus John Pedersen
2020-12-09 16:39:59 +01:00
parent 5efc1817d6
commit 9851c308f5
5 changed files with 143 additions and 8 deletions

View File

@@ -35,7 +35,16 @@ namespace Umbraco.Web.Composing
catch { /* don't make it worse */ }
if (runtimeState?.BootFailedException != null)
BootFailedException.Rethrow(runtimeState.BootFailedException);
{
// if we throw the exception here the HttpApplication.Application_Error method will never be hit
// and our custom error page will not be shown, so we need to wait for the request to begin
// before we throw the exception.
context.BeginRequest += (sender, args) =>
{
BootFailedException.Rethrow(runtimeState.BootFailedException);
};
return;
}
// else... throw what we have
throw;

View File

@@ -1,7 +1,10 @@
using System.Configuration;
using System;
using System.Configuration;
using System.IO;
using System.Threading;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Logging.Serilog;
using Umbraco.Core.Runtime;
@@ -23,6 +26,53 @@ namespace Umbraco.Web
return runtime;
}
protected override void OnApplicationError(object sender, EventArgs evargs)
{
base.OnApplicationError(sender, evargs);
// if the exception is a BootFailedException we want to show a custom 500 page
if (Server.GetLastError() is BootFailedException)
{
// if the requested file exists on disk, clear the error and return
// this is needed to serve static files
if (File.Exists(Request.PhysicalPath))
{
Server.ClearError();
return;
}
// if the application is in debug mode we don't want to show the custom 500 page
if (Context.IsDebuggingEnabled) return;
// find the error file to show
var fileName = GetBootErrorFileName();
// if the file doesn't exist we return and a YSOD will be shown
if (File.Exists(fileName) == false) return;
Response.TrySkipIisCustomErrors = true;
Server.ClearError();
Response.Clear();
Response.StatusCode = 500;
Response.ContentType = "text/html";
Response.WriteFile(fileName);
CompleteRequest();
}
}
/// <summary>
/// Returns the absolute filename to the BootException html file.
/// </summary>
protected virtual string GetBootErrorFileName()
{
var fileName = Server.MapPath("~/config/errors/BootFailed.html");
if (File.Exists(fileName)) return fileName;
return Server.MapPath("~/umbraco/views/errors/BootFailed.html");
}
/// <summary>
/// Returns a new MainDom
/// </summary>

View File

@@ -6,7 +6,6 @@ using System.Web.Hosting;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Core.Logging.Serilog;
namespace Umbraco.Web
{

View File

@@ -357,15 +357,13 @@ namespace Umbraco.Web
// there's nothing we can do really
app.BeginRequest += (sender, args) =>
{
// would love to avoid throwing, and instead display a customized Umbraco 500
// page - however if we don't throw here, something else might go wrong, and
// it's this later exception that would be reported. could not figure out how
// to prevent it, either with httpContext.Response.End() or .ApplicationInstance
// .CompleteRequest()
// if we don't throw here, something else might go wrong,
// and it's this later exception that would be reported.
// also, if something goes wrong with our DI setup, the logging subsystem may
// not even kick in, so here we try to give as much detail as possible
// the exception is handled in UmbracoApplication which shows a custom error page
BootFailedException.Rethrow(Core.Composing.Current.RuntimeState.BootFailedException);
};
return;