parent
b966ed0ba3
commit
a83c556bb7
|
|
@ -168,13 +168,8 @@ namespace Microsoft.AspNet.Hosting.Internal
|
||||||
|
|
||||||
return builder.Build();
|
return builder.Build();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex) when (_captureStartupErrors)
|
||||||
{
|
{
|
||||||
if (!_captureStartupErrors)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnsureApplicationServices may have failed due to a missing or throwing Startup class.
|
// EnsureApplicationServices may have failed due to a missing or throwing Startup class.
|
||||||
if (_applicationServices == null)
|
if (_applicationServices == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,72 +12,38 @@ using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.ExceptionServices;
|
using System.Runtime.ExceptionServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Encodings.Web;
|
using System.Text.Encodings.Web;
|
||||||
using Microsoft.Extensions.CompilationAbstractions;
|
|
||||||
using Microsoft.Extensions.PlatformAbstractions;
|
using Microsoft.Extensions.PlatformAbstractions;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Hosting.Startup
|
namespace Microsoft.AspNet.Hosting.Startup
|
||||||
{
|
{
|
||||||
internal static class StartupExceptionPage
|
internal static class StartupExceptionPage
|
||||||
{
|
{
|
||||||
private const int MaxCompilationErrorsToShow = 20;
|
|
||||||
|
|
||||||
private static readonly string _errorPageFormatString = GetResourceString("GenericError.html", escapeBraces: true);
|
private static readonly string _errorPageFormatString = GetResourceString("GenericError.html", escapeBraces: true);
|
||||||
private static readonly string _errorMessageFormatString = GetResourceString("GenericError_Message.html");
|
private static readonly string _errorMessageFormatString = GetResourceString("GenericError_Message.html");
|
||||||
private static readonly string _errorExceptionFormatString = GetResourceString("GenericError_Exception.html");
|
private static readonly string _errorExceptionFormatString = GetResourceString("GenericError_Exception.html");
|
||||||
private static readonly string _errorFooterFormatString = GetResourceString("GenericError_Footer.html");
|
private static readonly string _errorFooterFormatString = GetResourceString("GenericError_Footer.html");
|
||||||
private static readonly string _compilationExceptionFormatString = GetResourceString("Compilation_Exception.html");
|
|
||||||
|
|
||||||
public static byte[] GenerateErrorHtml(bool showDetails, IRuntimeEnvironment runtimeEnvironment, params object[] errorDetails)
|
public static byte[] GenerateErrorHtml(bool showDetails, IRuntimeEnvironment runtimeEnvironment, Exception exception)
|
||||||
{
|
{
|
||||||
if (!showDetails)
|
|
||||||
{
|
|
||||||
errorDetails = new[] { "An error occurred while starting the application." };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the message for each error
|
// Build the message for each error
|
||||||
var wasSourceCodeWrittenOntoPage = false;
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
var rawExceptionDetails = new StringBuilder();
|
var rawExceptionDetails = new StringBuilder();
|
||||||
|
|
||||||
foreach (object error in errorDetails ?? new object[0])
|
if (!showDetails)
|
||||||
{
|
{
|
||||||
var ex = error as Exception;
|
WriteMessage("An error occurred while starting the application.", builder);
|
||||||
if (ex == null && error is ExceptionDispatchInfo)
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Assert(exception != null);
|
||||||
|
var wasSourceCodeWrittenOntoPage = false;
|
||||||
|
var flattenedExceptions = FlattenAndReverseExceptionTree(exception);
|
||||||
|
foreach (var innerEx in flattenedExceptions)
|
||||||
{
|
{
|
||||||
ex = ((ExceptionDispatchInfo)error).SourceException;
|
WriteException(innerEx, builder, ref wasSourceCodeWrittenOntoPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ex != null)
|
WriteRawExceptionDetails("Show raw exception details", exception.ToString(), rawExceptionDetails);
|
||||||
{
|
|
||||||
var flattenedExceptions = FlattenAndReverseExceptionTree(ex);
|
|
||||||
|
|
||||||
var compilationException = flattenedExceptions.OfType<ICompilationException>()
|
|
||||||
.FirstOrDefault();
|
|
||||||
if (compilationException != null)
|
|
||||||
{
|
|
||||||
WriteException(compilationException, builder, ref wasSourceCodeWrittenOntoPage);
|
|
||||||
|
|
||||||
var compilationErrorMessages = compilationException.CompilationFailures
|
|
||||||
.SelectMany(f => f.Messages.Select(m => m.FormattedMessage))
|
|
||||||
.Take(MaxCompilationErrorsToShow);
|
|
||||||
|
|
||||||
WriteRawExceptionDetails("Show raw compilation error details", compilationErrorMessages, rawExceptionDetails);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var innerEx in flattenedExceptions)
|
|
||||||
{
|
|
||||||
WriteException(innerEx, builder, ref wasSourceCodeWrittenOntoPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteRawExceptionDetails("Show raw exception details", new[] { ex.ToString() }, rawExceptionDetails);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var message = Convert.ToString(error, CultureInfo.InvariantCulture);
|
|
||||||
WriteMessage(message, builder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the footer
|
// Generate the footer
|
||||||
|
|
@ -171,84 +137,13 @@ namespace Microsoft.AspNet.Hosting.Startup
|
||||||
|
|
||||||
private static string BuildMethodParametersUnescaped(MethodBase method)
|
private static string BuildMethodParametersUnescaped(MethodBase method)
|
||||||
{
|
{
|
||||||
return "(" + string.Join(", ", method.GetParameters().Select(p => {
|
return "(" + string.Join(", ", method.GetParameters().Select(p =>
|
||||||
|
{
|
||||||
Type parameterType = p.ParameterType;
|
Type parameterType = p.ParameterType;
|
||||||
return ((parameterType != null) ? PrettyPrintTypeName(parameterType) : "?") + " " + p.Name;
|
return ((parameterType != null) ? PrettyPrintTypeName(parameterType) : "?") + " " + p.Name;
|
||||||
})) + ")";
|
})) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void BuildCodeSnippetDiv(CompilationFailure failure,
|
|
||||||
StringBuilder builder,
|
|
||||||
ref int totalErrorsShown)
|
|
||||||
{
|
|
||||||
const int NumContextLines = 3;
|
|
||||||
var fileName = failure.SourceFilePath;
|
|
||||||
if (totalErrorsShown < MaxCompilationErrorsToShow &&
|
|
||||||
!string.IsNullOrEmpty(fileName))
|
|
||||||
{
|
|
||||||
builder.Append(@"<div class=""codeSnippet"">")
|
|
||||||
.AppendFormat(@"<div class=""filename""><code>{0}</code></div>", HtmlEncodeAndReplaceLineBreaks(fileName))
|
|
||||||
.AppendLine();
|
|
||||||
|
|
||||||
IEnumerable<string> fileContent;
|
|
||||||
if (string.IsNullOrEmpty(failure.SourceFileContent))
|
|
||||||
{
|
|
||||||
fileContent = File.ReadLines(fileName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fileContent = failure.SourceFileContent.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
|
|
||||||
}
|
|
||||||
foreach (var message in failure.Messages)
|
|
||||||
{
|
|
||||||
if (totalErrorsShown++ > MaxCompilationErrorsToShow)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (totalErrorsShown > 1)
|
|
||||||
{
|
|
||||||
builder.AppendLine("<br />");
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Append(@"<div class=""error-message"">")
|
|
||||||
.Append(HtmlEncodeAndReplaceLineBreaks(message.Message))
|
|
||||||
.Append("</div>");
|
|
||||||
|
|
||||||
// StartLine and EndLine are 1-based
|
|
||||||
var startLine = message.StartLine - 1;
|
|
||||||
var endLine = message.EndLine - 1;
|
|
||||||
var preContextIndex = Math.Max(startLine - NumContextLines, 0);
|
|
||||||
var index = preContextIndex + 1;
|
|
||||||
foreach (var line in fileContent.Skip(preContextIndex).Take(startLine - preContextIndex))
|
|
||||||
{
|
|
||||||
builder.Append(@"<div class=""line faded"">")
|
|
||||||
.AppendFormat(@"<span class=""line-number"">{0}</span><code>", index++)
|
|
||||||
.Append(HtmlEncodeAndReplaceLineBreaks(line))
|
|
||||||
.AppendLine("</code></div>");
|
|
||||||
}
|
|
||||||
|
|
||||||
var numErrorLines = 1 + Math.Max(0, endLine - startLine);
|
|
||||||
foreach (var line in fileContent.Skip(startLine).Take(numErrorLines))
|
|
||||||
{
|
|
||||||
builder.Append(@"<div class=""line error"">")
|
|
||||||
.AppendFormat(@"<span class=""line-number"">{0}</span><code>", index++)
|
|
||||||
.Append(HtmlEncodeAndReplaceLineBreaks(line))
|
|
||||||
.AppendLine("</code></div>");
|
|
||||||
}
|
|
||||||
foreach (var line in fileContent.Skip(message.EndLine).Take(NumContextLines))
|
|
||||||
{
|
|
||||||
builder.Append(@"<div class=""line faded"">")
|
|
||||||
.AppendFormat(@"<span class=""line-number"">{0}</span><code>", index++)
|
|
||||||
.Append(HtmlEncodeAndReplaceLineBreaks(line))
|
|
||||||
.AppendLine("</code></div>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.AppendLine("</div>"); // Close codeSnippet div
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetResourceString(string name, bool escapeBraces = false)
|
private static string GetResourceString(string name, bool escapeBraces = false)
|
||||||
{
|
{
|
||||||
// '{' and '}' are special in CSS, so we use "[[[0]]]" instead for {0} (and so on).
|
// '{' and '}' are special in CSS, so we use "[[[0]]]" instead for {0} (and so on).
|
||||||
|
|
@ -451,7 +346,7 @@ namespace Microsoft.AspNet.Hosting.Startup
|
||||||
stackTraceBuilder);
|
stackTraceBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteRawExceptionDetails(string linkText, IEnumerable<string> lines, StringBuilder rawExceptionDetails)
|
private static void WriteRawExceptionDetails(string linkText, string line, StringBuilder rawExceptionDetails)
|
||||||
{
|
{
|
||||||
rawExceptionDetails
|
rawExceptionDetails
|
||||||
.AppendLine("<div class=\"rawExceptionBlock\">")
|
.AppendLine("<div class=\"rawExceptionBlock\">")
|
||||||
|
|
@ -460,10 +355,7 @@ namespace Microsoft.AspNet.Hosting.Startup
|
||||||
.AppendLine(" <div id=\"rawException\">")
|
.AppendLine(" <div id=\"rawException\">")
|
||||||
.Append(" <pre>");
|
.Append(" <pre>");
|
||||||
|
|
||||||
foreach (var line in lines)
|
rawExceptionDetails.AppendLine(line);
|
||||||
{
|
|
||||||
rawExceptionDetails.AppendLine(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
rawExceptionDetails
|
rawExceptionDetails
|
||||||
.AppendLine("</pre>")
|
.AppendLine("</pre>")
|
||||||
|
|
@ -471,34 +363,6 @@ namespace Microsoft.AspNet.Hosting.Startup
|
||||||
.AppendLine("</div>");
|
.AppendLine("</div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteException(ICompilationException compilationException,
|
|
||||||
StringBuilder builder,
|
|
||||||
ref bool wasSourceCodeWrittenOntoPage)
|
|
||||||
{
|
|
||||||
var totalErrorsShown = 0;
|
|
||||||
var inlineSourceDiv = new StringBuilder();
|
|
||||||
var firstStackFrame = true;
|
|
||||||
foreach (var failure in compilationException.CompilationFailures)
|
|
||||||
{
|
|
||||||
if (firstStackFrame)
|
|
||||||
{
|
|
||||||
firstStackFrame = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inlineSourceDiv.AppendLine("<br/>");
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildCodeSnippetDiv(failure, inlineSourceDiv, ref totalErrorsShown);
|
|
||||||
}
|
|
||||||
|
|
||||||
wasSourceCodeWrittenOntoPage = totalErrorsShown > 0;
|
|
||||||
|
|
||||||
builder.AppendFormat(CultureInfo.InvariantCulture,
|
|
||||||
_compilationExceptionFormatString,
|
|
||||||
inlineSourceDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteMessage(string message, StringBuilder builder)
|
private static void WriteMessage(string message, StringBuilder builder)
|
||||||
{
|
{
|
||||||
// Build the <div>
|
// Build the <div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
<div class="message">
|
|
||||||
<span class="light exception">One or more compilation errors occurred:</span><br />
|
|
||||||
<div class="stacktrace">
|
|
||||||
{0}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
@ -75,11 +75,6 @@
|
||||||
background-color: #f6f6f6;
|
background-color: #f6f6f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.codeSnippet .error-message {
|
|
||||||
color: red;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.codeSnippet div.filename {
|
.codeSnippet div.filename {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
"Microsoft.Extensions.Configuration.Json": "1.0.0-*",
|
"Microsoft.Extensions.Configuration.Json": "1.0.0-*",
|
||||||
"Microsoft.Extensions.DependencyInjection": "1.0.0-*",
|
"Microsoft.Extensions.DependencyInjection": "1.0.0-*",
|
||||||
"Microsoft.Extensions.Logging": "1.0.0-*",
|
"Microsoft.Extensions.Logging": "1.0.0-*",
|
||||||
"Microsoft.Extensions.CompilationAbstractions": "1.0.0-*",
|
|
||||||
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-*",
|
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-*",
|
||||||
"System.Diagnostics.DiagnosticSource": "4.0.0-*"
|
"System.Diagnostics.DiagnosticSource": "4.0.0-*"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue