diff --git a/DiagnosticsPages.sln b/DiagnosticsPages.sln index 31ddf911b2..2b442e391a 100644 --- a/DiagnosticsPages.sln +++ b/DiagnosticsPages.sln @@ -12,8 +12,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Diagno EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "DeveloperExceptionPageSample", "samples\DeveloperExceptionPageSample\DeveloperExceptionPageSample.xproj", "{589AC17F-9455-4764-8F82-FCD2AE58DA14}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PageGenerator", "tools\PageGenerator\PageGenerator.xproj", "{4D4A785A-ECB9-4916-A88F-0FD306EE3B74}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F0557697-8D86-4DF3-A385-B0BFA9596189}" ProjectSection(SolutionItems) = preProject global.json = global.json @@ -51,7 +49,7 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Diagno EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.DiagnosticsViewPage.Sources", "src\Microsoft.AspNetCore.DiagnosticsViewPage.Sources\Microsoft.AspNetCore.DiagnosticsViewPage.Sources.xproj", "{B9F08060-621F-4E1F-BDA8-9C4EA107E08A}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{B9729160-50A4-49C5-8BB2-4944492AEA30}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ClassLibraryWithPortablePdbs", "test\ClassLibraryWithPortablePdbs\ClassLibraryWithPortablePdbs.xproj", "{AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -93,16 +91,6 @@ Global {589AC17F-9455-4764-8F82-FCD2AE58DA14}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {589AC17F-9455-4764-8F82-FCD2AE58DA14}.Release|Mixed Platforms.Build.0 = Release|Any CPU {589AC17F-9455-4764-8F82-FCD2AE58DA14}.Release|x86.ActiveCfg = Release|Any CPU - {4D4A785A-ECB9-4916-A88F-0FD306EE3B74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D4A785A-ECB9-4916-A88F-0FD306EE3B74}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D4A785A-ECB9-4916-A88F-0FD306EE3B74}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {4D4A785A-ECB9-4916-A88F-0FD306EE3B74}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {4D4A785A-ECB9-4916-A88F-0FD306EE3B74}.Debug|x86.ActiveCfg = Debug|Any CPU - {4D4A785A-ECB9-4916-A88F-0FD306EE3B74}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D4A785A-ECB9-4916-A88F-0FD306EE3B74}.Release|Any CPU.Build.0 = Release|Any CPU - {4D4A785A-ECB9-4916-A88F-0FD306EE3B74}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {4D4A785A-ECB9-4916-A88F-0FD306EE3B74}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {4D4A785A-ECB9-4916-A88F-0FD306EE3B74}.Release|x86.ActiveCfg = Release|Any CPU {994351B4-7B2A-4139-8B72-72C5BB5CC618}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {994351B4-7B2A-4139-8B72-72C5BB5CC618}.Debug|Any CPU.Build.0 = Debug|Any CPU {994351B4-7B2A-4139-8B72-72C5BB5CC618}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -279,6 +267,18 @@ Global {B9F08060-621F-4E1F-BDA8-9C4EA107E08A}.Release|Mixed Platforms.Build.0 = Release|Any CPU {B9F08060-621F-4E1F-BDA8-9C4EA107E08A}.Release|x86.ActiveCfg = Release|Any CPU {B9F08060-621F-4E1F-BDA8-9C4EA107E08A}.Release|x86.Build.0 = Release|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|x86.ActiveCfg = Debug|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Debug|x86.Build.0 = Debug|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|Any CPU.Build.0 = Release|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|x86.ActiveCfg = Release|Any CPU + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -287,7 +287,6 @@ Global {C5F59CBA-DF2D-4983-8CBB-11B6AF21B416} = {ACAA0157-A8C4-4152-93DE-90CCDF304087} {68A1F0E1-ECCE-46D1-B20F-C43EE5B097DE} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D} {589AC17F-9455-4764-8F82-FCD2AE58DA14} = {ACAA0157-A8C4-4152-93DE-90CCDF304087} - {4D4A785A-ECB9-4916-A88F-0FD306EE3B74} = {B9729160-50A4-49C5-8BB2-4944492AEA30} {994351B4-7B2A-4139-8B72-72C5BB5CC618} = {2AF90579-B118-4583-AE88-672EFACB5BC4} {427CDB36-78B0-4583-9EBC-7F283DE60355} = {ACAA0157-A8C4-4152-93DE-90CCDF304087} {4F5A6A72-FFE4-49C4-B4C6-58132CFCB9FE} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D} @@ -303,5 +302,6 @@ Global {B0166AED-738F-42EE-AF4D-C487C8B21521} = {2AF90579-B118-4583-AE88-672EFACB5BC4} {BFDFE1E3-A6A9-4DAB-8939-1DA306FC69C8} = {2AF90579-B118-4583-AE88-672EFACB5BC4} {B9F08060-621F-4E1F-BDA8-9C4EA107E08A} = {509A6F36-AD80-4A18-B5B1-717D38DFF29D} + {AA3661A1-CE8D-4597-ADFD-A5A30834E5D0} = {2AF90579-B118-4583-AE88-672EFACB5BC4} EndGlobalSection EndGlobal diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/ElmPageMiddleware.cs b/src/Microsoft.AspNetCore.Diagnostics.Elm/ElmPageMiddleware.cs index 3acce7f05a..63dffd492f 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.Elm/ElmPageMiddleware.cs +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/ElmPageMiddleware.cs @@ -3,9 +3,8 @@ using System; using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Diagnostics.Elm.Views; +using Microsoft.AspNetCore.Diagnostics.Elm.RazorViews; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Linq; diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPage.Designer.cs b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPage.Designer.cs new file mode 100644 index 0000000000..0dde472543 --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPage.Designer.cs @@ -0,0 +1,606 @@ +namespace Microsoft.AspNetCore.Diagnostics.Elm.RazorViews +{ +#line 1 "DetailsPage.cshtml" +using System + +#line default +#line hidden + ; +#line 2 "DetailsPage.cshtml" +using System.Globalization + +#line default +#line hidden + ; +#line 3 "DetailsPage.cshtml" +using System.Linq + +#line default +#line hidden + ; +#line 4 "DetailsPage.cshtml" +using Microsoft.AspNetCore.Diagnostics.Elm + +#line default +#line hidden + ; +#line 5 "DetailsPage.cshtml" +using Microsoft.AspNetCore.Diagnostics.Elm.RazorViews + +#line default +#line hidden + ; +#line 6 "DetailsPage.cshtml" +using Microsoft.Extensions.RazorViews + +#line default +#line hidden + ; +#line 7 "DetailsPage.cshtml" +using Microsoft.Extensions.Logging + +#line default +#line hidden + ; + using System.Threading.Tasks; + + internal class DetailsPage : Microsoft.Extensions.RazorViews.BaseView + { +#line 10 "DetailsPage.cshtml" + + public DetailsPage(DetailsPageModel model) + { + Model = model; + } + + public DetailsPageModel Model { get; set; } + + public HelperResult LogRow(LogInfo log) + { + return new HelperResult((writer) => + { + if (log.Severity >= Model.Options.MinLevel && + (string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal))) + { + WriteLiteralTo(writer, " \r\n "); + WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time)); + WriteLiteralTo(writer, "\r\n "); + WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time)); + var severity = log.Severity.ToString().ToLowerInvariant(); + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Severity); + + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Name); + + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Message); + + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Exception); + + WriteLiteralTo(writer, "\r\n \r\n"); + } + }); + } + + public HelperResult Traverse(ScopeNode node) + { + return new HelperResult((writer) => + { + var messageIndex = 0; + var childIndex = 0; + while (messageIndex < node.Messages.Count && childIndex < node.Children.Count) + { + if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime) + { + LogRow(node.Messages[messageIndex]); + messageIndex++; + } + else + { + Traverse(node.Children[childIndex]); + childIndex++; + } + } + if (messageIndex < node.Messages.Count) + { + for (var i = messageIndex; i < node.Messages.Count; i++) + { + LogRow(node.Messages[i]); + } + } + else + { + for (var i = childIndex; i < node.Children.Count; i++) + { + Traverse(node.Children[i]); + } + } + }); + } + +#line default +#line hidden + #line hidden + public DetailsPage() + { + } + + #pragma warning disable 1998 + public override async Task ExecuteAsync() + { + WriteLiteral("\r\n"); +#line 84 "DetailsPage.cshtml" + + Response.ContentType = "text/html; charset=utf-8"; + +#line default +#line hidden + + WriteLiteral(@" + + + + ASP.NET Core Logs + + + + +

ASP.NET Core Logs

+"); +#line 192 "DetailsPage.cshtml" + + +#line default +#line hidden + +#line 192 "DetailsPage.cshtml" + + var context = Model.Activity?.HttpInfo; + + +#line default +#line hidden + + WriteLiteral(" "); +#line 195 "DetailsPage.cshtml" + if (context != null) + { + +#line default +#line hidden + + WriteLiteral("

Request Details

\r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n + + + + \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Path"); +#line 203 "DetailsPage.cshtml" + Write(context.Path); + +#line default +#line hidden + WriteLiteral("
Host"); +#line 207 "DetailsPage.cshtml" + Write(context.Host); + +#line default +#line hidden + WriteLiteral("
Content Type"); +#line 211 "DetailsPage.cshtml" + Write(context.ContentType); + +#line default +#line hidden + WriteLiteral("
Method"); +#line 215 "DetailsPage.cshtml" + Write(context.Method); + +#line default +#line hidden + WriteLiteral("
Protocol"); +#line 219 "DetailsPage.cshtml" + Write(context.Protocol); + +#line default +#line hidden + WriteLiteral(@"
Headers + + + + + + + + +"); +#line 232 "DetailsPage.cshtml" + + +#line default +#line hidden + +#line 232 "DetailsPage.cshtml" + foreach (var header in context.Headers) + { + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n \r\n \r\n"); +#line 238 "DetailsPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral(" \r\n
VariableValue
"); +#line 235 "DetailsPage.cshtml" + Write(header.Key); + +#line default +#line hidden + WriteLiteral(""); +#line 236 "DetailsPage.cshtml" + Write(string.Join(";", header.Value)); + +#line default +#line hidden + WriteLiteral("
\r\n
Status Code"); +#line 245 "DetailsPage.cshtml" + Write(context.StatusCode); + +#line default +#line hidden + WriteLiteral("
User"); +#line 249 "DetailsPage.cshtml" + Write(context.User.Identity.Name); + +#line default +#line hidden + WriteLiteral("
Claims\r\n"); +#line 254 "DetailsPage.cshtml" + + +#line default +#line hidden + +#line 254 "DetailsPage.cshtml" + if (context.User.Claims.Any()) + { + +#line default +#line hidden + + WriteLiteral(@" + + + + + + + +"); +#line 264 "DetailsPage.cshtml" + + +#line default +#line hidden + +#line 264 "DetailsPage.cshtml" + foreach (var claim in context.User.Claims) + { + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n \r\n \r\n"); +#line 270 "DetailsPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral(" \r\n
IssuerValue
"); +#line 267 "DetailsPage.cshtml" + Write(claim.Issuer); + +#line default +#line hidden + WriteLiteral(""); +#line 268 "DetailsPage.cshtml" + Write(claim.Value); + +#line default +#line hidden + WriteLiteral("
\r\n"); +#line 273 "DetailsPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral("
Scheme"); +#line 278 "DetailsPage.cshtml" + Write(context.Scheme); + +#line default +#line hidden + WriteLiteral("
Query"); +#line 282 "DetailsPage.cshtml" + Write(context.Query.Value); + +#line default +#line hidden + WriteLiteral("
Cookies\r\n"); +#line 287 "DetailsPage.cshtml" + + +#line default +#line hidden + +#line 287 "DetailsPage.cshtml" + if (context.Cookies.Any()) + { + +#line default +#line hidden + + WriteLiteral(@" + + + + + + + +"); +#line 297 "DetailsPage.cshtml" + + +#line default +#line hidden + +#line 297 "DetailsPage.cshtml" + foreach (var cookie in context.Cookies) + { + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n \r\n \r\n"); +#line 303 "DetailsPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral(" \r\n
VariableValue
"); +#line 300 "DetailsPage.cshtml" + Write(cookie.Key); + +#line default +#line hidden + WriteLiteral(""); +#line 301 "DetailsPage.cshtml" + Write(string.Join(";", cookie.Value)); + +#line default +#line hidden + WriteLiteral("
\r\n"); +#line 306 "DetailsPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral("
\r\n"); +#line 310 "DetailsPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral("

Logs

\r\n
\r\n \r\n + +
+ + + + + + + + + + + + "); +#line 341 "DetailsPage.cshtml" + Write(Traverse(Model.Activity.Root)); + +#line default +#line hidden + WriteLiteral(@" +
DateTimeSeverityNameStateError
+ + +"); + } + #pragma warning restore 1998 + } +} diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPage.cshtml b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPage.cshtml index db56b731e1..f0519b8fee 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPage.cshtml +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPage.cshtml @@ -2,8 +2,8 @@ @using System.Globalization @using System.Linq @using Microsoft.AspNetCore.Diagnostics.Elm -@using Microsoft.AspNetCore.Diagnostics.Elm.Views -@using Microsoft.AspNetCore.DiagnosticsViewPage.Views +@using Microsoft.AspNetCore.Diagnostics.Elm.RazorViews +@using Microsoft.Extensions.RazorViews @using Microsoft.Extensions.Logging @functions @@ -82,7 +82,7 @@ } } @{ - Response.ContentType = "text/html"; + Response.ContentType = "text/html; charset=utf-8"; } @@ -91,7 +91,7 @@ ASP.NET Core Logs diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPageModel.cs b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPageModel.cs index 19304a5e43..1b9c2a64b0 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPageModel.cs +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPageModel.cs @@ -1,6 +1,6 @@ using System; -namespace Microsoft.AspNetCore.Diagnostics.Elm.Views +namespace Microsoft.AspNetCore.Diagnostics.Elm.RazorViews { public class DetailsPageModel { diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPage.Designer.cs b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPage.Designer.cs new file mode 100644 index 0000000000..1fa50b2f58 --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPage.Designer.cs @@ -0,0 +1,710 @@ +namespace Microsoft.AspNetCore.Diagnostics.Elm.RazorViews +{ +#line 1 "LogPage.cshtml" +using System + +#line default +#line hidden + ; +#line 2 "LogPage.cshtml" +using System.Collections.Generic + +#line default +#line hidden + ; +#line 3 "LogPage.cshtml" +using System.Globalization + +#line default +#line hidden + ; +#line 4 "LogPage.cshtml" +using System.Linq + +#line default +#line hidden + ; +#line 5 "LogPage.cshtml" +using Microsoft.AspNetCore.Diagnostics.Elm + +#line default +#line hidden + ; +#line 6 "LogPage.cshtml" +using Microsoft.AspNetCore.Diagnostics.Elm.RazorViews + +#line default +#line hidden + ; +#line 7 "LogPage.cshtml" +using Microsoft.Extensions.RazorViews + +#line default +#line hidden + ; +#line 8 "LogPage.cshtml" +using Microsoft.Extensions.Logging + +#line default +#line hidden + ; + using System.Threading.Tasks; + + internal class LogPage : Microsoft.Extensions.RazorViews.BaseView + { +#line 11 "LogPage.cshtml" + + public LogPage(LogPageModel model) + { + Model = model; + } + + public LogPageModel Model { get; set; } + + public HelperResult LogRow(LogInfo log, int level) + { + return new HelperResult((writer) => + { + if (log.Severity >= Model.Options.MinLevel && + (string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal))) + { + + WriteLiteralTo(writer, " \r\n "); + WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time)); + + WriteLiteralTo(writer, "\r\n "); + WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time)); + + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Name); + var severity = log.Severity.ToString().ToLowerInvariant(); + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Severity); + + WriteLiteralTo(writer, $"\r\n \r\n"); + + for (var i = 0; i < level; i++) + { + WriteLiteralTo(writer, " \r\n"); + } + + WriteLiteralTo(writer, " "); + WriteTo(writer, log.Message); + + WriteLiteralTo(writer, $"\r\n \r\n "); + + WriteTo(writer, log.Exception); + + WriteLiteralTo(writer, "\r\n \r\n"); + + } + }); + } + + public HelperResult Traverse(ScopeNode node, int level, Dictionary counts) + { + return new HelperResult((writer) => { + // print start of scope + WriteTo(writer, LogRow(new LogInfo() + { + Name = node.Name, + Time = node.StartTime, + Severity = LogLevel.Debug, + Message = "Beginning " + node.State, + }, level)); + + var messageIndex = 0; + var childIndex = 0; + while (messageIndex < node.Messages.Count && childIndex < node.Children.Count) + { + if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime) + { + WriteTo(writer, LogRow(node.Messages[messageIndex], level)); + + counts[node.Messages[messageIndex].Severity.ToString()]++; + messageIndex++; + } + else + { + WriteTo(writer, Traverse(node.Children[childIndex], level + 1, counts)); + childIndex++; + } + } + if (messageIndex < node.Messages.Count) + { + for (var i = messageIndex; i < node.Messages.Count; i++) + { + WriteTo(writer, LogRow(node.Messages[i], level)); + counts[node.Messages[i].Severity.ToString()]++; + } + } + else + { + for (var i = childIndex; i < node.Children.Count; i++) + { + WriteTo(writer, Traverse(node.Children[i], level + 1, counts)); + } + } + // print end of scope + WriteTo(writer, LogRow(new LogInfo() + { + Name = node.Name, + Time = node.EndTime, + Severity = LogLevel.Debug, + Message = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime) + }, level)); + }); + } + +#line default +#line hidden + #line hidden + public LogPage() + { + } + + #pragma warning disable 1998 + public override async Task ExecuteAsync() + { + WriteLiteral("\r\n"); +#line 114 "LogPage.cshtml" + + Response.ContentType = "text/html; charset=utf-8"; + +#line default +#line hidden + + WriteLiteral(@" + + + + + ASP.NET Core Logs + + \r\n\r\n\r\n

ASP.NET Core Logs

\r\n
\r\n \r\n + +
+
+ +
+ + + + + + + + + + + + + + + + + + +"); +#line 317 "LogPage.cshtml" + + +#line default +#line hidden + +#line 317 "LogPage.cshtml" + foreach (var activity in Model.Activities.Reverse()) + { + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n"); +#line 321 "LogPage.cshtml" + + +#line default +#line hidden + +#line 321 "LogPage.cshtml" + + var activityPath = Model.Path.Value + "/" + activity.Id; + if (activity.HttpInfo != null) + { + +#line default +#line hidden + + WriteLiteral(" \t\r\n \r\n \r\n \r\n"); +#line 329 "LogPage.cshtml" + } + else if (activity.RepresentsScope) + { + +#line default +#line hidden + + WriteLiteral(" \r\n"); +#line 333 "LogPage.cshtml" + } + else + { + +#line default +#line hidden + + WriteLiteral(" \r\n"); +#line 337 "LogPage.cshtml" + } + + +#line default +#line hidden + + WriteLiteral(@" \r\n \r\n \r\n"); +#line 391 "LogPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral(@"
PathMethodHostStatus CodeLogs
"); +#line 326 "LogPage.cshtml" + Write(activity.HttpInfo.Method); + +#line default +#line hidden + WriteLiteral(""); +#line 327 "LogPage.cshtml" + Write(activity.HttpInfo.Host); + +#line default +#line hidden + WriteLiteral(""); +#line 328 "LogPage.cshtml" + Write(activity.HttpInfo.StatusCode); + +#line default +#line hidden + WriteLiteral(" + + + + + + + + + + + +"); +#line 351 "LogPage.cshtml" + + +#line default +#line hidden + +#line 351 "LogPage.cshtml" + + var counts = new Dictionary(); + counts["Critical"] = 0; + counts["Error"] = 0; + counts["Warning"] = 0; + counts["Information"] = 0; + counts["Debug"] = 0; + + +#line default +#line hidden + + WriteLiteral(" \r\n"); +#line 360 "LogPage.cshtml" + + +#line default +#line hidden + +#line 360 "LogPage.cshtml" + if (!activity.RepresentsScope) + { + // message not within a scope + var logInfo = activity.Root.Messages.FirstOrDefault(); + + +#line default +#line hidden + +#line 364 "LogPage.cshtml" + Write(LogRow(logInfo, 0)); + +#line default +#line hidden +#line 364 "LogPage.cshtml" + + counts[logInfo.Severity.ToString()] = 1; + } + else + { + + +#line default +#line hidden + +#line 369 "LogPage.cshtml" + Write(Traverse(activity.Root, 0, counts)); + +#line default +#line hidden +#line 369 "LogPage.cshtml" + + } + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n \r\n \r\n"); +#line 375 "LogPage.cshtml" + + +#line default +#line hidden + +#line 375 "LogPage.cshtml" + foreach (var kvp in counts) + { + if (string.Equals("Debug", kvp.Key)) { + +#line default +#line hidden + + WriteLiteral(" \r\n"); +#line 379 "LogPage.cshtml" + } + else + { + +#line default +#line hidden + + WriteLiteral(" \r\n"); +#line 383 "LogPage.cshtml" + } + } + +#line default +#line hidden + + WriteLiteral(" \r\n \r\n
DateTimeNameSeverityStateError^
"); +#line 374 "LogPage.cshtml" + Write(activity.Time.ToString("MM-dd-yyyy HH:mm:ss")); + +#line default +#line hidden + WriteLiteral(""); +#line 378 "LogPage.cshtml" + Write(kvp.Value); + +#line default +#line hidden + WriteLiteral(" "); +#line 378 "LogPage.cshtml" + Write(kvp.Key); + +#line default +#line hidden + WriteLiteral("v"); +#line 382 "LogPage.cshtml" + Write(kvp.Value); + +#line default +#line hidden + WriteLiteral(" "); +#line 382 "LogPage.cshtml" + Write(kvp.Key); + +#line default +#line hidden + WriteLiteral("
\r\n
+ + +"); + } + #pragma warning restore 1998 + } +} diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPage.cshtml b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPage.cshtml index b8e356df46..870a3579c5 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPage.cshtml +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPage.cshtml @@ -3,8 +3,8 @@ @using System.Globalization @using System.Linq @using Microsoft.AspNetCore.Diagnostics.Elm -@using Microsoft.AspNetCore.Diagnostics.Elm.Views -@using Microsoft.AspNetCore.DiagnosticsViewPage.Views +@using Microsoft.AspNetCore.Diagnostics.Elm.RazorViews +@using Microsoft.Extensions.RazorViews @using Microsoft.Extensions.Logging @functions @@ -111,8 +111,8 @@ }); } } -@{ - Response.ContentType = "text/html"; +@{ + Response.ContentType = "text/html; charset=utf-8"; } @@ -205,7 +205,7 @@ var counts = new Dictionary(); counts["Critical"] = 0; counts["Error"] = 0; - counts["Warning"] = 0; + counts["Warning"] = 0; counts["Information"] = 0; counts["Debug"] = 0; } diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPageModel.cs b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPageModel.cs index f60b04fb44..46c20d9689 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPageModel.cs +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPageModel.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNetCore.Diagnostics.Elm.Views +namespace Microsoft.AspNetCore.Diagnostics.Elm.RazorViews { public class LogPageModel { diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPage.cs b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPage.cs similarity index 99% rename from src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPage.cs rename to src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPage.cs index dc0085f892..df09b8eca9 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/DetailsPage.cs +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPage.cs @@ -43,7 +43,7 @@ using Microsoft.Extensions.Logging #line hidden ; using System.Threading.Tasks; - + [Obsolete("This type is for internal use only and will be removed in a future version.")] public class DetailsPage : Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView { #line 10 "DetailsPage.cshtml" diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPage.cshtml b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPage.cshtml new file mode 100644 index 0000000000..db56b731e1 --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPage.cshtml @@ -0,0 +1,258 @@ +@using System +@using System.Globalization +@using System.Linq +@using Microsoft.AspNetCore.Diagnostics.Elm +@using Microsoft.AspNetCore.Diagnostics.Elm.Views +@using Microsoft.AspNetCore.DiagnosticsViewPage.Views +@using Microsoft.Extensions.Logging + +@functions +{ + public DetailsPage(DetailsPageModel model) + { + Model = model; + } + + public DetailsPageModel Model { get; set; } + + public HelperResult LogRow(LogInfo log) + { + return new HelperResult((writer) => + { + if (log.Severity >= Model.Options.MinLevel && + (string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal))) + { + WriteLiteralTo(writer, " \r\n "); + WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time)); + WriteLiteralTo(writer, "\r\n "); + WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time)); + var severity = log.Severity.ToString().ToLowerInvariant(); + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Severity); + + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Name); + + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Message); + + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Exception); + + WriteLiteralTo(writer, "\r\n \r\n"); + } + }); + } + + public HelperResult Traverse(ScopeNode node) + { + return new HelperResult((writer) => + { + var messageIndex = 0; + var childIndex = 0; + while (messageIndex < node.Messages.Count && childIndex < node.Children.Count) + { + if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime) + { + LogRow(node.Messages[messageIndex]); + messageIndex++; + } + else + { + Traverse(node.Children[childIndex]); + childIndex++; + } + } + if (messageIndex < node.Messages.Count) + { + for (var i = messageIndex; i < node.Messages.Count; i++) + { + LogRow(node.Messages[i]); + } + } + else + { + for (var i = childIndex; i < node.Children.Count; i++) + { + Traverse(node.Children[i]); + } + } + }); + } +} +@{ + Response.ContentType = "text/html"; +} + + + + + ASP.NET Core Logs + + + + +

ASP.NET Core Logs

+ @{ + var context = Model.Activity?.HttpInfo; + } + @if (context != null) + { +

Request Details

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Path@context.Path
Host@context.Host
Content Type@context.ContentType
Method@context.Method
Protocol@context.Protocol
Headers + + + + + + + + + @foreach (var header in context.Headers) + { + + + + + } + +
VariableValue
@header.Key@string.Join(";", header.Value)
+
Status Code@context.StatusCode
User@context.User.Identity.Name
Claims + @if (context.User.Claims.Any()) + { + + + + + + + + + @foreach (var claim in context.User.Claims) + { + + + + + } + +
IssuerValue
@claim.Issuer@claim.Value
+ } +
Scheme@context.Scheme
Query@context.Query.Value
Cookies + @if (context.Cookies.Any()) + { + + + + + + + + + @foreach (var cookie in context.Cookies) + { + + + + + } + +
VariableValue
@cookie.Key@string.Join(";", cookie.Value)
+ } +
+ } +

Logs

+
+ + + +
+ + + + + + + + + + + + @Traverse(Model.Activity.Root) +
DateTimeSeverityNameStateError
+ + + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPage.css b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPage.css new file mode 100644 index 0000000000..d0803ebf3f --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPage.css @@ -0,0 +1,56 @@ +body { + font-size: 0.9em; + width: 90%; + margin: 0px auto; +} + +h1 { + padding-bottom: 10px; +} + +h2 { + font-weight: normal; +} + +table { + border-spacing: 0px; + width: 100%; + border-collapse: collapse; + border: 1px solid black; + white-space: pre-wrap; +} + +th { + font-family: Arial; +} + +td, th { + padding: 8px; +} + +#headerTable, #cookieTable { + border: none; + height: 100%; +} + +#headerTd { + white-space: normal; +} + +#label { + width: 20%; + border-right: 1px solid black; +} + +#logs{ + margin-top: 10px; + margin-bottom: 20px; +} + +#logs>tbody>tr>td { + border-right: 1px dashed lightgray; +} + +#logs>thead>tr>th { + border: 1px solid black; +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPageModel.cs b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPageModel.cs new file mode 100644 index 0000000000..5ae8e15579 --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/DetailsPageModel.cs @@ -0,0 +1,12 @@ +using System; + +namespace Microsoft.AspNetCore.Diagnostics.Elm.Views +{ + [Obsolete("This type is for internal use only and will be removed in a future version.")] + public class DetailsPageModel + { + public ActivityContext Activity { get; set; } + + public ViewOptions Options { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPage.cs b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPage.cs similarity index 99% rename from src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPage.cs rename to src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPage.cs index 21a46aed52..4108ebe4db 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/LogPage.cs +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPage.cs @@ -49,7 +49,7 @@ using Microsoft.Extensions.Logging #line hidden ; using System.Threading.Tasks; - + [Obsolete("This type is for internal use only and will be removed in a future version.")] public class LogPage : Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView { #line 11 "LogPage.cshtml" diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPage.cshtml b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPage.cshtml new file mode 100644 index 0000000000..b8e356df46 --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPage.cshtml @@ -0,0 +1,263 @@ +@using System +@using System.Collections.Generic +@using System.Globalization +@using System.Linq +@using Microsoft.AspNetCore.Diagnostics.Elm +@using Microsoft.AspNetCore.Diagnostics.Elm.Views +@using Microsoft.AspNetCore.DiagnosticsViewPage.Views +@using Microsoft.Extensions.Logging + +@functions +{ + public LogPage(LogPageModel model) + { + Model = model; + } + + public LogPageModel Model { get; set; } + + public HelperResult LogRow(LogInfo log, int level) + { + return new HelperResult((writer) => + { + if (log.Severity >= Model.Options.MinLevel && + (string.IsNullOrEmpty(Model.Options.NamePrefix) || log.Name.StartsWith(Model.Options.NamePrefix, StringComparison.Ordinal))) + { + + WriteLiteralTo(writer, " \r\n "); + WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time)); + + WriteLiteralTo(writer, "\r\n "); + WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time)); + + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Name); + var severity = log.Severity.ToString().ToLowerInvariant(); + WriteLiteralTo(writer, $"\r\n "); + WriteTo(writer, log.Severity); + + WriteLiteralTo(writer, $"\r\n \r\n"); + + for (var i = 0; i < level; i++) + { + WriteLiteralTo(writer, " \r\n"); + } + + WriteLiteralTo(writer, " "); + WriteTo(writer, log.Message); + + WriteLiteralTo(writer, $"\r\n \r\n "); + + WriteTo(writer, log.Exception); + + WriteLiteralTo(writer, "\r\n \r\n"); + + } + }); + } + + public HelperResult Traverse(ScopeNode node, int level, Dictionary counts) + { + return new HelperResult((writer) => { + // print start of scope + WriteTo(writer, LogRow(new LogInfo() + { + Name = node.Name, + Time = node.StartTime, + Severity = LogLevel.Debug, + Message = "Beginning " + node.State, + }, level)); + + var messageIndex = 0; + var childIndex = 0; + while (messageIndex < node.Messages.Count && childIndex < node.Children.Count) + { + if (node.Messages[messageIndex].Time < node.Children[childIndex].StartTime) + { + WriteTo(writer, LogRow(node.Messages[messageIndex], level)); + + counts[node.Messages[messageIndex].Severity.ToString()]++; + messageIndex++; + } + else + { + WriteTo(writer, Traverse(node.Children[childIndex], level + 1, counts)); + childIndex++; + } + } + if (messageIndex < node.Messages.Count) + { + for (var i = messageIndex; i < node.Messages.Count; i++) + { + WriteTo(writer, LogRow(node.Messages[i], level)); + counts[node.Messages[i].Severity.ToString()]++; + } + } + else + { + for (var i = childIndex; i < node.Children.Count; i++) + { + WriteTo(writer, Traverse(node.Children[i], level + 1, counts)); + } + } + // print end of scope + WriteTo(writer, LogRow(new LogInfo() + { + Name = node.Name, + Time = node.EndTime, + Severity = LogLevel.Debug, + Message = string.Format("Completed {0} in {1}ms", node.State, node.EndTime - node.StartTime) + }, level)); + }); + } +} +@{ + Response.ContentType = "text/html"; +} + + + + + + ASP.NET Core Logs + + + + +

ASP.NET Core Logs

+
+ + + +
+
+ +
+ + + + + + + + + + + + + + + + + + + @foreach (var activity in Model.Activities.Reverse()) + { + + + @{ + var activityPath = Model.Path.Value + "/" + activity.Id; + if (activity.HttpInfo != null) + { + + + + + } + else if (activity.RepresentsScope) + { + + } + else + { + + } + } + + + + } +
PathMethodHostStatus CodeLogs
@activity.HttpInfo.Path@activity.HttpInfo.Method@activity.HttpInfo.Host@activity.HttpInfo.StatusCode@activity.Root.StateNon-scope Log + + + + + + + + + + + + @{ + var counts = new Dictionary(); + counts["Critical"] = 0; + counts["Error"] = 0; + counts["Warning"] = 0; + counts["Information"] = 0; + counts["Debug"] = 0; + } + + @if (!activity.RepresentsScope) + { + // message not within a scope + var logInfo = activity.Root.Messages.FirstOrDefault(); + @LogRow(logInfo, 0) + counts[logInfo.Severity.ToString()] = 1; + } + else + { + @Traverse(activity.Root, 0, counts) + } + + + + + @foreach (var kvp in counts) + { + if (string.Equals("Debug", kvp.Key)) { + + } + else + { + + } + } + + +
DateTimeNameSeverityStateError^
@activity.Time.ToString("MM-dd-yyyy HH:mm:ss")@kvp.Value @kvp.Keyv@kvp.Value @kvp.Key
+
+ + + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPage.css b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPage.css new file mode 100644 index 0000000000..420cc18121 --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPage.css @@ -0,0 +1,110 @@ +body { + font-size: .813em; + white-space: nowrap; + margin: 20px; +} + +col:nth-child(2n) { + background-color: #FAFAFA; +} + +form { + display: inline-block; +} + +h1 { + margin-left: 25px; +} + +table { + margin: 0px auto; + border-collapse: collapse; + border-spacing: 0px; + table-layout: fixed; + width: 100%; +} + +td, th { + padding: 4px; +} + +thead { + font-size: 1em; + font-family: Arial; +} + +tr { + height: 23px; +} + +#requestHeader { + border-bottom: solid 1px gray; + border-top: solid 1px gray; + margin-bottom: 2px; + font-size: 1em; + line-height: 2em; +} + +.collapse { + color: black; + float: right; + font-weight: normal; + width: 1em; +} + +.date, .time { + width: 70px; +} + +.logHeader { + border-bottom: 1px solid lightgray; + color: gray; + text-align: left; +} + +.logState { + text-overflow: ellipsis; + overflow: hidden; +} + +.logTd { + border-left: 1px solid gray; + padding: 0px; +} + +.logs { + width: 80%; +} + +.logRow:hover { + background-color: #D6F5FF; +} + +.requestRow>td { + border-bottom: solid 1px gray; +} + +.severity { + width: 80px; +} + +.summary { + color: black; + line-height: 1.8em; +} + +.summary>th { + font-weight: normal; +} + +.tab { + margin-left: 30px; +} + +#viewOptions { + margin: 20px; +} + +#viewOptions > * { + margin: 5px; +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPageModel.cs b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPageModel.cs new file mode 100644 index 0000000000..8041b21233 --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/LogPageModel.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Diagnostics.Elm.Views +{ + [Obsolete("This type is for internal use only and will be removed in a future version.")] + public class LogPageModel + { + public IEnumerable Activities { get; set; } + + public ViewOptions Options { get; set; } + + public PathString Path { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/Shared.css b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/Shared.css new file mode 100644 index 0000000000..18c14c10d1 --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/Views/Obsolete/Shared.css @@ -0,0 +1,39 @@ +body { + font-family: 'Segoe UI', Tahoma, Arial, Helvtica, sans-serif; + line-height: 1.4em; +} + +h1 { + font-family: 'Segoe UI', Helvetica, sans-serif; + font-size: 2.5em; +} + +td { + text-overflow: ellipsis; + overflow: hidden; +} + +tr:nth-child(2n) { + background-color: #F6F6F6; +} + +.critical { + background-color: red; + color: white; +} + +.error { + color: red; +} + +.information { + color: blue; +} + +.debug { + color: black; +} + +.warning { + color: orange; +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Diagnostics.Elm/project.json b/src/Microsoft.AspNetCore.Diagnostics.Elm/project.json index 7da8b4862e..7cf9b82cea 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.Elm/project.json +++ b/src/Microsoft.AspNetCore.Diagnostics.Elm/project.json @@ -24,10 +24,17 @@ "type": "build", "version": "1.1.0-*" }, + "Microsoft.Extensions.RazorViews.Sources": { + "type": "build", + "version": "1.1.0-*" + }, "Microsoft.AspNetCore.Http.Abstractions": "1.1.0-*", "Microsoft.Extensions.Logging.Abstractions": "1.1.0-*", "Microsoft.Extensions.Options": "1.1.0-*" }, + "tools": { + "RazorPageGenerator": "1.1.0-*" + }, "frameworks": { "net451": { "frameworkAssemblies": { diff --git a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/DatabaseErrorPageMiddleware.cs b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/DatabaseErrorPageMiddleware.cs index 4cb9ec39f4..297b3dc3ec 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/DatabaseErrorPageMiddleware.cs +++ b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/DatabaseErrorPageMiddleware.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Utilities; -using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views; +using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.RazorViews; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore /// Delegate to execute the next piece of middleware in the request pipeline. /// The to resolve services from. /// - /// The for the application. This middleware both produces logging messages and + /// The for the application. This middleware both produces logging messages and /// consumes them to detect database related exception. /// /// The options to control what information is displayed on the error page. diff --git a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Properties/AssemblyInfo.cs index e3ae91c58b..cc2655f392 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Properties/AssemblyInfo.cs +++ b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Properties/AssemblyInfo.cs @@ -3,7 +3,9 @@ using System.Reflection; using System.Resources; +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyCompany("Microsoft Corporation.")] diff --git a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPage.Designer.cs b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPage.Designer.cs new file mode 100644 index 0000000000..eb5626daa6 --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPage.Designer.cs @@ -0,0 +1,457 @@ +namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.RazorViews +{ +#line 1 "DatabaseErrorPage.cshtml" +using System + +#line default +#line hidden + ; +#line 2 "DatabaseErrorPage.cshtml" +using System.Linq + +#line default +#line hidden + ; +#line 3 "DatabaseErrorPage.cshtml" +using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore + +#line default +#line hidden + ; +#line 4 "DatabaseErrorPage.cshtml" +using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.RazorViews + +#line default +#line hidden + ; + using System.Threading.Tasks; + + internal class DatabaseErrorPage : Microsoft.Extensions.RazorViews.BaseView + { +#line 11 "DatabaseErrorPage.cshtml" + + public DatabaseErrorPageModel Model { get; set; } + + public string UrlEncode(string content) + { + return UrlEncoder.Encode(content); + } + + public string JavaScriptEncode(string content) + { + return JavaScriptEncoder.Encode(content); + } + +#line default +#line hidden + #line hidden + public DatabaseErrorPage() + { + } + + #pragma warning disable 1998 + public override async Task ExecuteAsync() + { +#line 5 "DatabaseErrorPage.cshtml" + + Response.StatusCode = 500; + Response.ContentType = "text/html; charset=utf-8"; + Response.ContentLength = null; // Clear any prior Content-Length + +#line default +#line hidden + + WriteLiteral(@" + + + + + Internal Server Error + + + +

"); +#line 113 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_Title); + +#line default +#line hidden + WriteLiteral("

\r\n

\r\n"); +#line 115 "DatabaseErrorPage.cshtml" + + +#line default +#line hidden + +#line 115 "DatabaseErrorPage.cshtml" + for (Exception ex = Model.Exception; ex != null; ex = ex.InnerException) + { + +#line default +#line hidden + + WriteLiteral(" "); +#line 117 "DatabaseErrorPage.cshtml" + Write(ex.GetType().Name); + +#line default +#line hidden + WriteLiteral(": "); +#line 117 "DatabaseErrorPage.cshtml" + Write(ex.Message); + +#line default +#line hidden + WriteLiteral("\r\n
\r\n"); +#line 119 "DatabaseErrorPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral("

\r\n
\r\n\r\n"); +#line 123 "DatabaseErrorPage.cshtml" + + +#line default +#line hidden + +#line 123 "DatabaseErrorPage.cshtml" + if (!Model.DatabaseExists && !Model.PendingMigrations.Any()) + { + +#line default +#line hidden + + WriteLiteral("

"); +#line 125 "DatabaseErrorPage.cshtml" + Write(Strings.FormatDatabaseErrorPage_NoDbOrMigrationsTitle(Model.ContextType.Name)); + +#line default +#line hidden + WriteLiteral("

\r\n

"); +#line 126 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_NoDbOrMigrationsInfoPMC); + +#line default +#line hidden + WriteLiteral("

\r\n "); +#line 127 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_AddMigrationCommandPMC); + +#line default +#line hidden + WriteLiteral("\r\n
\r\n "); +#line 129 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC); + +#line default +#line hidden + WriteLiteral("\r\n

"); +#line 130 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_NoDbOrMigrationsInfoCLI); + +#line default +#line hidden + WriteLiteral("

\r\n "); +#line 131 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_AddMigrationCommandCLI); + +#line default +#line hidden + WriteLiteral("\r\n
\r\n "); +#line 133 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI); + +#line default +#line hidden + WriteLiteral("\r\n
\r\n"); +#line 135 "DatabaseErrorPage.cshtml" + } + else if (Model.PendingMigrations.Any()) + { + +#line default +#line hidden + + WriteLiteral("
\r\n

"); +#line 139 "DatabaseErrorPage.cshtml" + Write(Strings.FormatDatabaseErrorPage_PendingMigrationsTitle(Model.ContextType.Name)); + +#line default +#line hidden + WriteLiteral("

\r\n

"); +#line 140 "DatabaseErrorPage.cshtml" + Write(Strings.FormatDatabaseErrorPage_PendingMigrationsInfo(Model.ContextType.Name)); + +#line default +#line hidden + WriteLiteral("

\r\n\r\n
    \r\n"); +#line 143 "DatabaseErrorPage.cshtml" + + +#line default +#line hidden + +#line 143 "DatabaseErrorPage.cshtml" + foreach (var migration in Model.PendingMigrations) + { + +#line default +#line hidden + + WriteLiteral("
  • "); +#line 145 "DatabaseErrorPage.cshtml" + Write(migration); + +#line default +#line hidden + WriteLiteral("
  • \r\n"); +#line 146 "DatabaseErrorPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral("
\r\n\r\n

\r\n + + +

+ \r\n\r\n

"); +#line 190 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_HowToApplyFromPMC); + +#line default +#line hidden + WriteLiteral("

\r\n "); +#line 191 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC); + +#line default +#line hidden + WriteLiteral("\r\n

"); +#line 192 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_HowToApplyFromCLI); + +#line default +#line hidden + WriteLiteral("

\r\n "); +#line 193 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI); + +#line default +#line hidden + WriteLiteral("\r\n
\r\n
\r\n"); +#line 196 "DatabaseErrorPage.cshtml" + } + else if (Model.PendingModelChanges) + { + +#line default +#line hidden + + WriteLiteral("
\r\n

"); +#line 200 "DatabaseErrorPage.cshtml" + Write(Strings.FormatDatabaseErrorPage_PendingChangesTitle(Model.ContextType.Name)); + +#line default +#line hidden + WriteLiteral("

\r\n

"); +#line 201 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_PendingChangesInfoPMC); + +#line default +#line hidden + WriteLiteral("

\r\n "); +#line 202 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_AddMigrationCommandPMC); + +#line default +#line hidden + WriteLiteral("\r\n
\r\n "); +#line 204 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC); + +#line default +#line hidden + WriteLiteral("\r\n

"); +#line 205 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_PendingChangesInfoCLI); + +#line default +#line hidden + WriteLiteral("

\r\n "); +#line 206 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_AddMigrationCommandCLI); + +#line default +#line hidden + WriteLiteral("\r\n
\r\n "); +#line 208 "DatabaseErrorPage.cshtml" + Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI); + +#line default +#line hidden + WriteLiteral("\r\n
\r\n
\r\n"); +#line 211 "DatabaseErrorPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral("\r\n"); + } + #pragma warning restore 1998 + } +} diff --git a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPage.cshtml b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPage.cshtml index c790b461eb..81c7df9276 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPage.cshtml +++ b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPage.cshtml @@ -1,10 +1,10 @@ @using System @using System.Linq @using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore -@using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views +@using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.RazorViews @{ Response.StatusCode = 500; - Response.ContentType = "text/html"; + Response.ContentType = "text/html; charset=utf-8"; Response.ContentLength = null; // Clear any prior Content-Length } @functions diff --git a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPageModel.cs b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPageModel.cs index fecb511a38..99280314a2 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPageModel.cs +++ b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPageModel.cs @@ -7,9 +7,9 @@ using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Utilities; using System; using System.Collections.Generic; -namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views +namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.RazorViews { - public class DatabaseErrorPageModel + internal class DatabaseErrorPageModel { private readonly Type _contextType; private readonly Exception _exception; diff --git a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPage.cs b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/Obsolete/DatabaseErrorPage.cs similarity index 99% rename from src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPage.cs rename to src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/Obsolete/DatabaseErrorPage.cs index 95820eb3dd..9d648a4a05 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/DatabaseErrorPage.cs +++ b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/Obsolete/DatabaseErrorPage.cs @@ -25,7 +25,7 @@ using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views #line hidden ; using System.Threading.Tasks; - + [Obsolete("This type is for internal use only and will be removed in a future version.")] public class DatabaseErrorPage : Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView { #line 11 "DatabaseErrorPage.cshtml" @@ -53,7 +53,7 @@ using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views public override async Task ExecuteAsync() { #line 5 "DatabaseErrorPage.cshtml" - + Response.StatusCode = 500; Response.ContentType = "text/html"; Response.ContentLength = null; // Clear any prior Content-Length @@ -69,7 +69,7 @@ using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views #line hidden WriteLiteral("\r\n

\r\n"); #line 37 "DatabaseErrorPage.cshtml" - + #line default #line hidden @@ -102,7 +102,7 @@ using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views WriteLiteral("

\r\n
\r\n\r\n"); #line 45 "DatabaseErrorPage.cshtml" - + #line default #line hidden @@ -179,7 +179,7 @@ using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views #line hidden WriteLiteral("

\r\n\r\n
    \r\n"); #line 65 "DatabaseErrorPage.cshtml" - + #line default #line hidden diff --git a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/Obsolete/DatabaseErrorPage.cshtml b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/Obsolete/DatabaseErrorPage.cshtml new file mode 100644 index 0000000000..c790b461eb --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/Obsolete/DatabaseErrorPage.cshtml @@ -0,0 +1,135 @@ +@using System +@using System.Linq +@using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore +@using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views +@{ + Response.StatusCode = 500; + Response.ContentType = "text/html"; + Response.ContentLength = null; // Clear any prior Content-Length +} +@functions +{ + public DatabaseErrorPageModel Model { get; set; } + + public string UrlEncode(string content) + { + return UrlEncoder.Encode(content); + } + + public string JavaScriptEncode(string content) + { + return JavaScriptEncoder.Encode(content); + } +} + + + + + + Internal Server Error + + + +

    @Strings.DatabaseErrorPage_Title

    +

    + @for (Exception ex = Model.Exception; ex != null; ex = ex.InnerException) + { + @ex.GetType().Name: @ex.Message +
    + } +

    +
    + + @if (!Model.DatabaseExists && !Model.PendingMigrations.Any()) + { +

    @Strings.FormatDatabaseErrorPage_NoDbOrMigrationsTitle(Model.ContextType.Name)

    +

    @Strings.DatabaseErrorPage_NoDbOrMigrationsInfoPMC

    + @Strings.DatabaseErrorPage_AddMigrationCommandPMC +
    + @Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC +

    @Strings.DatabaseErrorPage_NoDbOrMigrationsInfoCLI

    + @Strings.DatabaseErrorPage_AddMigrationCommandCLI +
    + @Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI +
    + } + else if (Model.PendingMigrations.Any()) + { +
    +

    @Strings.FormatDatabaseErrorPage_PendingMigrationsTitle(Model.ContextType.Name)

    +

    @Strings.FormatDatabaseErrorPage_PendingMigrationsInfo(Model.ContextType.Name)

    + +
      + @foreach (var migration in Model.PendingMigrations) + { +
    • @migration
    • + } +
    + +

    + + + +

    + + +

    @Strings.DatabaseErrorPage_HowToApplyFromPMC

    + @Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC +

    @Strings.DatabaseErrorPage_HowToApplyFromCLI

    + @Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI +
    +
    + } + else if (Model.PendingModelChanges) + { +
    +

    @Strings.FormatDatabaseErrorPage_PendingChangesTitle(Model.ContextType.Name)

    +

    @Strings.DatabaseErrorPage_PendingChangesInfoPMC

    + @Strings.DatabaseErrorPage_AddMigrationCommandPMC +
    + @Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC +

    @Strings.DatabaseErrorPage_PendingChangesInfoCLI

    + @Strings.DatabaseErrorPage_AddMigrationCommandCLI +
    + @Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI +
    +
    + } + + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/Obsolete/DatabaseErrorPageModel.cs b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/Obsolete/DatabaseErrorPageModel.cs new file mode 100644 index 0000000000..15c7ad66c9 --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/Views/Obsolete/DatabaseErrorPageModel.cs @@ -0,0 +1,73 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using JetBrains.Annotations; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Utilities; +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views +{ + [Obsolete("This type is for internal use only and will be removed in a future version.")] + public class DatabaseErrorPageModel + { + private readonly Type _contextType; + private readonly Exception _exception; + private readonly bool _databaseExists; + private readonly bool _pendingModelChanges; + private readonly IEnumerable _pendingMigrations; + private readonly DatabaseErrorPageOptions _options; + + public DatabaseErrorPageModel( + [NotNull] Type contextType, + [NotNull] Exception exception, + bool databaseExists, + bool pendingModelChanges, + [NotNull] IEnumerable pendingMigrations, + [NotNull] DatabaseErrorPageOptions options) + { + Check.NotNull(contextType, "contextType"); + Check.NotNull(exception, "exception"); + Check.NotNull(pendingMigrations, "pendingMigrations"); + Check.NotNull(options, "options"); + + _contextType = contextType; + _exception = exception; + _databaseExists = databaseExists; + _pendingModelChanges = pendingModelChanges; + _pendingMigrations = pendingMigrations; + _options = options; + } + + public virtual Type ContextType + { + get { return _contextType; } + } + + public virtual Exception Exception + { + get { return _exception; } + } + + public virtual bool DatabaseExists + { + get { return _databaseExists; } + } + + public virtual bool PendingModelChanges + { + get { return _pendingModelChanges; } + } + + public virtual IEnumerable PendingMigrations + { + get { return _pendingMigrations; } + } + + public virtual DatabaseErrorPageOptions Options + { + get { return _options; } + } + } +} diff --git a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/project.json b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/project.json index 0ba4ea398c..27235651f4 100644 --- a/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/project.json +++ b/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/project.json @@ -25,9 +25,16 @@ "type": "build", "version": "1.1.0-*" }, + "Microsoft.Extensions.RazorViews.Sources": { + "type": "build", + "version": "1.1.0-*" + }, "Microsoft.AspNetCore.Http.Abstractions": "1.1.0-*", "Microsoft.EntityFrameworkCore.Relational": "1.1.0-*" }, + "tools": { + "RazorPageGenerator": "1.1.0-*" + }, "frameworks": { "net451": { "frameworkAssemblies": { diff --git a/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs b/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs index d6a3f9f542..8296174a7b 100644 --- a/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs +++ b/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs @@ -1,14 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Diagnostics.Views; +using Microsoft.AspNetCore.Diagnostics.RazorViews; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.FileProviders; @@ -28,6 +26,7 @@ namespace Microsoft.AspNetCore.Diagnostics private readonly ILogger _logger; private readonly IFileProvider _fileProvider; private readonly System.Diagnostics.DiagnosticSource _diagnosticSource; + private readonly ExceptionDetailsProvider _exceptionDetailsProvider; /// /// Initializes a new instance of the class @@ -59,6 +58,7 @@ namespace Microsoft.AspNetCore.Diagnostics _logger = loggerFactory.CreateLogger(); _fileProvider = _options.FileProvider ?? hostingEnvironment.ContentRootFileProvider; _diagnosticSource = diagnosticSource; + _exceptionDetailsProvider = new ExceptionDetailsProvider(_fileProvider, _options.SourceCodeLineCount); } /// @@ -128,8 +128,8 @@ namespace Microsoft.AspNetCore.Diagnostics foreach (var compilationFailure in compilationException.CompilationFailures) { - var stackFrames = new List(); - var errorDetails = new ErrorDetails + var stackFrames = new List(); + var exceptionDetails = new ExceptionDetails { StackFrames = stackFrames, ErrorMessage = compilationFailure.FailureSummary, @@ -140,20 +140,20 @@ namespace Microsoft.AspNetCore.Diagnostics foreach (var item in compilationFailure.Messages) { - var frame = new StackFrame + var frame = new StackFrameSourceCodeInfo { File = compilationFailure.SourceFilePath, Line = item.StartLine, Function = string.Empty }; - ReadFrameContent(frame, fileContent, item.StartLine, item.EndLine); + _exceptionDetailsProvider.ReadFrameContent(frame, fileContent, item.StartLine, item.EndLine); frame.ErrorDetails = item.Message; stackFrames.Add(frame); } - model.ErrorDetails.Add(errorDetails); + model.ErrorDetails.Add(exceptionDetails); } var errorPage = new CompilationErrorPage @@ -171,7 +171,7 @@ namespace Microsoft.AspNetCore.Diagnostics var model = new ErrorPageModel { Options = _options, - ErrorDetails = GetErrorDetails(ex).Reverse(), + ErrorDetails = _exceptionDetailsProvider.GetDetails(ex), Query = request.Query, Cookies = request.Cookies, Headers = request.Headers @@ -180,107 +180,5 @@ namespace Microsoft.AspNetCore.Diagnostics var errorPage = new ErrorPage(model); return errorPage.ExecuteAsync(context); } - - private IEnumerable GetErrorDetails(Exception ex) - { - for (var scan = ex; scan != null; scan = scan.InnerException) - { - var stackTrace = ex.StackTrace; - yield return new ErrorDetails - { - Error = scan, - StackFrames = StackTraceHelper.GetFrames(ex) - .Select(frame => GetStackFrame(frame.MethodDisplayInfo.ToString(), frame.FilePath, frame.LineNumber)) - }; - }; - } - - // make it internal to enable unit testing - internal StackFrame GetStackFrame(string method, string filePath, int lineNumber) - { - var stackFrame = new StackFrame - { - Function = method, - File = filePath, - Line = lineNumber - }; - - if (string.IsNullOrEmpty(stackFrame.File)) - { - return stackFrame; - } - - IEnumerable lines = null; - if (File.Exists(stackFrame.File)) - { - lines = File.ReadLines(stackFrame.File); - } - else - { - // Handle relative paths and embedded files - var fileInfo = _fileProvider.GetFileInfo(stackFrame.File); - if (fileInfo.Exists) - { - // ReadLines doesn't accept a stream. Use ReadLines as its more efficient - // relative to reading lines via stream reader - if (!string.IsNullOrEmpty(fileInfo.PhysicalPath)) - { - lines = File.ReadLines(fileInfo.PhysicalPath); - } - else - { - lines = ReadLines(fileInfo); - } - } - } - - if (lines != null) - { - ReadFrameContent(stackFrame, lines, stackFrame.Line, stackFrame.Line); - } - - return stackFrame; - } - - // make it internal to enable unit testing - internal void ReadFrameContent( - StackFrame frame, - IEnumerable allLines, - int errorStartLineNumberInFile, - int errorEndLineNumberInFile) - { - // Get the line boundaries in the file to be read and read all these lines at once into an array. - var preErrorLineNumberInFile = Math.Max(errorStartLineNumberInFile - _options.SourceCodeLineCount, 1); - var postErrorLineNumberInFile = errorEndLineNumberInFile + _options.SourceCodeLineCount; - var codeBlock = allLines - .Skip(preErrorLineNumberInFile - 1) - .Take(postErrorLineNumberInFile - preErrorLineNumberInFile + 1) - .ToArray(); - - var numOfErrorLines = (errorEndLineNumberInFile - errorStartLineNumberInFile) + 1; - var errorStartLineNumberInArray = errorStartLineNumberInFile - preErrorLineNumberInFile; - - frame.PreContextLine = preErrorLineNumberInFile; - frame.PreContextCode = codeBlock.Take(errorStartLineNumberInArray).ToArray(); - frame.ContextCode = codeBlock - .Skip(errorStartLineNumberInArray) - .Take(numOfErrorLines) - .ToArray(); - frame.PostContextCode = codeBlock - .Skip(errorStartLineNumberInArray + numOfErrorLines) - .ToArray(); - } - - private static IEnumerable ReadLines(IFileInfo fileInfo) - { - using (var reader = new StreamReader(fileInfo.CreateReadStream())) - { - string line; - while ((line = reader.ReadLine()) != null) - { - yield return line; - } - } - } } } diff --git a/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/CompilationErrorModel.cs b/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/CompilationErrorModel.cs index 17cf4f3881..195b303d11 100644 --- a/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/CompilationErrorModel.cs +++ b/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/CompilationErrorModel.cs @@ -3,13 +3,14 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.StackTrace.Sources; -namespace Microsoft.AspNetCore.Diagnostics.Views +namespace Microsoft.AspNetCore.Diagnostics.RazorViews { /// /// Holds data to be displayed on the compilation error page. /// - public class CompilationErrorPageModel + internal class CompilationErrorPageModel { /// /// Options for what output to display. @@ -19,6 +20,6 @@ namespace Microsoft.AspNetCore.Diagnostics.Views /// /// Detailed information about each parse or compilation error. /// - public IList ErrorDetails { get; } = new List(); + public IList ErrorDetails { get; } = new List(); } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/CompilationErrorPage.Designer.cs b/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/CompilationErrorPage.Designer.cs new file mode 100644 index 0000000000..4e3629dae8 --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/CompilationErrorPage.Designer.cs @@ -0,0 +1,817 @@ +namespace Microsoft.AspNetCore.Diagnostics.RazorViews +{ +#line 1 "CompilationErrorPage.cshtml" +using System + +#line default +#line hidden + ; +#line 2 "CompilationErrorPage.cshtml" +using System.Globalization + +#line default +#line hidden + ; +#line 3 "CompilationErrorPage.cshtml" +using System.Linq + +#line default +#line hidden + ; +#line 4 "CompilationErrorPage.cshtml" +using System.Net + +#line default +#line hidden + ; +#line 5 "CompilationErrorPage.cshtml" +using Microsoft.AspNetCore.Diagnostics + +#line default +#line hidden + ; +#line 6 "CompilationErrorPage.cshtml" +using Microsoft.AspNetCore.Diagnostics.RazorViews + +#line default +#line hidden + ; + using System.Threading.Tasks; + + internal class CompilationErrorPage : Microsoft.Extensions.RazorViews.BaseView + { +#line 8 "CompilationErrorPage.cshtml" + + public CompilationErrorPageModel Model { get; set; } + +#line default +#line hidden + #line hidden + public CompilationErrorPage() + { + } + + #pragma warning disable 1998 + public override async Task ExecuteAsync() + { +#line 11 "CompilationErrorPage.cshtml" + + Response.StatusCode = 500; + Response.ContentType = "text/html; charset=utf-8"; + Response.ContentLength = null; // Clear any prior Content-Length + +#line default +#line hidden + + WriteLiteral("\r\n\r\n \r\n \r\n "); +#line 20 "CompilationErrorPage.cshtml" + Write(Resources.ErrorPageHtml_Title); + +#line default +#line hidden + WriteLiteral(@" + + + +

    "); +#line 221 "CompilationErrorPage.cshtml" + Write(Resources.ErrorPageHtml_CompilationException); + +#line default +#line hidden + WriteLiteral("

    \r\n"); +#line 222 "CompilationErrorPage.cshtml" + + +#line default +#line hidden + +#line 222 "CompilationErrorPage.cshtml" + foreach (var errorDetail in Model.ErrorDetails) + { + +#line default +#line hidden + + WriteLiteral("
    \r\n"); +#line 225 "CompilationErrorPage.cshtml" + + +#line default +#line hidden + +#line 225 "CompilationErrorPage.cshtml" + + var stackFrameCount = 0; + var frameId = ""; + + +#line default +#line hidden + + WriteLiteral(" "); +#line 229 "CompilationErrorPage.cshtml" + + var fileName = errorDetail.StackFrames.FirstOrDefault()?.File; + if (!string.IsNullOrEmpty(fileName)) + { + +#line default +#line hidden + + WriteLiteral("
    "); +#line 233 "CompilationErrorPage.cshtml" + Write(fileName); + +#line default +#line hidden + WriteLiteral("
    \r\n"); +#line 234 "CompilationErrorPage.cshtml" + } + + +#line default +#line hidden + + WriteLiteral(" "); +#line 236 "CompilationErrorPage.cshtml" + if (!string.IsNullOrEmpty(errorDetail.ErrorMessage)) + { + +#line default +#line hidden + + WriteLiteral("
    "); +#line 238 "CompilationErrorPage.cshtml" + Write(errorDetail.ErrorMessage); + +#line default +#line hidden + WriteLiteral("
    \r\n"); +#line 239 "CompilationErrorPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral("
    \r\n
      \r\n"); +#line 242 "CompilationErrorPage.cshtml" + + +#line default +#line hidden + +#line 242 "CompilationErrorPage.cshtml" + foreach (var frame in errorDetail.StackFrames) + { + + +#line default +#line hidden + +#line 244 "CompilationErrorPage.cshtml" + + stackFrameCount++; + frameId = "frame" + stackFrameCount; + + +#line default +#line hidden + +#line 247 "CompilationErrorPage.cshtml" + + +#line default +#line hidden + + WriteLiteral("
    • "); +#line 263 "CompilationErrorPage.cshtml" + Write(line); + +#line default +#line hidden + WriteLiteral("
    • \r\n"); +#line 264 "CompilationErrorPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral(" \r\n"); +#line 266 "CompilationErrorPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral("
    \r\n"); +#line 283 "CompilationErrorPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral(" \r\n"); +#line 285 "CompilationErrorPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral("
\r\n
\r\n \r\n"); +#line 289 "CompilationErrorPage.cshtml" + } + +#line default +#line hidden + + WriteLiteral(@" + + +"); + } + #pragma warning restore 1998 + } +} diff --git a/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/CompilationErrorPage.cshtml b/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/CompilationErrorPage.cshtml index 932d677b9c..1b93b23194 100644 --- a/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/CompilationErrorPage.cshtml +++ b/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/CompilationErrorPage.cshtml @@ -3,6 +3,7 @@ @using System.Linq @using System.Net @using Microsoft.AspNetCore.Diagnostics +@using Microsoft.AspNetCore.Diagnostics.RazorViews @functions { public CompilationErrorPageModel Model { get; set; } diff --git a/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/ErrorPage.Designer.cs b/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/ErrorPage.Designer.cs new file mode 100644 index 0000000000..03c05faa8d --- /dev/null +++ b/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/Views/ErrorPage.Designer.cs @@ -0,0 +1,1303 @@ +namespace Microsoft.AspNetCore.Diagnostics.RazorViews +{ +#line 1 "ErrorPage.cshtml" +using System + +#line default +#line hidden + ; +#line 2 "ErrorPage.cshtml" +using System.Globalization + +#line default +#line hidden + ; +#line 3 "ErrorPage.cshtml" +using System.Linq + +#line default +#line hidden + ; +#line 4 "ErrorPage.cshtml" +using System.Net + +#line default +#line hidden + ; +#line 5 "ErrorPage.cshtml" +using System.Reflection + +#line default +#line hidden + ; +#line 6 "ErrorPage.cshtml" +using Microsoft.AspNetCore.Diagnostics.RazorViews + +#line default +#line hidden + ; +#line 7 "ErrorPage.cshtml" +using Microsoft.AspNetCore.Diagnostics + +#line default +#line hidden + ; + using System.Threading.Tasks; + + internal class ErrorPage : Microsoft.Extensions.RazorViews.BaseView + { +#line 9 "ErrorPage.cshtml" + + public ErrorPage(ErrorPageModel model) + { + Model = model; + } + + public ErrorPageModel Model { get; set; } + +#line default +#line hidden + #line hidden + public ErrorPage() + { + } + + #pragma warning disable 1998 + public override async Task ExecuteAsync() + { +#line 17 "ErrorPage.cshtml" + + // TODO: Response.ReasonPhrase = "Internal Server Error"; + Response.ContentType = "text/html; charset=utf-8"; + string location = string.Empty; + +#line default +#line hidden + + WriteLiteral("\r\n