Moved PageGenerator to Razor repo and moved diagnostic view page sources to Common.

This commit is contained in:
Kiran Challa 2016-08-29 12:43:49 -07:00
parent 175a4c961e
commit c224a726f9
66 changed files with 6941 additions and 736 deletions

View File

@ -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

View File

@ -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;

View File

@ -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, " <tr>\r\n <td>");
WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteralTo(writer, "</td>\r\n <td>");
WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time));
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteralTo(writer, $"</td>\r\n <td class=\"{severity}\">");
WriteTo(writer, log.Severity);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Name}\">");
WriteTo(writer, log.Name);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Message}\""+
"class=\"logState\" width=\"100px\">");
WriteTo(writer, log.Message);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Exception}\">");
WriteTo(writer, log.Exception);
WriteLiteralTo(writer, "</td>\r\n </tr>\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(@"<!DOCTYPE html>
<html>
<head>
<meta charset=""utf-8"" />
<title>ASP.NET Core Logs</title>
<script src=""http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js""></script>
<style>
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;
} 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;
}
");
WriteLiteral(@"
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;
}
</style>
</head>
<body>
<h1>ASP.NET Core Logs</h1>
");
#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(" <h2 id=\"requestHeader\">Request Details</h2>\r\n <table id=\"requestDetails\">\r\n <colgroup><col id=\"label\" /><col /></colgroup>\r\n\r\n <tr>\r\n <th>Path</th>\r\n <td>");
#line 203 "DetailsPage.cshtml"
Write(context.Path);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Host</th>\r\n <td>");
#line 207 "DetailsPage.cshtml"
Write(context.Host);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Content Type</th>\r\n <td>");
#line 211 "DetailsPage.cshtml"
Write(context.ContentType);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Method</th>\r\n <td>");
#line 215 "DetailsPage.cshtml"
Write(context.Method);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Protocol</th>\r\n <td>");
#line 219 "DetailsPage.cshtml"
Write(context.Protocol);
#line default
#line hidden
WriteLiteral(@"</td>
</tr>
<tr>
<th>Headers</th>
<td id=""headerTd"">
<table id=""headerTable"">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
");
#line 232 "DetailsPage.cshtml"
#line default
#line hidden
#line 232 "DetailsPage.cshtml"
foreach (var header in context.Headers)
{
#line default
#line hidden
WriteLiteral(" <tr>\r\n <td>");
#line 235 "DetailsPage.cshtml"
Write(header.Key);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 236 "DetailsPage.cshtml"
Write(string.Join(";", header.Value));
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n");
#line 238 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </tbody>\r\n </table>\r\n </td>\r\n </tr>\r\n <tr>\r\n <th>Status Code</th>\r\n <td>");
#line 245 "DetailsPage.cshtml"
Write(context.StatusCode);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>User</th>\r\n <td>");
#line 249 "DetailsPage.cshtml"
Write(context.User.Identity.Name);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Claims</th>\r\n <td>\r\n");
#line 254 "DetailsPage.cshtml"
#line default
#line hidden
#line 254 "DetailsPage.cshtml"
if (context.User.Claims.Any())
{
#line default
#line hidden
WriteLiteral(@" <table id=""claimsTable"">
<thead>
<tr>
<th>Issuer</th>
<th>Value</th>
</tr>
</thead>
<tbody>
");
#line 264 "DetailsPage.cshtml"
#line default
#line hidden
#line 264 "DetailsPage.cshtml"
foreach (var claim in context.User.Claims)
{
#line default
#line hidden
WriteLiteral(" <tr>\r\n <td>");
#line 267 "DetailsPage.cshtml"
Write(claim.Issuer);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 268 "DetailsPage.cshtml"
Write(claim.Value);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n");
#line 270 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </tbody>\r\n </table>\r\n");
#line 273 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </td>\r\n </tr>\r\n <tr>\r\n <th>Scheme</th>\r\n <td>");
#line 278 "DetailsPage.cshtml"
Write(context.Scheme);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Query</th>\r\n <td>");
#line 282 "DetailsPage.cshtml"
Write(context.Query.Value);
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n <tr>\r\n <th>Cookies</th>\r\n <td>\r\n");
#line 287 "DetailsPage.cshtml"
#line default
#line hidden
#line 287 "DetailsPage.cshtml"
if (context.Cookies.Any())
{
#line default
#line hidden
WriteLiteral(@" <table id=""cookieTable"">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
");
#line 297 "DetailsPage.cshtml"
#line default
#line hidden
#line 297 "DetailsPage.cshtml"
foreach (var cookie in context.Cookies)
{
#line default
#line hidden
WriteLiteral(" <tr>\r\n <td>");
#line 300 "DetailsPage.cshtml"
Write(cookie.Key);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 301 "DetailsPage.cshtml"
Write(string.Join(";", cookie.Value));
#line default
#line hidden
WriteLiteral("</td>\r\n </tr>\r\n");
#line 303 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </tbody>\r\n </table>\r\n");
#line 306 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </td>\r\n </tr>\r\n </table>\r\n");
#line 310 "DetailsPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" <h2>Logs</h2>\r\n <form method=\"get\">\r\n <select name=\"level\">\r\n");
#line 314 "DetailsPage.cshtml"
#line default
#line hidden
#line 314 "DetailsPage.cshtml"
foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 8920, "\"", 8940, 1);
#line 319 "DetailsPage.cshtml"
WriteAttributeValue("", 8928, severityInt, 8928, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(" selected=\"selected\">");
#line 319 "DetailsPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 320 "DetailsPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 9069, "\"", 9089, 1);
#line 323 "DetailsPage.cshtml"
WriteAttributeValue("", 9077, severityInt, 9077, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 323 "DetailsPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 324 "DetailsPage.cshtml"
}
}
#line default
#line hidden
WriteLiteral(" </select>\r\n <input type=\"text\" name=\"name\"");
BeginWriteAttribute("value", " value=\"", 9202, "\"", 9235, 1);
#line 327 "DetailsPage.cshtml"
WriteAttributeValue("", 9210, Model.Options.NamePrefix, 9210, 25, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(@" />
<input type=""submit"" value=""filter"" />
</form>
<table id=""logs"">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Severity</th>
<th>Name</th>
<th>State</th>
<th>Error</th>
</tr>
</thead>
");
#line 341 "DetailsPage.cshtml"
Write(Traverse(Model.Activity.Root));
#line default
#line hidden
WriteLiteral(@"
</table>
<script type=""text/javascript"">
$(document).ready(function () {
$(""#requestHeader"").click(function () {
$(""#requestDetails"").toggle();
});
});
</script>
</body>
</html>");
}
#pragma warning restore 1998
}
}

View File

@ -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";
}
<!DOCTYPE html>
<html>
@ -91,7 +91,7 @@
<title>ASP.NET Core Logs</title>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js"></script>
<style>
<%$ include: Shared.css % > <%$ include: DetailsPage.css % >
<%$ include: Shared.css %> <%$ include: DetailsPage.css %>
</style>
</head>
<body>

View File

@ -1,6 +1,6 @@
using System;
namespace Microsoft.AspNetCore.Diagnostics.Elm.Views
namespace Microsoft.AspNetCore.Diagnostics.Elm.RazorViews
{
public class DetailsPageModel
{

View File

@ -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, " <tr class=\"logRow\">\r\n <td>");
WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteralTo(writer, "</td>\r\n <td>");
WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time));
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Name}\">");
WriteTo(writer, log.Name);
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteralTo(writer, $"</td>\r\n <td class=\"{severity}\">");
WriteTo(writer, log.Severity);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Message}\"> \r\n");
for (var i = 0; i < level; i++)
{
WriteLiteralTo(writer, " <span class=\"tab\"></span>\r\n");
}
WriteLiteralTo(writer, " ");
WriteTo(writer, log.Message);
WriteLiteralTo(writer, $"\r\n </td>\r\n <td title=\"{log.Exception}\">");
WriteTo(writer, log.Exception);
WriteLiteralTo(writer, "</td>\r\n </tr>\r\n");
}
});
}
public HelperResult Traverse(ScopeNode node, int level, Dictionary<string, int> 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(@"
<!DOCTYPE html>
<html>
<head>
<meta charset=""utf-8"" />
<title>ASP.NET Core Logs</title>
<script src=""//ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js""></script>
<style>
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 ");
WriteLiteral(@"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;
}
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;
}
");
WriteLiteral("\r\n.information {\r\n color: blue;\r\n}\r\n\r\n.debug {\r\n color: black;\r\n}\r\n\r\n.warning {\r\n color: orange;\r\n}\r\n </style>\r\n</head>\r\n<body>\r\n <h1>ASP.NET Core Logs</h1>\r\n <form id=\"viewOptions\" method=\"get\">\r\n <select name=\"level\">\r\n");
#line 280 "LogPage.cshtml"
#line default
#line hidden
#line 280 "LogPage.cshtml"
foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 6825, "\"", 6845, 1);
#line 285 "LogPage.cshtml"
WriteAttributeValue("", 6833, severityInt, 6833, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(" selected=\"selected\">");
#line 285 "LogPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 286 "LogPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <option");
BeginWriteAttribute("value", " value=\"", 6974, "\"", 6994, 1);
#line 289 "LogPage.cshtml"
WriteAttributeValue("", 6982, severityInt, 6982, 12, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 289 "LogPage.cshtml"
Write(severity);
#line default
#line hidden
WriteLiteral("</option>\r\n");
#line 290 "LogPage.cshtml"
}
}
#line default
#line hidden
WriteLiteral(" </select>\r\n <input type=\"text\" name=\"name\"");
BeginWriteAttribute("value", " value=\"", 7107, "\"", 7140, 1);
#line 293 "LogPage.cshtml"
WriteAttributeValue("", 7115, Model.Options.NamePrefix, 7115, 25, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(@" />
<input type=""submit"" value=""filter"" />
</form>
<form id=""clear"" method=""post"" action="""">
<button type=""submit"" name=""clear"" value=""1"">Clear Logs</button>
</form>
<table id=""requestTable"">
<thead id=""requestHeader"">
<tr>
<th class=""path"">Path</th>
<th class=""method"">Method</th>
<th class=""host"">Host</th>
<th class=""statusCode"">Status Code</th>
<th class=""logs"">Logs</th>
</tr>
</thead>
<colgroup>
<col />
<col />
<col />
<col />
<col />
</colgroup>
");
#line 317 "LogPage.cshtml"
#line default
#line hidden
#line 317 "LogPage.cshtml"
foreach (var activity in Model.Activities.Reverse())
{
#line default
#line hidden
WriteLiteral(" <tbody>\r\n <tr class=\"requestRow\">\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<td><a");
BeginWriteAttribute("href", " href=\"", 8204, "\"", 8224, 1);
#line 325 "LogPage.cshtml"
WriteAttributeValue("", 8211, activityPath, 8211, 13, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 8225, "\"", 8256, 1);
#line 325 "LogPage.cshtml"
WriteAttributeValue("", 8233, activity.HttpInfo.Path, 8233, 23, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 325 "LogPage.cshtml"
Write(activity.HttpInfo.Path);
#line default
#line hidden
WriteLiteral("</a></td>\r\n <td>");
#line 326 "LogPage.cshtml"
Write(activity.HttpInfo.Method);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 327 "LogPage.cshtml"
Write(activity.HttpInfo.Host);
#line default
#line hidden
WriteLiteral("</td>\r\n <td>");
#line 328 "LogPage.cshtml"
Write(activity.HttpInfo.StatusCode);
#line default
#line hidden
WriteLiteral("</td>\r\n");
#line 329 "LogPage.cshtml"
}
else if (activity.RepresentsScope)
{
#line default
#line hidden
WriteLiteral(" <td colspan=\"4\"><a");
BeginWriteAttribute("href", " href=\"", 8646, "\"", 8666, 1);
#line 332 "LogPage.cshtml"
WriteAttributeValue("", 8653, activityPath, 8653, 13, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 8667, "\"", 8695, 1);
#line 332 "LogPage.cshtml"
WriteAttributeValue("", 8675, activity.Root.State, 8675, 20, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">");
#line 332 "LogPage.cshtml"
Write(activity.Root.State);
#line default
#line hidden
WriteLiteral("</a></td>\r\n");
#line 333 "LogPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <td colspan=\"4\"><a");
BeginWriteAttribute("href", " href=\"", 8858, "\"", 8878, 1);
#line 336 "LogPage.cshtml"
WriteAttributeValue("", 8865, activityPath, 8865, 13, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">Non-scope Log</a></td>\r\n");
#line 337 "LogPage.cshtml"
}
#line default
#line hidden
WriteLiteral(@" <td class=""logTd"">
<table class=""logTable"">
<thead class=""logHeader"">
<tr class=""headerRow"">
<th class=""date"">Date</th>
<th class=""time"">Time</th>
<th class=""name"">Name</th>
<th class=""severity"">Severity</th>
<th class=""state"">State</th>
<th>Error<span class=""collapse"">^</span></th>
</tr>
</thead>
");
#line 351 "LogPage.cshtml"
#line default
#line hidden
#line 351 "LogPage.cshtml"
var counts = new Dictionary<string, int>();
counts["Critical"] = 0;
counts["Error"] = 0;
counts["Warning"] = 0;
counts["Information"] = 0;
counts["Debug"] = 0;
#line default
#line hidden
WriteLiteral(" <tbody class=\"logBody\">\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(" </tbody>\r\n <tbody class=\"summary\">\r\n <tr class=\"logRow\">\r\n <td>");
#line 374 "LogPage.cshtml"
Write(activity.Time.ToString("MM-dd-yyyy HH:mm:ss"));
#line default
#line hidden
WriteLiteral("</td>\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(" <td>");
#line 378 "LogPage.cshtml"
Write(kvp.Value);
#line default
#line hidden
WriteLiteral(" ");
#line 378 "LogPage.cshtml"
Write(kvp.Key);
#line default
#line hidden
WriteLiteral("<span class=\"collapse\">v</span></td>\r\n");
#line 379 "LogPage.cshtml"
}
else
{
#line default
#line hidden
WriteLiteral(" <td>");
#line 382 "LogPage.cshtml"
Write(kvp.Value);
#line default
#line hidden
WriteLiteral(" ");
#line 382 "LogPage.cshtml"
Write(kvp.Key);
#line default
#line hidden
WriteLiteral("</td>\r\n");
#line 383 "LogPage.cshtml"
}
}
#line default
#line hidden
WriteLiteral(" </tr>\r\n </tbody>\r\n </table>\r\n </td>\r\n </tr>\r\n </tbody>\r\n");
#line 391 "LogPage.cshtml"
}
#line default
#line hidden
WriteLiteral(@" </table>
<script type=""text/javascript"">
$(document).ready(function () {
$("".logBody"").hide();
$("".logTable > thead"").hide();
$("".logTable > thead"").click(function () {
$(this).closest("".logTable"").find(""tbody"").hide();
$(this).closest("".logTable"").find("".summary"").show();
$(this).hide();
});
$("".logTable > .summary"").click(function () {
$(this).closest("".logTable"").find(""tbody"").show();
$(this).closest("".logTable"").find(""thead"").show();
$(this).hide();
});
});
</script>
</body>
</html>");
}
#pragma warning restore 1998
}
}

View File

@ -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";
}
<!DOCTYPE html>
@ -205,7 +205,7 @@
var counts = new Dictionary<string, int>();
counts["Critical"] = 0;
counts["Error"] = 0;
counts["Warning"] = 0;
counts["Warning"] = 0;
counts["Information"] = 0;
counts["Debug"] = 0;
}

View File

@ -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
{

View File

@ -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"

View File

@ -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, " <tr>\r\n <td>");
WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteralTo(writer, "</td>\r\n <td>");
WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time));
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteralTo(writer, $"</td>\r\n <td class=\"{severity}\">");
WriteTo(writer, log.Severity);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Name}\">");
WriteTo(writer, log.Name);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Message}\""+
"class=\"logState\" width=\"100px\">");
WriteTo(writer, log.Message);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Exception}\">");
WriteTo(writer, log.Exception);
WriteLiteralTo(writer, "</td>\r\n </tr>\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";
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ASP.NET Core Logs</title>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js"></script>
<style>
<%$ include: Shared.css % > <%$ include: DetailsPage.css % >
</style>
</head>
<body>
<h1>ASP.NET Core Logs</h1>
@{
var context = Model.Activity?.HttpInfo;
}
@if (context != null)
{
<h2 id="requestHeader">Request Details</h2>
<table id="requestDetails">
<colgroup><col id="label" /><col /></colgroup>
<tr>
<th>Path</th>
<td>@context.Path</td>
</tr>
<tr>
<th>Host</th>
<td>@context.Host</td>
</tr>
<tr>
<th>Content Type</th>
<td>@context.ContentType</td>
</tr>
<tr>
<th>Method</th>
<td>@context.Method</td>
</tr>
<tr>
<th>Protocol</th>
<td>@context.Protocol</td>
</tr>
<tr>
<th>Headers</th>
<td id="headerTd">
<table id="headerTable">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var header in context.Headers)
{
<tr>
<td>@header.Key</td>
<td>@string.Join(";", header.Value)</td>
</tr>
}
</tbody>
</table>
</td>
</tr>
<tr>
<th>Status Code</th>
<td>@context.StatusCode</td>
</tr>
<tr>
<th>User</th>
<td>@context.User.Identity.Name</td>
</tr>
<tr>
<th>Claims</th>
<td>
@if (context.User.Claims.Any())
{
<table id="claimsTable">
<thead>
<tr>
<th>Issuer</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var claim in context.User.Claims)
{
<tr>
<td>@claim.Issuer</td>
<td>@claim.Value</td>
</tr>
}
</tbody>
</table>
}
</td>
</tr>
<tr>
<th>Scheme</th>
<td>@context.Scheme</td>
</tr>
<tr>
<th>Query</th>
<td>@context.Query.Value</td>
</tr>
<tr>
<th>Cookies</th>
<td>
@if (context.Cookies.Any())
{
<table id="cookieTable">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var cookie in context.Cookies)
{
<tr>
<td>@cookie.Key</td>
<td>@string.Join(";", cookie.Value)</td>
</tr>
}
</tbody>
</table>
}
</td>
</tr>
</table>
}
<h2>Logs</h2>
<form method="get">
<select name="level">
@foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
<option value="@severityInt" selected="selected">@severity</option>
}
else
{
<option value="@severityInt">@severity</option>
}
}
</select>
<input type="text" name="name" value="@Model.Options.NamePrefix" />
<input type="submit" value="filter" />
</form>
<table id="logs">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Severity</th>
<th>Name</th>
<th>State</th>
<th>Error</th>
</tr>
</thead>
@Traverse(Model.Activity.Root)
</table>
<script type="text/javascript">
$(document).ready(function () {
$("#requestHeader").click(function () {
$("#requestDetails").toggle();
});
});
</script>
</body>
</html>

View File

@ -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;
}

View File

@ -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; }
}
}

View File

@ -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"

View File

@ -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, " <tr class=\"logRow\">\r\n <td>");
WriteTo(writer, string.Format("{0:MM/dd/yy}", log.Time));
WriteLiteralTo(writer, "</td>\r\n <td>");
WriteTo(writer, string.Format("{0:H:mm:ss}", log.Time));
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Name}\">");
WriteTo(writer, log.Name);
var severity = log.Severity.ToString().ToLowerInvariant();
WriteLiteralTo(writer, $"</td>\r\n <td class=\"{severity}\">");
WriteTo(writer, log.Severity);
WriteLiteralTo(writer, $"</td>\r\n <td title=\"{log.Message}\"> \r\n");
for (var i = 0; i < level; i++)
{
WriteLiteralTo(writer, " <span class=\"tab\"></span>\r\n");
}
WriteLiteralTo(writer, " ");
WriteTo(writer, log.Message);
WriteLiteralTo(writer, $"\r\n </td>\r\n <td title=\"{log.Exception}\">");
WriteTo(writer, log.Exception);
WriteLiteralTo(writer, "</td>\r\n </tr>\r\n");
}
});
}
public HelperResult Traverse(ScopeNode node, int level, Dictionary<string, int> 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";
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ASP.NET Core Logs</title>
<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js"></script>
<style>
<%$ include: LogPage.css %>
<%$ include: Shared.css %>
</style>
</head>
<body>
<h1>ASP.NET Core Logs</h1>
<form id="viewOptions" method="get">
<select name="level">
@foreach (var severity in Enum.GetValues(typeof(LogLevel)))
{
var severityInt = (int)severity;
if ((int)Model.Options.MinLevel == severityInt)
{
<option value="@severityInt" selected="selected">@severity</option>
}
else
{
<option value="@severityInt">@severity</option>
}
}
</select>
<input type="text" name="name" value="@Model.Options.NamePrefix" />
<input type="submit" value="filter" />
</form>
<form id="clear" method="post" action="">
<button type="submit" name="clear" value="1">Clear Logs</button>
</form>
<table id="requestTable">
<thead id="requestHeader">
<tr>
<th class="path">Path</th>
<th class="method">Method</th>
<th class="host">Host</th>
<th class="statusCode">Status Code</th>
<th class="logs">Logs</th>
</tr>
</thead>
<colgroup>
<col />
<col />
<col />
<col />
<col />
</colgroup>
@foreach (var activity in Model.Activities.Reverse())
{
<tbody>
<tr class="requestRow">
@{
var activityPath = Model.Path.Value + "/" + activity.Id;
if (activity.HttpInfo != null)
{
<td><a href="@activityPath" title="@activity.HttpInfo.Path">@activity.HttpInfo.Path</a></td>
<td>@activity.HttpInfo.Method</td>
<td>@activity.HttpInfo.Host</td>
<td>@activity.HttpInfo.StatusCode</td>
}
else if (activity.RepresentsScope)
{
<td colspan="4"><a href="@activityPath" title="@activity.Root.State">@activity.Root.State</a></td>
}
else
{
<td colspan="4"><a href="@activityPath">Non-scope Log</a></td>
}
}
<td class="logTd">
<table class="logTable">
<thead class="logHeader">
<tr class="headerRow">
<th class="date">Date</th>
<th class="time">Time</th>
<th class="name">Name</th>
<th class="severity">Severity</th>
<th class="state">State</th>
<th>Error<span class="collapse">^</span></th>
</tr>
</thead>
@{
var counts = new Dictionary<string, int>();
counts["Critical"] = 0;
counts["Error"] = 0;
counts["Warning"] = 0;
counts["Information"] = 0;
counts["Debug"] = 0;
}
<tbody class="logBody">
@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)
}
</tbody>
<tbody class="summary">
<tr class="logRow">
<td>@activity.Time.ToString("MM-dd-yyyy HH:mm:ss")</td>
@foreach (var kvp in counts)
{
if (string.Equals("Debug", kvp.Key)) {
<td>@kvp.Value @kvp.Key<span class="collapse">v</span></td>
}
else
{
<td>@kvp.Value @kvp.Key</td>
}
}
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
}
</table>
<script type="text/javascript">
$(document).ready(function () {
$(".logBody").hide();
$(".logTable > thead").hide();
$(".logTable > thead").click(function () {
$(this).closest(".logTable").find("tbody").hide();
$(this).closest(".logTable").find(".summary").show();
$(this).hide();
});
$(".logTable > .summary").click(function () {
$(this).closest(".logTable").find("tbody").show();
$(this).closest(".logTable").find("thead").show();
$(this).hide();
});
});
</script>
</body>
</html>

View File

@ -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;
}

View File

@ -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<ActivityContext> Activities { get; set; }
public ViewOptions Options { get; set; }
public PathString Path { get; set; }
}
}

View File

@ -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;
}

View File

@ -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": {

View File

@ -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
/// <param name="next">Delegate to execute the next piece of middleware in the request pipeline.</param>
/// <param name="serviceProvider">The <see cref="IServiceProvider"/> to resolve services from.</param>
/// <param name="loggerFactory">
/// The <see cref="ILoggerFactory"/> for the application. This middleware both produces logging messages and
/// The <see cref="ILoggerFactory"/> for the application. This middleware both produces logging messages and
/// consumes them to detect database related exception.
/// </param>
/// <param name="options">The options to control what information is displayed on the error page.</param>

View File

@ -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.")]

View File

@ -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(@"<!DOCTYPE html>
<html lang=""en"" xmlns=""http://www.w3.org/1999/xhtml"">
<head>
<meta charset=""utf-8"" />
<title>Internal Server Error</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif;
font-size: .813em;
line-height: 1.4em;
color: #222;
}
h1, h2, h3, h4, h5 {
font-weight: 100;
}
h1 {
color: #44525e;
margin: 15px 0 15px 0;
}
h2 {
margin: 10px 5px 0 0;
}
h3 {
color: #363636;
margin: 5px 5px 0 0;
}
code {
font-family: Consolas, ""Courier New"", courier, monospace;
}
a {
color: #1ba1e2;
text-decoration: none;
}
a:hover {
color: #13709e;
text-decoration: underline;
}
hr {
border: 1px #ddd solid;
}
body .titleerror {
padding: 3px;
}
#applyMigrations {
font-size: 14px;
background: #44c5f2;
color: #ffffff;
display: inline-block;
padding: 6px 12px;
margin-bottom: 0;
font-weight: norma");
WriteLiteral(@"l;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
border: 1px solid transparent;
}
#applyMigrations:disabled {
background-color: #a9e4f9;
border-color: #44c5f2;
}
.error {
color: red;
}
.expanded {
display: block;
}
.collapsed {
display: none;
}
</style>
</head>
<body>
<h1>");
#line 113 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_Title);
#line default
#line hidden
WriteLiteral("</h1>\r\n <p>\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(" <span>");
#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("</span>\r\n <br />\r\n");
#line 119 "DatabaseErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </p>\r\n <hr />\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(" <h2>");
#line 125 "DatabaseErrorPage.cshtml"
Write(Strings.FormatDatabaseErrorPage_NoDbOrMigrationsTitle(Model.ContextType.Name));
#line default
#line hidden
WriteLiteral("</h2>\r\n <p>");
#line 126 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_NoDbOrMigrationsInfoPMC);
#line default
#line hidden
WriteLiteral("</p>\r\n <code> ");
#line 127 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_AddMigrationCommandPMC);
#line default
#line hidden
WriteLiteral("</code>\r\n <br />\r\n <code> ");
#line 129 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC);
#line default
#line hidden
WriteLiteral("</code>\r\n <p>");
#line 130 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_NoDbOrMigrationsInfoCLI);
#line default
#line hidden
WriteLiteral("</p>\r\n <code> ");
#line 131 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_AddMigrationCommandCLI);
#line default
#line hidden
WriteLiteral("</code>\r\n <br />\r\n <code> ");
#line 133 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI);
#line default
#line hidden
WriteLiteral("</code>\r\n <hr />\r\n");
#line 135 "DatabaseErrorPage.cshtml"
}
else if (Model.PendingMigrations.Any())
{
#line default
#line hidden
WriteLiteral(" <div>\r\n <h2>");
#line 139 "DatabaseErrorPage.cshtml"
Write(Strings.FormatDatabaseErrorPage_PendingMigrationsTitle(Model.ContextType.Name));
#line default
#line hidden
WriteLiteral("</h2>\r\n <p>");
#line 140 "DatabaseErrorPage.cshtml"
Write(Strings.FormatDatabaseErrorPage_PendingMigrationsInfo(Model.ContextType.Name));
#line default
#line hidden
WriteLiteral("</p>\r\n\r\n <ul>\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(" <li>");
#line 145 "DatabaseErrorPage.cshtml"
Write(migration);
#line default
#line hidden
WriteLiteral("</li>\r\n");
#line 146 "DatabaseErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </ul>\r\n\r\n <p>\r\n <button id=\"applyMigrations\" onclick=\"ApplyMigrations()\">");
#line 150 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_ApplyMigrationsButton);
#line default
#line hidden
WriteLiteral(@"</button>
<span id=""applyMigrationsError"" class=""error""></span>
<span id=""applyMigrationsSuccess""></span>
</p>
<script>
function ApplyMigrations() {
applyMigrations.disabled = true;
applyMigrationsError.innerHTML = """";
applyMigrations.innerHTML = """);
#line 158 "DatabaseErrorPage.cshtml"
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButtonRunning));
#line default
#line hidden
WriteLiteral("\";\r\n\r\n var req = new XMLHttpRequest();\r\n\r\n req.onload = function (e) {\r\n if (req.status === 204) {\r\n applyMigrations.innerHTML = \"");
#line 164 "DatabaseErrorPage.cshtml"
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButtonDone));
#line default
#line hidden
WriteLiteral("\";\r\n applyMigrationsSuccess.innerHTML = \"");
#line 165 "DatabaseErrorPage.cshtml"
Write(JavaScriptEncode(Strings.DatabaseErrorPage_MigrationsAppliedRefresh));
#line default
#line hidden
WriteLiteral(@""";
} else {
ErrorApplyingMigrations();
}
};
req.onerror = function (e) {
ErrorApplyingMigrations();
};
var formBody = ""context=");
#line 175 "DatabaseErrorPage.cshtml"
Write(JavaScriptEncode(UrlEncode(Model.ContextType.AssemblyQualifiedName)));
#line default
#line hidden
WriteLiteral("\";\r\n req.open(\"POST\", \"");
#line 176 "DatabaseErrorPage.cshtml"
Write(JavaScriptEncode(Model.Options.MigrationsEndPointPath.Value));
#line default
#line hidden
WriteLiteral(@""", true);
req.setRequestHeader(""Content-type"", ""application/x-www-form-urlencoded"");
req.setRequestHeader(""Content-length"", formBody.length);
req.setRequestHeader(""Connection"", ""close"");
req.send(formBody);
}
function ErrorApplyingMigrations() {
applyMigrations.innerHTML = """);
#line 184 "DatabaseErrorPage.cshtml"
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButton));
#line default
#line hidden
WriteLiteral("\";\r\n applyMigrationsError.innerHTML = \"");
#line 185 "DatabaseErrorPage.cshtml"
Write(JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsFailed));
#line default
#line hidden
WriteLiteral("\";\r\n applyMigrations.disabled = false;\r\n }\r\n </script>\r\n\r\n <p>");
#line 190 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_HowToApplyFromPMC);
#line default
#line hidden
WriteLiteral("</p>\r\n <code>");
#line 191 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC);
#line default
#line hidden
WriteLiteral("</code>\r\n <p>");
#line 192 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_HowToApplyFromCLI);
#line default
#line hidden
WriteLiteral("</p>\r\n <code>");
#line 193 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI);
#line default
#line hidden
WriteLiteral("</code>\r\n <hr />\r\n </div>\r\n");
#line 196 "DatabaseErrorPage.cshtml"
}
else if (Model.PendingModelChanges)
{
#line default
#line hidden
WriteLiteral(" <div>\r\n <h2>");
#line 200 "DatabaseErrorPage.cshtml"
Write(Strings.FormatDatabaseErrorPage_PendingChangesTitle(Model.ContextType.Name));
#line default
#line hidden
WriteLiteral("</h2>\r\n <p>");
#line 201 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_PendingChangesInfoPMC);
#line default
#line hidden
WriteLiteral("</p>\r\n <code>");
#line 202 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_AddMigrationCommandPMC);
#line default
#line hidden
WriteLiteral("</code>\r\n <br />\r\n <code>");
#line 204 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC);
#line default
#line hidden
WriteLiteral("</code>\r\n <p>");
#line 205 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_PendingChangesInfoCLI);
#line default
#line hidden
WriteLiteral("</p>\r\n <code>");
#line 206 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_AddMigrationCommandCLI);
#line default
#line hidden
WriteLiteral("</code>\r\n <br />\r\n <code>");
#line 208 "DatabaseErrorPage.cshtml"
Write(Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI);
#line default
#line hidden
WriteLiteral("</code>\r\n <hr />\r\n </div>\r\n");
#line 211 "DatabaseErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral("</body>\r\n</html>");
}
#pragma warning restore 1998
}
}

View File

@ -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

View File

@ -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;

View File

@ -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("</h1>\r\n <p>\r\n");
#line 37 "DatabaseErrorPage.cshtml"
#line default
#line hidden
@ -102,7 +102,7 @@ using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views
WriteLiteral(" </p>\r\n <hr />\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("</p>\r\n\r\n <ul>\r\n");
#line 65 "DatabaseErrorPage.cshtml"
#line default
#line hidden

View File

@ -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);
}
}
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Internal Server Error</title>
<style>
<%$ include: ErrorPage.css %>
</style>
</head>
<body>
<h1>@Strings.DatabaseErrorPage_Title</h1>
<p>
@for (Exception ex = Model.Exception; ex != null; ex = ex.InnerException)
{
<span>@ex.GetType().Name: @ex.Message</span>
<br />
}
</p>
<hr />
@if (!Model.DatabaseExists && !Model.PendingMigrations.Any())
{
<h2>@Strings.FormatDatabaseErrorPage_NoDbOrMigrationsTitle(Model.ContextType.Name)</h2>
<p>@Strings.DatabaseErrorPage_NoDbOrMigrationsInfoPMC</p>
<code> @Strings.DatabaseErrorPage_AddMigrationCommandPMC</code>
<br />
<code> @Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC</code>
<p>@Strings.DatabaseErrorPage_NoDbOrMigrationsInfoCLI</p>
<code> @Strings.DatabaseErrorPage_AddMigrationCommandCLI</code>
<br />
<code> @Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI</code>
<hr />
}
else if (Model.PendingMigrations.Any())
{
<div>
<h2>@Strings.FormatDatabaseErrorPage_PendingMigrationsTitle(Model.ContextType.Name)</h2>
<p>@Strings.FormatDatabaseErrorPage_PendingMigrationsInfo(Model.ContextType.Name)</p>
<ul>
@foreach (var migration in Model.PendingMigrations)
{
<li>@migration</li>
}
</ul>
<p>
<button id="applyMigrations" onclick="ApplyMigrations()">@Strings.DatabaseErrorPage_ApplyMigrationsButton</button>
<span id="applyMigrationsError" class="error"></span>
<span id="applyMigrationsSuccess"></span>
</p>
<script>
function ApplyMigrations() {
applyMigrations.disabled = true;
applyMigrationsError.innerHTML = "";
applyMigrations.innerHTML = "@JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButtonRunning)";
var req = new XMLHttpRequest();
req.onload = function (e) {
if (req.status === 204) {
applyMigrations.innerHTML = "@JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButtonDone)";
applyMigrationsSuccess.innerHTML = "@JavaScriptEncode(Strings.DatabaseErrorPage_MigrationsAppliedRefresh)";
} else {
ErrorApplyingMigrations();
}
};
req.onerror = function (e) {
ErrorApplyingMigrations();
};
var formBody = "context=@JavaScriptEncode(UrlEncode(Model.ContextType.AssemblyQualifiedName))";
req.open("POST", "@JavaScriptEncode(Model.Options.MigrationsEndPointPath.Value)", true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.setRequestHeader("Content-length", formBody.length);
req.setRequestHeader("Connection", "close");
req.send(formBody);
}
function ErrorApplyingMigrations() {
applyMigrations.innerHTML = "@JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsButton)";
applyMigrationsError.innerHTML = "@JavaScriptEncode(Strings.DatabaseErrorPage_ApplyMigrationsFailed)";
applyMigrations.disabled = false;
}
</script>
<p>@Strings.DatabaseErrorPage_HowToApplyFromPMC</p>
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC</code>
<p>@Strings.DatabaseErrorPage_HowToApplyFromCLI</p>
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI</code>
<hr />
</div>
}
else if (Model.PendingModelChanges)
{
<div>
<h2>@Strings.FormatDatabaseErrorPage_PendingChangesTitle(Model.ContextType.Name)</h2>
<p>@Strings.DatabaseErrorPage_PendingChangesInfoPMC</p>
<code>@Strings.DatabaseErrorPage_AddMigrationCommandPMC</code>
<br />
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandPMC</code>
<p>@Strings.DatabaseErrorPage_PendingChangesInfoCLI</p>
<code>@Strings.DatabaseErrorPage_AddMigrationCommandCLI</code>
<br />
<code>@Strings.DatabaseErrorPage_ApplyMigrationsCommandCLI</code>
<hr />
</div>
}
</body>
</html>

View File

@ -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<string> _pendingMigrations;
private readonly DatabaseErrorPageOptions _options;
public DatabaseErrorPageModel(
[NotNull] Type contextType,
[NotNull] Exception exception,
bool databaseExists,
bool pendingModelChanges,
[NotNull] IEnumerable<string> 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<string> PendingMigrations
{
get { return _pendingMigrations; }
}
public virtual DatabaseErrorPageOptions Options
{
get { return _options; }
}
}
}

View File

@ -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": {

View File

@ -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;
/// <summary>
/// Initializes a new instance of the <see cref="DeveloperExceptionPageMiddleware"/> class
@ -59,6 +58,7 @@ namespace Microsoft.AspNetCore.Diagnostics
_logger = loggerFactory.CreateLogger<DeveloperExceptionPageMiddleware>();
_fileProvider = _options.FileProvider ?? hostingEnvironment.ContentRootFileProvider;
_diagnosticSource = diagnosticSource;
_exceptionDetailsProvider = new ExceptionDetailsProvider(_fileProvider, _options.SourceCodeLineCount);
}
/// <summary>
@ -128,8 +128,8 @@ namespace Microsoft.AspNetCore.Diagnostics
foreach (var compilationFailure in compilationException.CompilationFailures)
{
var stackFrames = new List<StackFrame>();
var errorDetails = new ErrorDetails
var stackFrames = new List<StackFrameSourceCodeInfo>();
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<ErrorDetails> 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<string> 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<string> 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<string> ReadLines(IFileInfo fileInfo)
{
using (var reader = new StreamReader(fileInfo.CreateReadStream()))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
}
}

View File

@ -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
{
/// <summary>
/// Holds data to be displayed on the compilation error page.
/// </summary>
public class CompilationErrorPageModel
internal class CompilationErrorPageModel
{
/// <summary>
/// Options for what output to display.
@ -19,6 +20,6 @@ namespace Microsoft.AspNetCore.Diagnostics.Views
/// <summary>
/// Detailed information about each parse or compilation error.
/// </summary>
public IList<ErrorDetails> ErrorDetails { get; } = new List<ErrorDetails>();
public IList<ExceptionDetails> ErrorDetails { get; } = new List<ExceptionDetails>();
}
}

View File

@ -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("<!DOCTYPE html>\r\n<html>\r\n <head>\r\n <meta charset=\"utf-8\" />\r\n <title>");
#line 20 "CompilationErrorPage.cshtml"
Write(Resources.ErrorPageHtml_Title);
#line default
#line hidden
WriteLiteral(@"</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif;
font-size: .813em;
color: #222;
}
h1, h2, h3, h4, h5 {
/*font-family: 'Segoe UI',Tahoma,Arial,Helvetica,sans-serif;*/
font-weight: 100;
}
h1 {
color: #44525e;
margin: 15px 0 15px 0;
}
h2 {
margin: 10px 5px 0 0;
}
h3 {
color: #363636;
margin: 5px 5px 0 0;
}
code {
font-family: Consolas, ""Courier New"", courier, monospace;
}
body .titleerror {
padding: 3px 3px 6px 3px;
display: block;
font-size: 1.5em;
font-weight: 100;
}
body .location {
margin: 3px 0 10px 30px;
}
#header {
font-size: 18px;
padding: 15px 0;
border-top: 1px #ddd solid;
border-bottom: 1px #ddd solid;
margin-bottom: 0;
}
#header li {
display: inline;
margin: 5px;
padding: 5px;
color: #a0a0a0;
cursor: pointer;
}
#header .selected {
ba");
WriteLiteral(@"ckground: #44c5f2;
color: #fff;
}
#stackpage ul {
list-style: none;
padding-left: 0;
margin: 0;
/*border-bottom: 1px #ddd solid;*/
}
#stackpage .details {
font-size: 1.2em;
padding: 3px;
color: #000;
}
#stackpage .stackerror {
padding: 5px;
border-bottom: 1px #ddd solid;
}
#stackpage .frame {
padding: 0;
margin: 0 0 0 30px;
}
#stackpage .frame h3 {
padding: 2px;
margin: 0;
}
#stackpage .source {
padding: 0 0 0 30px;
}
#stackpage .source ol li {
font-family: Consolas, ""Courier New"", courier, monospace;
white-space: pre;
background-color: #fbfbfb;
}
#stackpage .frame .source .highlight li span {
color: #FF0000;
}
#stackpage .source ol.collapsible li {
color: #888;
}
#stackpage .source ol.collapsible li span {
color: #606060;
}
.page table {
border-collapse: separate;
border-spacing: 0;
margin:");
WriteLiteral(@" 0 0 20px;
}
.page th {
vertical-align: bottom;
padding: 10px 5px 5px 5px;
font-weight: 400;
color: #a0a0a0;
text-align: left;
}
.page td {
padding: 3px 10px;
}
.page th, .page td {
border-right: 1px #ddd solid;
border-bottom: 1px #ddd solid;
border-left: 1px transparent solid;
border-top: 1px transparent solid;
box-sizing: border-box;
}
.page th:last-child, .page td:last-child {
border-right: 1px transparent solid;
}
.page .length {
text-align: right;
}
a {
color: #1ba1e2;
text-decoration: none;
}
a:hover {
color: #13709e;
text-decoration: underline;
}
.showRawException {
cursor: pointer;
color: #44c5f2;
background-color: transparent;
font-size: 1.2em;
text-align: left;
text-decoration: none;
display: inline-block;
border: 0;
padding: 0;
}
.rawExceptionStackTrace {
font-size: 1.2em;
}
.rawExceptionBlock {
");
WriteLiteral(@" border-top: 1px #ddd solid;
border-bottom: 1px #ddd solid;
}
.showRawExceptionContainer {
margin-top: 10px;
margin-bottom: 10px;
}
.expandCollapseButton {
cursor: pointer;
float: left;
height: 16px;
width: 16px;
font-size: 10px;
position: absolute;
left: 10px;
background-color: #eee;
padding: 0;
border: 0;
margin: 0;
}
</style>
</head>
<body>
<h1>");
#line 221 "CompilationErrorPage.cshtml"
Write(Resources.ErrorPageHtml_CompilationException);
#line default
#line hidden
WriteLiteral("</h1>\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(" <div id=\"stackpage\" class=\"page\">\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(" <div class=\"titleerror\">");
#line 233 "CompilationErrorPage.cshtml"
Write(fileName);
#line default
#line hidden
WriteLiteral("</div>\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(" <div class=\"details\">");
#line 238 "CompilationErrorPage.cshtml"
Write(errorDetail.ErrorMessage);
#line default
#line hidden
WriteLiteral("</div>\r\n");
#line 239 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" <br />\r\n <ul>\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(" <li class=\"frame\"");
BeginWriteAttribute("id", " id=\"", 5153, "\"", 5166, 1);
#line 248 "CompilationErrorPage.cshtml"
WriteAttributeValue("", 5158, frameId, 5158, 8, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">\r\n");
#line 249 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 249 "CompilationErrorPage.cshtml"
if (!string.IsNullOrEmpty(frame.ErrorDetails))
{
#line default
#line hidden
WriteLiteral(" <h3>");
#line 251 "CompilationErrorPage.cshtml"
Write(frame.ErrorDetails);
#line default
#line hidden
WriteLiteral("</h3>\r\n");
#line 252 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral("\r\n");
#line 254 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 254 "CompilationErrorPage.cshtml"
if (frame.Line != 0 && frame.ContextCode.Any())
{
#line default
#line hidden
WriteLiteral(" <button class=\"expandCollapseButton\" data-frameId=\"");
#line 256 "CompilationErrorPage.cshtml"
Write(frameId);
#line default
#line hidden
WriteLiteral("\">+</button>\r\n <div class=\"source\">\r\n");
#line 258 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 258 "CompilationErrorPage.cshtml"
if (frame.PreContextCode.Any())
{
#line default
#line hidden
WriteLiteral(" <ol");
BeginWriteAttribute("start", " start=\"", 5749, "\"", 5778, 1);
#line 260 "CompilationErrorPage.cshtml"
WriteAttributeValue("", 5757, frame.PreContextLine, 5757, 21, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(" class=\"collapsible\">\r\n");
#line 261 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 261 "CompilationErrorPage.cshtml"
foreach (var line in frame.PreContextCode)
{
#line default
#line hidden
WriteLiteral(" <li><span>");
#line 263 "CompilationErrorPage.cshtml"
Write(line);
#line default
#line hidden
WriteLiteral("</span></li>\r\n");
#line 264 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </ol>\r\n");
#line 266 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" <ol");
BeginWriteAttribute("start", " start=\"", 6159, "\"", 6178, 1);
#line 267 "CompilationErrorPage.cshtml"
WriteAttributeValue("", 6167, frame.Line, 6167, 11, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(" class=\"highlight\">\r\n");
#line 268 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 268 "CompilationErrorPage.cshtml"
foreach (var line in frame.ContextCode)
{
#line default
#line hidden
WriteLiteral(" <li><span>");
#line 270 "CompilationErrorPage.cshtml"
Write(line);
#line default
#line hidden
WriteLiteral("</span></li>\r\n");
#line 271 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </ol>\r\n");
#line 273 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 273 "CompilationErrorPage.cshtml"
if (frame.PostContextCode.Any())
{
#line default
#line hidden
WriteLiteral(" <ol");
BeginWriteAttribute("start", " start=\'", 6605, "\'", 6630, 1);
#line 275 "CompilationErrorPage.cshtml"
WriteAttributeValue("", 6613, frame.Line + 1, 6613, 17, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(" class=\"collapsible\">\r\n");
#line 276 "CompilationErrorPage.cshtml"
#line default
#line hidden
#line 276 "CompilationErrorPage.cshtml"
foreach (var line in frame.PostContextCode)
{
#line default
#line hidden
WriteLiteral(" <li><span>");
#line 278 "CompilationErrorPage.cshtml"
Write(line);
#line default
#line hidden
WriteLiteral("</span></li>\r\n");
#line 279 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </ol>\r\n");
#line 281 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </div>\r\n");
#line 283 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </li>\r\n");
#line 285 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(" </ul>\r\n <br />\r\n </div>\r\n");
#line 289 "CompilationErrorPage.cshtml"
}
#line default
#line hidden
WriteLiteral(@" <script>
//<!--
(function (window, undefined) {
""use strict"";
function ns(selector, element) {
return new NodeCollection(selector, element);
}
function NodeCollection(selector, element) {
this.items = [];
element = element || window.document;
var nodeList;
if (typeof (selector) === ""string"") {
nodeList = element.querySelectorAll(selector);
for (var i = 0, l = nodeList.length; i < l; i++) {
this.items.push(nodeList.item(i));
}
}
}
NodeCollection.prototype = {
each: function (callback) {
for (var i = 0, l = this.items.length; i < l; i++) {
callback(this.items[i], i);
}
return this;
},
children: function (selector) {
var children = [];
this.each(function (el) {
children = children.concat(ns(selector, el)");
WriteLiteral(@".items);
});
return ns(children);
},
hide: function () {
this.each(function (el) {
el.style.display = ""none"";
});
return this;
},
toggle: function () {
this.each(function (el) {
el.style.display = el.style.display === ""none"" ? """" : ""none"";
});
return this;
},
show: function () {
this.each(function (el) {
el.style.display = """";
});
return this;
},
addClass: function (className) {
this.each(function (el) {
var existingClassName = el.className,
classNames;
if (!existingClassName) {
el.className = className;
} else {
classNames = existingClassName.split("" "");
if (classNames.indexOf(className");
WriteLiteral(@") < 0) {
el.className = existingClassName + "" "" + className;
}
}
});
return this;
},
removeClass: function (className) {
this.each(function (el) {
var existingClassName = el.className,
classNames, index;
if (existingClassName === className) {
el.className = """";
} else if (existingClassName) {
classNames = existingClassName.split("" "");
index = classNames.indexOf(className);
if (index > 0) {
classNames.splice(index, 1);
el.className = classNames.join("" "");
}
}
});
return this;
},
attr: function (name) {
if (this.items.length === 0) {
return null;
}
");
WriteLiteral(@" return this.items[0].getAttribute(name);
},
on: function (eventName, handler) {
this.each(function (el, idx) {
var callback = function (e) {
e = e || window.event;
if (!e.which && e.keyCode) {
e.which = e.keyCode; // Normalize IE8 key events
}
handler.apply(el, [e]);
};
if (el.addEventListener) { // DOM Events
el.addEventListener(eventName, callback, false);
} else if (el.attachEvent) { // IE8 events
el.attachEvent(""on"" + eventName, callback);
} else {
el[""on"" + type] = callback;
}
});
return this;
},
click: function (handler) {
return this.on(""click"", handler);
},
keypress: function (handler) {
return this.on(");
WriteLiteral(@"""keypress"", handler);
}
};
function frame(el) {
ns("".source .collapsible"", el).toggle();
}
function expandCollapseButton(el) {
var frameId = el.getAttribute(""data-frameId"");
frame(document.getElementById(frameId));
if (el.innerText === ""+"") {
el.innerText = ""-"";
}
else {
el.innerText = ""+"";
}
}
function tab(el) {
var unselected = ns(""#header .selected"").removeClass(""selected"").attr(""id"");
var selected = ns(""#"" + el.id).addClass(""selected"").attr(""id"");
ns(""#"" + unselected + ""page"").hide();
ns(""#"" + selected + ""page"").show();
}
ns("".rawExceptionDetails"").hide();
ns("".collapsible"").hide();
ns("".page"").hide();
ns(""#stackpage"").show();
ns("".expandCollapseButton"")
.click(function () {
expandCollapseButton(this);
})
.keypress(function (e) {
if (e.which === 13) {");
WriteLiteral(@"
expandCollapseButton(this);
}
});
ns(""#header li"")
.click(function () {
tab(this);
})
.keypress(function (e) {
if (e.which === 13) {
tab(this);
}
});
ns("".showRawException"")
.click(function () {
var exceptionDetailId = this.getAttribute(""data-exceptionDetailId"");
ns(""#"" + exceptionDetailId).toggle();
});
})(window);
//-->
</script>
</body>
</html>
");
}
#pragma warning restore 1998
}
}

View File

@ -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; }

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
@using System.Linq
@using System.Net
@using System.Reflection
@using Microsoft.AspNetCore.Diagnostics.Views
@using Microsoft.AspNetCore.Diagnostics.RazorViews
@using Microsoft.AspNetCore.Diagnostics
@functions
{
@ -42,19 +42,18 @@
}
if (!string.IsNullOrEmpty(location) && firstFrame != null && !string.IsNullOrEmpty(firstFrame.File))
{
<p class="location">@location in <code title="@firstFrame.File">@System.IO.Path.GetFileName(firstFrame.File)</code>, line @firstFrame.Line</p>
<p class="location">@location in <code title="@firstFrame.File">@System.IO.Path.GetFileName(firstFrame.File)</code>, line @firstFrame.Line</p>
}
else if (!string.IsNullOrEmpty(location))
{
<p class="location">@location</p>
<p class="location">@location</p>
}
else
{
<p class="location">@Resources.ErrorPageHtml_UnknownLocation</p>
<p class="location">@Resources.ErrorPageHtml_UnknownLocation</p>
}
}
@{
var reflectionTypeLoadException = Model.ErrorDetails.Last()?.Error as ReflectionTypeLoadException;
var reflectionTypeLoadException = errorDetail.Error as ReflectionTypeLoadException;
if (reflectionTypeLoadException != null)
{
if (reflectionTypeLoadException.LoaderExceptions.Length > 0)

View File

@ -5,13 +5,14 @@ using System.Collections.Generic;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Microsoft.Extensions.StackTrace.Sources;
namespace Microsoft.AspNetCore.Diagnostics.Views
namespace Microsoft.AspNetCore.Diagnostics.RazorViews
{
/// <summary>
/// Holds data to be displayed on the error page.
/// </summary>
public class ErrorPageModel
internal class ErrorPageModel
{
/// <summary>
/// Options for what output to display.
@ -21,7 +22,7 @@ namespace Microsoft.AspNetCore.Diagnostics.Views
/// <summary>
/// Detailed information about each exception in the stack.
/// </summary>
public IEnumerable<ErrorDetails> ErrorDetails { get; set; }
public IEnumerable<ExceptionDetails> ErrorDetails { get; set; }
/// <summary>
/// Parsed query data.

View File

@ -0,0 +1,26 @@
// 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 Microsoft.AspNetCore.Builder;
namespace Microsoft.AspNetCore.Diagnostics.Views
{
/// <summary>
/// Holds data to be displayed on the compilation error page.
/// </summary>
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class CompilationErrorPageModel
{
/// <summary>
/// Options for what output to display.
/// </summary>
public DeveloperExceptionPageOptions Options { get; set; }
/// <summary>
/// Detailed information about each parse or compilation error.
/// </summary>
public IList<ErrorDetails> ErrorDetails { get; } = new List<ErrorDetails>();
}
}

View File

@ -31,7 +31,7 @@ using Microsoft.AspNetCore.Diagnostics
#line hidden
;
using System.Threading.Tasks;
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class CompilationErrorPage : Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView
{
#line 7 "CompilationErrorPage.cshtml"

View File

@ -0,0 +1,100 @@
@using System
@using System.Globalization
@using System.Linq
@using System.Net
@using Microsoft.AspNetCore.Diagnostics
@functions
{
public CompilationErrorPageModel Model { get; set; }
}
@{
Response.StatusCode = 500;
Response.ContentType = "text/html; charset=utf-8";
Response.ContentLength = null; // Clear any prior Content-Length
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@Resources.ErrorPageHtml_Title</title>
<style>
<%$ include: ErrorPage.css %>
</style>
</head>
<body>
<h1>@Resources.ErrorPageHtml_CompilationException</h1>
@foreach (var errorDetail in Model.ErrorDetails)
{
<div id="stackpage" class="page">
@{
var stackFrameCount = 0;
var frameId = "";
}
@{
var fileName = errorDetail.StackFrames.FirstOrDefault()?.File;
if (!string.IsNullOrEmpty(fileName))
{
<div class="titleerror">@fileName</div>
}
}
@if (!string.IsNullOrEmpty(errorDetail.ErrorMessage))
{
<div class="details">@errorDetail.ErrorMessage</div>
}
<br />
<ul>
@foreach (var frame in errorDetail.StackFrames)
{
@{
stackFrameCount++;
frameId = "frame" + stackFrameCount;
}
<li class="frame" id="@frameId">
@if (!string.IsNullOrEmpty(frame.ErrorDetails))
{
<h3>@frame.ErrorDetails</h3>
}
@if (frame.Line != 0 && frame.ContextCode.Any())
{
<button class="expandCollapseButton" data-frameId="@frameId">+</button>
<div class="source">
@if (frame.PreContextCode.Any())
{
<ol start="@frame.PreContextLine" class="collapsible">
@foreach (var line in frame.PreContextCode)
{
<li><span>@line</span></li>
}
</ol>
}
<ol start="@frame.Line" class="highlight">
@foreach (var line in frame.ContextCode)
{
<li><span>@line</span></li>
}
</ol>
@if (frame.PostContextCode.Any())
{
<ol start='@(frame.Line + 1)' class="collapsible">
@foreach (var line in frame.PostContextCode)
{
<li><span>@line</span></li>
}
</ol>
}
</div>
}
</li>
}
</ul>
<br />
</div>
}
<script>
//<!--
<%$ include: ErrorPage.js %>
//-->
</script>
</body>
</html>

View File

@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Diagnostics.Views
/// <summary>
/// Contains details for individual exception messages.
/// </summary>
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class ErrorDetails
{
/// <summary>

View File

@ -43,7 +43,7 @@ using Microsoft.AspNetCore.Diagnostics
#line hidden
;
using System.Threading.Tasks;
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class ErrorPage : Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView
{
#line 9 "ErrorPage.cshtml"

View File

@ -0,0 +1,262 @@
@using System
@using System.Globalization
@using System.Linq
@using System.Net
@using System.Reflection
@using Microsoft.AspNetCore.Diagnostics.Views
@using Microsoft.AspNetCore.Diagnostics
@functions
{
public ErrorPage(ErrorPageModel model)
{
Model = model;
}
public ErrorPageModel Model { get; set; }
}
@{
// TODO: Response.ReasonPhrase = "Internal Server Error";
Response.ContentType = "text/html; charset=utf-8";
string location = string.Empty;
}
<!DOCTYPE html>
<html lang="@CultureInfo.CurrentUICulture.TwoLetterISOLanguageName" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>@Resources.ErrorPageHtml_Title</title>
<style>
<%$ include: ErrorPage.css %>
</style>
</head>
<body>
<h1>@Resources.ErrorPageHtml_UnhandledException</h1>
@foreach (var errorDetail in Model.ErrorDetails)
{
<div class="titleerror">@errorDetail.Error.GetType().Name: @{ Output.Write(HtmlEncodeAndReplaceLineBreaks(errorDetail.Error.Message)); }</div>
@{
var firstFrame = errorDetail.StackFrames.FirstOrDefault();
if (firstFrame != null)
{
location = firstFrame.Function;
}
}
if (!string.IsNullOrEmpty(location) && firstFrame != null && !string.IsNullOrEmpty(firstFrame.File))
{
<p class="location">@location in <code title="@firstFrame.File">@System.IO.Path.GetFileName(firstFrame.File)</code>, line @firstFrame.Line</p>
}
else if (!string.IsNullOrEmpty(location))
{
<p class="location">@location</p>
}
else
{
<p class="location">@Resources.ErrorPageHtml_UnknownLocation</p>
}
}
@{
var reflectionTypeLoadException = Model.ErrorDetails.Last()?.Error as ReflectionTypeLoadException;
if (reflectionTypeLoadException != null)
{
if (reflectionTypeLoadException.LoaderExceptions.Length > 0)
{
<h3>Loader Exceptions:</h3>
<ul>
@foreach (var ex in reflectionTypeLoadException.LoaderExceptions)
{
<li>@ex.Message</li>
}
</ul>
}
}
}
<ul id="header">
<li id="stack" tabindex="1" class="selected">
@Resources.ErrorPageHtml_StackButton
</li>
<li id="query" tabindex="2">
@Resources.ErrorPageHtml_QueryButton
</li>
<li id="cookies" tabindex="3">
@Resources.ErrorPageHtml_CookiesButton
</li>
<li id="headers" tabindex="4">
@Resources.ErrorPageHtml_HeadersButton
</li>
</ul>
<div id="stackpage" class="page">
<ul>
@{
var exceptionCount = 0;
var stackFrameCount = 0;
var exceptionDetailId = "";
var frameId = "";
}
@foreach (var errorDetail in Model.ErrorDetails)
{
@{
exceptionCount++;
exceptionDetailId = "exceptionDetail" + exceptionCount;
}
<li>
<h2 class="stackerror">@errorDetail.Error.GetType().Name: @errorDetail.Error.Message</h2>
<ul>
@foreach (var frame in errorDetail.StackFrames)
{
@{
stackFrameCount++;
frameId = "frame" + stackFrameCount;
}
<li class="frame" id="@frameId">
@if (string.IsNullOrEmpty(frame.File))
{
<h3>@frame.Function</h3>
}
else
{
<h3>@frame.Function in <code title="@frame.File">@System.IO.Path.GetFileName(frame.File)</code></h3>
}
@if (frame.Line != 0 && frame.ContextCode.Any())
{
<button class="expandCollapseButton" data-frameId="@frameId">+</button>
<div class="source">
@if (frame.PreContextCode.Any())
{
<ol start="@frame.PreContextLine" class="collapsible">
@foreach (var line in frame.PreContextCode)
{
<li><span>@line</span></li>
}
</ol>
}
<ol start="@frame.Line" class="highlight">
@foreach (var line in frame.ContextCode)
{
<li><span>@line</span></li>
}
</ol>
@if (frame.PostContextCode.Any())
{
<ol start='@(frame.Line + 1)' class="collapsible">
@foreach (var line in frame.PostContextCode)
{
<li><span>@line</span></li>
}
</ol>
}
</div>
}
</li>
}
</ul>
</li>
<li>
<br/>
<div class="rawExceptionBlock">
<div class="showRawExceptionContainer">
<button class="showRawException" data-exceptionDetailId="@exceptionDetailId">Show raw exception details</button>
</div>
<div id="@exceptionDetailId" class="rawExceptionDetails">
<pre class="rawExceptionStackTrace">@errorDetail.Error.ToString()</pre>
</div>
</div>
</li>
}
</ul>
</div>
<div id="querypage" class="page">
@if (Model.Query.Any())
{
<table>
<thead>
<tr>
<th>@Resources.ErrorPageHtml_VariableColumn</th>
<th>@Resources.ErrorPageHtml_ValueColumn</th>
</tr>
</thead>
<tbody>
@foreach (var kv in Model.Query.OrderBy(kv => kv.Key))
{
foreach (var v in kv.Value)
{
<tr>
<td>@kv.Key</td>
<td>@v</td>
</tr>
}
}
</tbody>
</table>
}
else
{
<p>@Resources.ErrorPageHtml_NoQueryStringData</p>
}
</div>
<div id="cookiespage" class="page">
@if (Model.Cookies.Any())
{
<table>
<thead>
<tr>
<th>@Resources.ErrorPageHtml_VariableColumn</th>
<th>@Resources.ErrorPageHtml_ValueColumn</th>
</tr>
</thead>
<tbody>
@foreach (var kv in Model.Cookies.OrderBy(kv => kv.Key))
{
<tr>
<td>@kv.Key</td>
<td>@kv.Value</td>
</tr>
}
</tbody>
</table>
}
else
{
<p>@Resources.ErrorPageHtml_NoCookieData</p>
}
</div>
<div id="headerspage" class="page">
@if (Model.Headers.Any())
{
<table>
<thead>
<tr>
<th>@Resources.ErrorPageHtml_VariableColumn</th>
<th>@Resources.ErrorPageHtml_ValueColumn</th>
</tr>
</thead>
<tbody>
@foreach (var kv in Model.Headers.OrderBy(kv => kv.Key))
{
foreach (var v in kv.Value)
{
<tr>
<td>@kv.Key</td>
<td>@v</td>
</tr>
}
}
</tbody>
</table>
}
else
{
<p>@Resources.ErrorPageHtml_NoHeaderData</p>
}
</div>
<script>
//<!--
<%$ include: ErrorPage.js %>
//-->
</script>
</body>
</html>

View File

@ -0,0 +1,195 @@
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif;
font-size: .813em;
color: #222;
}
h1, h2, h3, h4, h5 {
/*font-family: 'Segoe UI',Tahoma,Arial,Helvetica,sans-serif;*/
font-weight: 100;
}
h1 {
color: #44525e;
margin: 15px 0 15px 0;
}
h2 {
margin: 10px 5px 0 0;
}
h3 {
color: #363636;
margin: 5px 5px 0 0;
}
code {
font-family: Consolas, "Courier New", courier, monospace;
}
body .titleerror {
padding: 3px 3px 6px 3px;
display: block;
font-size: 1.5em;
font-weight: 100;
}
body .location {
margin: 3px 0 10px 30px;
}
#header {
font-size: 18px;
padding: 15px 0;
border-top: 1px #ddd solid;
border-bottom: 1px #ddd solid;
margin-bottom: 0;
}
#header li {
display: inline;
margin: 5px;
padding: 5px;
color: #a0a0a0;
cursor: pointer;
}
#header .selected {
background: #44c5f2;
color: #fff;
}
#stackpage ul {
list-style: none;
padding-left: 0;
margin: 0;
/*border-bottom: 1px #ddd solid;*/
}
#stackpage .details {
font-size: 1.2em;
padding: 3px;
color: #000;
}
#stackpage .stackerror {
padding: 5px;
border-bottom: 1px #ddd solid;
}
#stackpage .frame {
padding: 0;
margin: 0 0 0 30px;
}
#stackpage .frame h3 {
padding: 2px;
margin: 0;
}
#stackpage .source {
padding: 0 0 0 30px;
}
#stackpage .source ol li {
font-family: Consolas, "Courier New", courier, monospace;
white-space: pre;
background-color: #fbfbfb;
}
#stackpage .frame .source .highlight li span {
color: #FF0000;
}
#stackpage .source ol.collapsible li {
color: #888;
}
#stackpage .source ol.collapsible li span {
color: #606060;
}
.page table {
border-collapse: separate;
border-spacing: 0;
margin: 0 0 20px;
}
.page th {
vertical-align: bottom;
padding: 10px 5px 5px 5px;
font-weight: 400;
color: #a0a0a0;
text-align: left;
}
.page td {
padding: 3px 10px;
}
.page th, .page td {
border-right: 1px #ddd solid;
border-bottom: 1px #ddd solid;
border-left: 1px transparent solid;
border-top: 1px transparent solid;
box-sizing: border-box;
}
.page th:last-child, .page td:last-child {
border-right: 1px transparent solid;
}
.page .length {
text-align: right;
}
a {
color: #1ba1e2;
text-decoration: none;
}
a:hover {
color: #13709e;
text-decoration: underline;
}
.showRawException {
cursor: pointer;
color: #44c5f2;
background-color: transparent;
font-size: 1.2em;
text-align: left;
text-decoration: none;
display: inline-block;
border: 0;
padding: 0;
}
.rawExceptionStackTrace {
font-size: 1.2em;
}
.rawExceptionBlock {
border-top: 1px #ddd solid;
border-bottom: 1px #ddd solid;
}
.showRawExceptionContainer {
margin-top: 10px;
margin-bottom: 10px;
}
.expandCollapseButton {
cursor: pointer;
float: left;
height: 16px;
width: 16px;
font-size: 10px;
position: absolute;
left: 10px;
background-color: #eee;
padding: 0;
border: 0;
margin: 0;
}

View File

@ -0,0 +1,192 @@
(function (window, undefined) {
"use strict";
function ns(selector, element) {
return new NodeCollection(selector, element);
}
function NodeCollection(selector, element) {
this.items = [];
element = element || window.document;
var nodeList;
if (typeof (selector) === "string") {
nodeList = element.querySelectorAll(selector);
for (var i = 0, l = nodeList.length; i < l; i++) {
this.items.push(nodeList.item(i));
}
}
}
NodeCollection.prototype = {
each: function (callback) {
for (var i = 0, l = this.items.length; i < l; i++) {
callback(this.items[i], i);
}
return this;
},
children: function (selector) {
var children = [];
this.each(function (el) {
children = children.concat(ns(selector, el).items);
});
return ns(children);
},
hide: function () {
this.each(function (el) {
el.style.display = "none";
});
return this;
},
toggle: function () {
this.each(function (el) {
el.style.display = el.style.display === "none" ? "" : "none";
});
return this;
},
show: function () {
this.each(function (el) {
el.style.display = "";
});
return this;
},
addClass: function (className) {
this.each(function (el) {
var existingClassName = el.className,
classNames;
if (!existingClassName) {
el.className = className;
} else {
classNames = existingClassName.split(" ");
if (classNames.indexOf(className) < 0) {
el.className = existingClassName + " " + className;
}
}
});
return this;
},
removeClass: function (className) {
this.each(function (el) {
var existingClassName = el.className,
classNames, index;
if (existingClassName === className) {
el.className = "";
} else if (existingClassName) {
classNames = existingClassName.split(" ");
index = classNames.indexOf(className);
if (index > 0) {
classNames.splice(index, 1);
el.className = classNames.join(" ");
}
}
});
return this;
},
attr: function (name) {
if (this.items.length === 0) {
return null;
}
return this.items[0].getAttribute(name);
},
on: function (eventName, handler) {
this.each(function (el, idx) {
var callback = function (e) {
e = e || window.event;
if (!e.which && e.keyCode) {
e.which = e.keyCode; // Normalize IE8 key events
}
handler.apply(el, [e]);
};
if (el.addEventListener) { // DOM Events
el.addEventListener(eventName, callback, false);
} else if (el.attachEvent) { // IE8 events
el.attachEvent("on" + eventName, callback);
} else {
el["on" + type] = callback;
}
});
return this;
},
click: function (handler) {
return this.on("click", handler);
},
keypress: function (handler) {
return this.on("keypress", handler);
}
};
function frame(el) {
ns(".source .collapsible", el).toggle();
}
function expandCollapseButton(el) {
var frameId = el.getAttribute("data-frameId");
frame(document.getElementById(frameId));
if (el.innerText === "+") {
el.innerText = "-";
}
else {
el.innerText = "+";
}
}
function tab(el) {
var unselected = ns("#header .selected").removeClass("selected").attr("id");
var selected = ns("#" + el.id).addClass("selected").attr("id");
ns("#" + unselected + "page").hide();
ns("#" + selected + "page").show();
}
ns(".rawExceptionDetails").hide();
ns(".collapsible").hide();
ns(".page").hide();
ns("#stackpage").show();
ns(".expandCollapseButton")
.click(function () {
expandCollapseButton(this);
})
.keypress(function (e) {
if (e.which === 13) {
expandCollapseButton(this);
}
});
ns("#header li")
.click(function () {
tab(this);
})
.keypress(function (e) {
if (e.which === 13) {
tab(this);
}
});
ns(".showRawException")
.click(function () {
var exceptionDetailId = this.getAttribute("data-exceptionDetailId");
ns("#" + exceptionDetailId).toggle();
});
})(window);

View File

@ -0,0 +1,43 @@
// 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 Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Diagnostics.Views
{
/// <summary>
/// Holds data to be displayed on the error page.
/// </summary>
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class ErrorPageModel
{
/// <summary>
/// Options for what output to display.
/// </summary>
public DeveloperExceptionPageOptions Options { get; set; }
/// <summary>
/// Detailed information about each exception in the stack.
/// </summary>
public IEnumerable<ErrorDetails> ErrorDetails { get; set; }
/// <summary>
/// Parsed query data.
/// </summary>
public IQueryCollection Query { get; set; }
/// <summary>
/// Request cookies.
/// </summary>
public IRequestCookieCollection Cookies { get; set; }
/// <summary>
/// Request headers.
/// </summary>
public IDictionary<string, StringValues> Headers { get; set; }
}
}

View File

@ -2,6 +2,7 @@
// 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.Linq;
@ -10,6 +11,7 @@ namespace Microsoft.AspNetCore.Diagnostics.Views
/// <summary>
/// Detailed exception stack information used to generate a view
/// </summary>
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class StackFrame
{
/// <summary>

View File

@ -1,6 +1,7 @@
// 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.Linq;
@ -9,6 +10,7 @@ namespace Microsoft.AspNetCore.Diagnostics.Views
/// <summary>
/// Detailed exception stack information used to generate a view
/// </summary>
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class StackFrameInfo
{
/// <summary>

View File

@ -13,7 +13,8 @@ using Microsoft.AspNetCore.Diagnostics
#line hidden
;
using System.Threading.Tasks;
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class WelcomePage : Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView
{
#line hidden

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,372 @@
namespace Microsoft.AspNetCore.Diagnostics.RazorViews
{
#line 1 "WelcomePage.cshtml"
using System
#line default
#line hidden
;
#line 2 "WelcomePage.cshtml"
using Microsoft.AspNetCore.Diagnostics
#line default
#line hidden
;
using System.Threading.Tasks;
internal class WelcomePage : Microsoft.Extensions.RazorViews.BaseView
{
#line hidden
public WelcomePage()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
#line 3 "WelcomePage.cshtml"
Response.ContentType = "text/html; charset=utf-8";
#line default
#line hidden
WriteLiteral("<!DOCTYPE html>\r\n<html");
BeginWriteAttribute("lang", " lang=\"", 141, "\"", 223, 1);
#line 7 "WelcomePage.cshtml"
WriteAttributeValue("", 148, System.Globalization.CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, 148, 75, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(">\r\n<head>\r\n <meta charset=\"utf-8\" />\r\n <title>");
#line 10 "WelcomePage.cshtml"
Write(Resources.WelcomeTitle);
#line default
#line hidden
WriteLiteral(@"</title>
<style type=""text/css"">
@font-face {
font-family: 'SegoeLight', helvetica, sans-serif;
font-weight: normal;
font-style: normal;
}
body {
background-color: #00abec;
color: #fff;
font-family: 'SegoeLight', helvetica, sans-serif;
font-size: 18px;
margin: 0;
padding: 0;
}
.content {
position: absolute;
left: 50px;
top: 38px;
width: 440px;
}
.content .azureLogo {
margin: 0 0 65px 0;
}
.content .bodyHeadline {
margin: 35px 0 0;
font-size: 40px;
line-height: 43px;
}
.content .bodyContent {
margin: 10px 0 30px 0;
line-height: 22px;
}
.content .bodyContent a {
");
WriteLiteral(@" color: #fff;
text-decoration: none;
}
.content .bodyContent a:hover {
opacity: .7;
}
.content .bodyCTA {
color: #fff;
display: block;
line-height: 30px;
height: 29px;
width: 230px;
cursor: pointer;
text-decoration: none;
position: relative;
}
.content .bodyCTA.longer {
margin-top: 10px;
width: 440px;
}
.content .bodyCTA div {
position: absolute;
overflow: hidden;
width: 29px;
height: 29px;
float: right;
top: 0;
right: 0;
}
.content .bodyCTA div img {
");
WriteLiteral(@" position: absolute;
top: 0;
left: 0;
border: 0;
}
.content .bodyCTA:hover div img {
left: -29px;
}
.content .bodyCTA:hover {
opacity: .7;
}
.wrapper {
width: 100%;
height: 100%;
overflow: hidden;
min-width: 1200px;
}
.innerwrapper {
width: 384px;
height: 100%;
margin-right: auto;
margin-left: auto;
}
.browser {
position: absolute;
display: block;
top: 400px;
width: 384px;
height: 305px;
cursor: default;
z-index: 10;
}
.browser div {
width: 384px;
height: 305px;
position: absol");
WriteLiteral(@"ute;
top: 40px;
left: 100px;
font-size: 200px;
text-align: left;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.bulb {
position: fixed;
margin-left: 20px;
top: 0;
}
.light {
position: fixed;
margin-left: 53px;
top: 0;
opacity: 1;
}
.bottom {
position: fixed;
bottom: 0;
margin-right: auto;
margin-left: -303px;
z-index: -1;
height: 202px;
}
</style>
<script>
</script>
</head>
<body>
<div class=""wrapper"">
<div class=""innerwrapper"">
<div class=""light first"">
");
WriteLiteral(@" <img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARIAAAESCAYAAAAxN1ojAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAACKhJREFUeNrs3TFPG0kYgOE1kou4IIVTUITiXJAiFFxBk/8vGopQQBEKKFyci7jAhRsX3E4YB3I5Asva3p2Z55EspJNOOq/3Xn8zu7arCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADI1MAhILi/v9+v/wwb/murwWCwcPQQknJCMa7/jOLj3X/+bsKqfiye/F3Gx6KOzcorICSkGY0P9WM/hmK/4/+kZYxLeHwXFyGh3+EYx0cK1lGZh4ewCAm7D0fYyziIjxCOYQZPaxajMqujsvQqCwnbj8dB5k83TCtTURESNheQdTgOCz0EsxiUqbNBSGg+fUzqx8dqc1dVUreKU8qtKUVI+HNAQjSOCp4+mkwpN3VQ5g6FkPAYkHGMh4A0E0LyTVCEpPSAhPs7jqt0LtkKCkJiCVNEUC7dti8kuQdkvYl65GhsVdiUvXKTm5DkGJFwCfdz5SrMroSIXNcxuXEohCSXZcxJZR+kK2GZ89VyR0hSjsh6GTN0NDp3EycUyx0hMYVgOhGSMiJyECNiCumvMJl8cxiEpI8BCeEIm6ku6aYhXCo+t9QRkr4tZU6r7r9AiGZCRM4sdYSkDxEZx4hYyqTrwqeLhaTLiIRlzIkjkYVpHZMLh0FIdh2REBD7IXmZxenEvomQbD0gNlXzFvZLzsRESLYdkS+VTdUSYnLuC5SERERoyxUdIRERxERIRAQxERIRQUzKsucQiAgvCufC3/GcQEga+SwiPBHOhS9iIiRNphE3m/FcTE4dBiF5TUT8LAR/Mo5vNAjJsxEJH8BzkvCSw/iGg5D8FpGRsZUGTuIbD0LyMyLDylcB0NypzVchecoVGt5iaIoVkvU");
WriteLiteral(@"0Er5j1XqXtwqbr5+EpOyIrL/tHdo4Kn2/pPSJxLe9s7FzqeT9kmJDEn+8yq47m7L+YXghKWxJ44e82bRJqUucUicSSxoscYSk1TRyYEnDlpc4EyHJOyLrL26GbTqKy2chyXUNG98xYBfLZyHJcBqxwcoujUvaeC1pIhERdu1YSPKaRsLnaNwGz67tl/J1A6VMJMfOaUzCQtJmGgnrVJd76cqohKmkhInEkgZTiZC0mkZGQoKpREi8E2AyFpJOp5GhaYQeyfq+kpwnkolzF1OJkLT10XlL30KS6yeDswxJ/ISvz9RgKhGSVg6cr/TUX0KSxjRik5U+G8WPbAiJaQQsb4QEnKNC8sKyRkiwvBESpcfyRkiEBIo7V3MLia8LIKXlTTb3OmUTkvg5Br9Vg6lESFr54LzEBC0kXhSEREi8KNDQMJfLwFmEpNQfbsaSXEi8GBCYSLwY0Np7IREScO5mFBJfYkSyctjj2/MigDdCE4lpBOewkHgRIP19khxC8s55SOKS/4yYiQS6Z7PVRAKYSKAHUv/MzZ6XEHoh6X2SpEOS4++DgJCoOBS5RLe0ASEREkBIACEBEBJASAAhAYQEQEgAIQGEBHi0EhIHH9q6E5KODAaDhfMPhASwtPECgOk6j5BY3oCQmEgoXvJvhiYS8GYoJLWl85DEzYVESMBEYmkDnbtL/QkkH5LBYLAyleDNUEi8EJRsGd8MhURIoOxzN5eQfHc+kqh5Dk/CRALdusvhSWQRkrjGFBNSPHdNJJY3YFmTW0jmzksSMxMSIQFTdG4hifskYkIqljl9w19u35A2c35ighYSIaEUWZ2rWYWkHhXDZ25cBqbvVvW5KiQ9N3WeYhoREi8SQiIkvVjeuHpDXy1zW9bkOpFY3mAaEZKNTCUhJL5dnj66FRJTCbQxj0tvIVF+eLObXJ9YtiGJ5XcFh77IcpO1hIkk63cAknOd85PLOiTxS2NcCqZrq3gBQEgS9s15TMey36/LPiSmErqeRkpYYu8V8mKaSuhsGsn");
WriteLiteral(@"hd2uExFRCd8KVmiLexPYKelFNJezadSlPtJiQxKnE3a7syiL3KzWlTiTrdwifwWEXLkt6skWFJN7t6tZ5tm2ayw9fCcnzMQl7Jb6OkW0JE+9VaU96r9AX+9L5zpZclXC5V0iqnxuvPofDps1L2mA1kTwIG69L5z4bXNJclPrkiw1JHD/Pnf9syEWuX1okJC/HZFEVdNMQWzPL+btGhOR1MQlXcdw+z1stS17SCMmvzis3qtHcj+VxiVdphOT/p5JwIpw5EjR0FZfHxROSx5gsjKg0MC31Uq+QvByTcGI4OXhJuF/Em46Q/DEm4QSx+cpzwuTqtgEheZXzyudx+J3NVSFpNJWsN1/FhKcROSv5pjMheXtMvlYuC/MYEW8sQvKmmCziZCImZRMRIRETWrkQkVf8f+IQvM79/f1+/edL/Rg6GsUsZ85L+6YzIdldTE7rx8jRyD4iljNCstWYDONksu9oiAhC0jYmYTIZOxpZWcTljEu8QrLToJzUfw4diSzMKzebCUmHMZnUfz47Ekmb+uyMkPQhJuO41HFFJy0/fjrCp3iFpE8xsQmblmVcythUFZJeBuVT/efIkei18P2qF/ZDhCSFpU7YiHW/iaWMkNB6qRMmk4mj0QvzqvCfjBAS0wmmECERkx/TyaSyd7Jr06rQ3+IVkryDMorTiTtitytcibn0gTshKWG5c1y5VLxpYf/j2jJGSEoLymFc7tg/aScsXW7jryYiJILiaDQPSP24sQ8iJPwalPCwh/KKJUz18OPdAiIkPBOUcQyKTxb/ah6nj5lDISS8PijDGJO/Cl72hOkjhOPWzWRCQvuo7MeoHBQQlVWMx8z0ISSIingICYlEZRSDMo6PlL4TZR4f//g4v5DQv2nlQ/Vws9v7qj83vYX9jUUMx527ToWE9OIyjkugUfV4aXlbl5gXcZkyj3/vwj9zmVZIyH+CWS+H3jdYGq0j8XAimTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
WriteLiteral("AAAAAAAAAAAAAAHL0rwADANq3ok68n5URAAAAAElFTkSuQmCC\"");
BeginWriteAttribute("alt", "\r\n alt=\"", 7518, "\"", 7586, 1);
#line 169 "WelcomePage.cshtml"
WriteAttributeValue("", 7545, Resources.WelcomePageImageText_LightBulb, 7545, 41, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 7587, "\"", 7636, 1);
#line 169 "WelcomePage.cshtml"
WriteAttributeValue("", 7595, Resources.WelcomePageImageText_LightBulb, 7595, 41, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(@" width=""274"" height=""274"" /></div>
<div class=""browser"" style=""opacity: 1; visible: true;"">
<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYAAAAExCAYAAAB1UXVvAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAGcxJREFUeNrsnUuPHcd5hqvJIU0bkcJQgkXGMOgYshHJsM0MhMBwEFlxsjDsjQBvsrQRL7LzT0j0C5xFFgogAzSQRTYGnEUCb+IwCWIohkFScSwnsayQkiwOb8O5cc45fS6d/nou6jOnL1Xd1dWXeh7iiNTMmZ4zfaa+t7737aoOVAZ/9q0/Px//9VL8uBI/vnT44ZcUAAB0nVupxxvx49p3X3v1ZtYTg4zC/5348XL8OM95BAAYBCIAr8RC8INMAYiLv8z2/5nCDwAwWK7GIvDNo/85nZr536D4AwAMmivr6y8EN67/9Jr8z6nDD36H4g8A4AV/EU/6P5EIwOHs/xucEwAAb/j2UQfwEucCAMArkrq/pg4u9WyMvQ//lrpz4XeO/z7Jhd076onRI3Vx8//UUzt3eFsAAJrnirg/IgBfsn3k8Mw59cuPrSePh09cKnxuWhTOzsbq8t031fpbP1K/EYsCAAA0JwIiANbCXyn8P7/8B+q/PvFFFa6dM//6tQ+E41LcEbz4s+8jBAAAzXD+9Pr6C6/aONLtZ55X//j731LvPf0pNT+1Vvt4Yhn9PBaSIP4jYgAAAFb5nzUbR3n9ua/FM/8vNvIKrz/75cQm+pMbf6vOTse8ZQAAljhV9wD/+tmvN1b8jxABkO5CLCYAAOiAAEjxF7/eBRImIwIAAB0QgBvP/rGz4n9SBAAAoCUBEEtGvPk2EBEQ8QEAgBYEQKyfNhHxefjkJd49AIAaGF8FJLNvuUSzbf7jd7+mvvqT17");
WriteLiteral(@"Se+/nPf453GgC84Y03/rMZAZBFXlW4cv60evm3z658/Afvh+rm1tz4eGJDyYM1AgAA1TCygCT0rbLC9wsX1qwW//TrAQAABwJw+5nnjL+BFP6vXDxjvfgfvJ7neQcBAJwIwEfNCq4Uf7F+mij+gnQjWTuMAgCARQEwLbRZxX88j9Srb0+sFP8jNi58kncRAKBJATC58iev+F+9HaqN8cLqD/DwyYu8iwAAFdC+CkhHAM6dDtQ3Lp9VF8+t6orU/awsQIertya5nwvXPsy7CADQpADUKf7C+TNB8gAAgG5wytaBvvLMmdzi3ySEwAAALQvAD+9O1X/vzp3/ACwEAwCohjULSELev3s3zL30c2saJQ8AAOiZAOjem1eu8VdqVQTEHXr94cx6l3B2NuJdBACogLYFdGH3jvZBsxZ6SUj8px/P7g7q8NTOBu8iAECTAvDUzp14tq1/T14Rgdc3Zysfz7OIqnJx823eRQCAJgVAuHz3TaOD/3BjemgJNSMCIkiEwAAALgTg3i+Mv4FYQXkiILuE1sFUkAAA4AOMKrAUXAmDTW8Ic5AHhCtbQsvK4PNng6RTqML6Wz/Sep7uzREAABCAkqJb5ZaQIgI3t+xdsfOpX1/XvjIJAABWMV4IJoX3KYMrgppAvH/d2T8AAFgSAOEPf/b9Vl/0+lv/xOwfAKANAZBLQl9sSQQu33tTfebWj3nnAADaEABBrCB5uESspxdb7j4AALwXAEGKsSsRkOL/1Z+8ps5Ox7xrAABtC8CRCDQ9KxeRofgDANjFym6gUqBlr6B/++zX1cMnLll7cXK1zxd+8Q/OrSYAAATAAAmGX/73v1a//Ni6uv7sl40Xi53kM7d/nFztw6wfAKDjApDuBuQhQnD7mefU7Y8+ry8icRdx9PUUfgCAngnASSEQ5LaNGxc+efzvI8Q2+lBc6OXvS5tvU/QBAIYgAGlkx86jXTt/j3MOANAJTnEKAAAQAAAAQAAAAAABAAAABAAAAIaD1lVAp55dV+O1c4f/F8");
WriteLiteral(@"R/UgQ6RwhWnxaUfYXSfkKg8dWB5jcJ9H4gAKjJaDZX79x9yIlogI/vvqM+Mtu3IwB3PnJJbX3o/ErhLCuVQXGlNTyGqQisfjQoOY5u6UciAOoxjyL1vw8eq/D805yMBnh69MCeAKwQpf4K8gtilPpXcLJ0Gh8j4zmpT0aZYhAtfST3WFHRMQxfEwCU8u72SIXzBSeiZeovBItSBbG0kEepohlUPEYVMVj9yqhACBADgOa4uzdR2+MZJ6IvAhAlfzQKXfTBjL7oedFSV9CuGJR1BYgBgD32wrnaiAUAetwBlBa6E/ZO3vNWLaIcMdASlOLXIp9cfV51MQg0zxFCAHCA+P63tvY5EX0XAKNCR15AVwAQ86vNfTVfRJyI3gmAzMSjQ/8+CKoXOvICxAC85P3dsRpN55yIPgpAunAdCYE1MbCRF9iwiFSWvUNeAFCXzdFU3X8cciJ62wGo7LbNihjYyAuMj1HyWgotInMxIC8AX5HFXjL7h14LwEGRKpzRGogBeQFdAQwfCX3f3R7j+w9BAExmquQFWEQA7+/g+w9KAEyLE3kBYgB+cn8/TLx/GIAAJHU8pzI6FYPKeUFQ4xh18gI9iyh7jUK9LgygLRLffwfff1AdQJT6R6DciYGdvCDfItI/Rs7rqWgRLR2LrgAGQrLY69GIEzE0ASgUg6D6TJW8AIsIhoMUfzZ5G5gARGWfi1LFp02LKF3IyQsQA3CKbPK2F7LJ2yA7gLLLQNNi0D+LKC0G5AUApmxPZmzyNlwBOEiBU2VZbxbqQAxcWkRmgoJFBH4glo/s7w9DFYDoZAsQ5ZXJcjEgLzAWAywi6DK3tkYs9hqyABzX/5XqUVgms4sPeUHhiyUvgD4hM38Wew29A8gqGCViQF5AXgDDRhZ6sdjLkw5ASwxWLKJyMSAvyHk95AXQYdjkzbMOoGiGGOV2BWkxIC8gL4AhcLTYC9/fIwHQKQomFpFW8SEvKHyx5AXQBuL7s9jLJwHI2QvIlhiQF5AXQD+QTd62xyz28k");
WriteLiteral(@"oAIo2qpGURZT6xRl4QVJ+pkhfQFYAZeyGbvPnZASwV6YxNzKx0BenvU98iMpmpWs0LbFhEjsQAiwh0SXz/rX1OhJ8CkG1qrMzqrYlBj/MCG7e4NBYUt3kBFpF/EPp6LABRh8SAvKD9vICuwC/kck82efO8A8gfzNHKLDIo+SLyAvIC6Aeyydv9xyEnwmsBiHQGc4mpQV5Q0d4hL4B2kMVebPKGAFSYzZMXGNky2vaOg7wg83JQ8gLfkND33e0xvj8CkLkZqEEBJy/QKnRdyQtKZ/TkBT4gl3uyyRsCUDxIjQs4eQF5AWLQddjkDQHQFoNqBZy8wFgMyAsQAwfg+yMA5RZQ2QDN+GAXLSJdMXBpEeUei7yAvKBhjjZ5AwQgUwEizaJRfTbfzbzA5ZbVWoWugbzAflew+pOQF3QbNnlDADQqjt5AJS+oLwZD3bI6973CImqNu3sTNnlDAJTeUEuNThMxIC8oFwPyAsTANbLJ20YsAIAAFDlA2YPYQAyGahGlxYC8IP+T5AXdQywfNnlDAIz7gECzM2jeInIjBl28xaVWoSMvoCso4NYWm7whABUo3g4iIC9Q5AU2LKLc9wqLqDayyRuLvRCA8mIf5V8GWjxkFXnBCYvo+HnkBcZiQF5gD1noxSZvoH8VUOXBTl6QJwbkBfmfJC9oDlnsJbN/gGoWUOXB3p28wIZFtCQGNiwiR2JAXuBvV8Amb1BfACrPHruTFxRaRKkPlhWFSMsiqiAGFvICKxaRViEnL+gLstgL3x+MBcD+7JG8oMwiOn5exbzAikVk3PGRF3SV+/shi73AXACiRmeP9cWAvMCRGJAX9DYvSHz/HXx/qNIBRAfz1yC3bNqaPZbkBUH5ACQvsCsG5AX97wrE9//VJou9oLIFFB2LwMFArXAduo28oKJFVFcM3OYFgX7xiTp2SalWIScvcI3s8EnoCzUEYLUb+GCgBg5mjz7lBT2+xaVxx+fAIsq0d/zJC2STt70Q3x9qCEBUJgZBtolBXmBXDLzLC2");
WriteLiteral(@"zc4rLU3hluXrA9mbHJG9jpAHRab2tiQF5AXpBz4sgL9JBN3rizF9i3gAzFgLzA3CJa+hLyAvICQ5I7e7HJG1izgKLqYkBe4M4i0io+5AWFL3YIeYFc7sliL7BrAckMMtDrDILcwU5e4EoM/MgLAktdo669Y2YR6diQpl1YGbLJmzwArFtA6U6gSAzIC/TEgLygbseXbxFV6xrrW0R576uLroBN3qBRAWhaDNxaRNnTPfICRV5gSQxcWkSJ78/1/tCEAESHf/LmkrbEoCgv6KJFlDnYyQvsW0TGHZ9/eYFc8SNX/gA0ZwFpGAtH4528QJEXtG4RZRpug8sL2OQNmhWAKF8Mmu4K0hZRbTEgL+hNXuDSIjITlG5ZRI9DNnkDFx1Azj0hTboCm2JAXqDICxoQgz5tWX1wvT+bvEHDAhCdtAGC+haRrhgUWkTHA5W8oEmLSEsMyAsKX2wTecHbm/uEvuCoA9Ac7FXEoHJXkBYD8gLygtodX3/yAhZ7QSsCYDLYV40F8oKmLKLM8kVeYN0iMhOUZvKCnfFMPdgPqV7gyAKKNItGiRiQF7gRA/ICN2LQRl4wns3Ve2zyBq1aQDpFLHJjEZW+JvICpxaRlhiQFxS+2Ly8YB7/9d72OAl/AVq1gHQGl628wEpXkBaDrlhEqnxvefICu2LQ57xgY3ecdAAAbi2gkt9aEzEYTF5gY8vq1Ch3aRFllq8aeUGQ07JUzguCirN5Ndy84MEoVI/Y5A1a6QCi6HA4B8szvwoDlbwgRwx6nBcUdwXLsl7XItJ6P06IQWcsoopiMJ4t4tk/d/aC1i2gEy1+yQgiLyAvKLKI6opB725xaSwoSi3i1/4OoS+0bQFFGYVjqSxbsoiKZn46YkBeUGc2T17QTMdXPS+QTd6mbPIGXegAigrH0qyOvKDm7DFnkZDBvWjt5QVBzQ4j43PkBUonL7j/OEz2+gHoiAWkZydkigF5QcXZoz2LqJoYlJga5AUVO75ii2h/Oo8FAN8fuiAAUf5IKg8Zyy");
WriteLiteral(@"0inYFKXmBXDMgL6ltE9jq+5bMplg+LvaAzArBU/yvZO+QFdmeP5AWlwt3jvOC9nRGLvaCbFlB5C68rBsPPC4osInuzR/KC0veqR3nBnd1JctknQCcFQH+g6tkJQ84LiiyiZmaPHbaIjDsM//ICuavX9pjFXtA5Cygy30HSsCtYavHJCyrNHm2KQaFFlPpgFy0iXTFwaRGVdXwy67+7R+gLPbGAtAoQeUG+GJAXtJ4XuNyyumjsyGKvO3vj5G+A7glAtFoBtYvvyYFqZO+QF+jMHskL+p0XiO8/wfeH7lpAJ1YC1xCDavYOeQF5wTDzgs3RVO2FMyoRdN8Cyh5Xyya5dvFV5AVe5AVcUprbFYxY7AX9EIBIwwpYnQqTF5AX2NiyukkxaOsWl+L3/3pnTAWC/nQA2jNa8gLrFtHx9yIvqGA3ZXyu5bzg/d0JoS/0RwB0PM9Ci6iCGNjIC6qtUWjWIqorBuQFdeym9vMC2eRN7B+AfghAKgXWbnOLxMBhXtBFiyjjVFQTXpsWkSMx8D0vkN09t1jsBX0SgChnoFYWA/KCRi2i2mLQ47zAhkW09DtmwyI6PM5sEbHYCwZgARWsCA1MjlPTIsoeqCZiQF4wtLyg0CIymLxEWhaRvhgs4uJ/Z4fFXtBTAdAdqC4tovKBWjbzIy8gL3CTFzzYD9WEO3tBPwUgqjRQm7CIjNr3AVhEGbqo311liQF5gfO8YHcySx4AvRSASHuY5Q9U8oL6YjDYvCAwfE9rWERpMXCRF4TzSN1jsRf0ugOIDovP8Xg1EAPygkwxIC9If7HLW1ympzTN5gXi92/sstgLBtEB5A32/KpKXkBe0KRFlD1JMJnNN5sX3N8Lkyt/APrdAagTm8FlDvbiqtpGXuCbRZShi/rdVZYYkBdUzgsejafqMYu9YCgCUPgLvzLYu5EXVLaIeiQGLi2i2mLgSV4gN3d5NGKxFwxMAIzEgLzASV7g0iJKiwF5QfYvp9zMncVeMCgBiDQ/H5QOdvIC8oLs349e5w");
WriteLiteral(@"Wp42ywyRsMrgNIXQVkXHwzBzt5gSuLSEcMyAuUlbzg0ShUIYu9YLAWkOZA1bKINMRguHnB8C8prS0GPcsL9sK52mGxFwxTAFZuCqk9ULXEwLu8oOAWlxXEoIu3uEyLgVuLKP3FbvICmfUT+sJgBSBSJ6OwwHigFg588gJv84IuWkTZk4TsFyqh78P9Kb4/eGABZc9drVtEy4JCXlDXIjp+DnmBsRiU2ZAy88f3B28EIEsMgpw+mbzAhhiQF3Q1L9gdz5IbvAAM2wKK9GZ9pWJAXqCVFwRlPVelNQo5FlHuccgLir5n4vtzZy/wpQMwH+zkBYU/U8WuIC0G1TKHAjFwmBcUWkTHvx/dtIjE77/3OKR6gJ8WkNlgJy9o1iIqF4Mu5gU6q4a7mhfIzV0IfcEfC0hDDPTCQQcWkYYYkBfoiQF5waoYyLX+kxmhL/hmAZUMsuoW0WrVJS9QFS8HJS9oMi8YzWSxF74/+G4BlRUx8oKMDsMsL7DRFaTFoIt5gZVLSo9/P5q1iOaLiMVegAAY2wnkBYUWkVHxVdzisvG8IKfzfDhisRcgAFbEgLyAvMCFRVRJDDK6xq24+E9Z7AUIgB0xaMIiqi0G5AXkBRlP2J/OkwcAAlBDDJq2iJbtnQqvibyAvODE108XETt8AgLg2iKqKwbkBTYsonIxGHJeIN9vc8T1/oAAtCoG5AXkBS4sopPfb2s8Ta78AUAAemMRpcWAvCD3GOQFhWKwH87VeIbvDwhAJ7uCuhbRsr1TQaAyj1GeF1i3iDJaJfKCenlBOFvg+wMC4IsYdGbL6rpiQF5QuysQx2eLHT4BAeinGJAXkBfUEQMp/tj+gAB0XAzICwzOEXmB1u/H7mTGnb0AAeiTENgTA/ICn/MC2d2TxV6AACAGqhd5gWWLyKj4qmHlBdN5pLbZ4RMQgP7jTV5QYBHVFYMmbnGZLwbt5gXyo8v2zqz1AgRgYJAXOM4LKtk77eYFu+FMzUh9AQEYLuQFFYVp4HnBeLZIHgAIgCc4t4");
WriteLiteral(@"g0xIC8IPsnajIvmMU/0y6LvQD8EgAjO8HGLS7Thdxzi2hJDFrMC8Tx2RlT/AG8FgAjO6EreUHhltXmYmDFIqogBjbygmprFOLiH87UnNQXAAEw7QrMxYC8oKm8oIpFNJrOubMXAAJgVwzIC7qfF8jNXVjsBYAAWBcD8oJu5wWLJPRlsRcAAmBJDMgLTF6LmUW0dJ4t5AVyvT+2PwAC4KwrMBcDD/KCAosot7vK6goynpz3qf0pi70AEICOiAF5gbu8QHb3ZLEXAALQGTEgL3CTF8wJfQEQgC6Igcu8wIZFtCwGgcZsfvkDbecF8tfjuPjj+wMgAJ3vCszFoNktq5cFpfjVt5EXlAmBFP85vj8AAtBnMSAvMN+yejJfsNgLAAHovxiQF5jlBXK9/wjfHwAB6KsYkBcYCFOqVZJ/7oVs8gaAAAy4KzAXAz/ygn1CXwAEwFcx8DkvEN+fxV4ACIC3YuBrXiCFf8JiLwAEwDcx8D0vkEk/oS8AAkBXYEUM+pMXyJw/8f35NQBAABADfTEYQl4gts+C1BcAAQAzMeh7XiC+/3SB7w+AAICWGAwlL5BZ/2SG7w+AAIC1rsBcDNznBfJf2d4Z4wcAAQAHYmAlL7BhEamD6/3x/QEQAHAkBlbyAgu3uJSburPYCwABgIbFoGt5gcz6Q3b4BEAAoP2uwFwMqucFyVYPrPQFQACg22LQRF4wIfQFQACg+2Jg2yKSa/0JfQEQAOioGDRlEc0jQl8ABAB63RVUEQN5Prd1BEAAYKBiUCQEYv0w9wdAAKDnYmDaFcj1/jg/AAgAeNYViO8/p/oDIADglxiICBD6AiAA4JkYCGzvDOCeU5wCaBuZ+TP3B0AAwDPE92exFwACAJ6xIPQFQADAP6TsE/oCIADgITNCXwAEAHws/pHC9gdAAMAzFoS+AAgA+AeLvQAQAPCUWYTvD4AAgH/FH98fAAEA/2CxFwACAB4idZ/FXgAIAHgIm7wBIADgIVzxA4AAgIfMF/j+AAgAeEeyyRvFHw");
WriteLiteral(@"ABAL9gkzcABAA8hU3eABAA8LL4s9gLAAEA72CTNwAEADyETd4AEADwFHx/AAQAvCz+kWLuD4AAgGewyRsAAgAewiZvAAgA+Fj8FZu8ASAA4CWEvgAIAHjInMVeAAgA+AebvAEgAOAhLPYCQADAU2YRvj8AAgD+FX98fwAEAPyDxV4ACAB4CIu9ABAA8BQWewEgAOAhXPEDgACAh+D7AyAA4CHJYi9m/wAIAPiFlH2sHwAEADyETd4AEADwsviz2AsAAQDvWBD6AiAA4B9s8gaAAICn4PsDIADgZfGPFHN/AAQAPIPFXgCAAHgIm7wBAALgKWzyBgAIAMUfABAA8IE5i70AAAHwj2STN6o/ACAAfsFiLwBAADxlFuH7AwAC4F/xx/cHAATAP9jkDQAQAA/B9wcABMBT2OQNABAAL4s/m7wBAALgHWzyBgAIgIewyRsAIAA+Fn/FPj8AgAB4CaEvACAAHsImbwCAAHgIm7wBAALgISz2AgAEwFPY5A0AEAAfiz++PwAgAP7BYi8AQAA8hMVeAIAAeAqLvQAAAfAQrvgBAATAQ8T2wfcHAATAM1jsBQAIgIdI2cf6AQAEwEPY5A0AEAAviz+LvQAAAfCOBYu9AKBh1nSe9Ol7b6jZqTOcLQCAHvBkuG1PAH5T82AAANAfsIAAADwWgGucBgAA77hJBwAA4CdbIgD/wnkAAPCL77726jURgJucCgAAr0jq/lEGsMX5AADwhr9PBCBuA6T4X+V8AAB4w9WjDkB4hS4AAMALXokn/reOBeCwC/ij+HGLcwMAMFj+Kq73f3n0P6eP/nHj+k831tdf+F78z0n8uBI/znGuAAAGwbX48c24+P9N+oP/L8AAx5G6SMzC+fMAAAAASUVORK5CYII=""");
BeginWriteAttribute("alt", "\r\n alt=\"", 16724, "\"", 16791, 1);
#line 172 "WelcomePage.cshtml"
WriteAttributeValue("", 16752, Resources.WelcomePageImageText_Browser, 16752, 39, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 16792, "\"", 16839, 1);
#line 172 "WelcomePage.cshtml"
WriteAttributeValue("", 16800, Resources.WelcomePageImageText_Browser, 16800, 39, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(@" width=""384"" height=""305"" /><div>:-)</div>
</div>
<div class=""light second"">
<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARIAAAESCAYAAAAxN1ojAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAEf1JREFUeNrsne1LHFkWh2+3otGxscGQTHSCMkLCZtj9MB/2//+8HxZ2QjJEcDE4ZlaJ0KFNxzQ22TrmVKY1/VbVt6ruPfd5oOjJQKL10k/9zrm3brUcmOHLly9r2cd6tnWybSXbNvRzM5BfcZhtn7PtU7aNsq0vn61Wa8DZi5sWhyBaaWyqKPLPTuS71FfRiFQ+ZXLpc5YRCfiVxoqKomNEGosiUrnSz34mlyFXAyKBcuLYCqg0CaE06ucbYkEkMLlUEWl0E0ocvhLLJX0WRJK6PHZUHmsckaWQ5m1PtkwqPQ4HIkEegFQQCUyQhwjjoQoEedQvlUvKH0QSs0B2VB70PMJARHKhSWXE4UAkoaePxyqQFY5I0KXPBSkFkYQmEEkdj9zX3gfEQ1/LnksOBSJpunwRgTDXI25kTso7yh5E0oRAdh3NU4tlj/RRzhEKIkEggFAQCQIBhIJIbAlEmqdPEQhCybZTmrKIpKhAZBTmiWMOCNxFmrInLHOASOYJZEUTyA5HA2bQV6HwBDIi+U4i0gORoVwmksGiSP/kXer9E0TyVxnzk2MuCJQvd05TfkAwaZFoGZOnEIBl6alQkit3khUJozFQESMtdS4Qif0UQjMVqiapZmxSItFeyAEpBGpMJ0nMPUlGJJlEJIXQC4Em6Gk6MTuyY14kuj7IoWNEBppFSpxjq+ufmBaJNlSllGFeCITCqcVGrFmRUMoApQ4iWUYgkj6eUcoApQ4iKSuRTZUIpQzEgJlRHTMi0fVCDrg2IUL+");
WriteLiteral(@"zGTyDpE0LxH6IRA7l5pOouybRC0SZqmCMaRfchSjTKIVCU1VMEqUTdgoRcIkMzDOSJNJNDKJTiSMzEBCMjmOZUnHqESCRCBBTmIYHo5GJEgEkAkiQSIAhmUSvEiQCED4MglaJEgEIA6ZBCsSJAIQj0zaSAQgOg502VBEMkMiK0gEYC6HesNFJEgEoDS335VQZBKMSHh2BqCUTA71u9MowTRbs4Nx4HiKt2m2sm214N+5ybYrDl2jNP7UcBAiYT2R2pDFsNez7cHYlv/ZByKVj2Nyuc62z/rfNxz+SullIjlOViSsbFapNLY1ZazrZ5Ncq2REKh+QSyVcZDI5TU4k2ij6G+ffqzjyzxjIpdLTT8SyPI3MMWlMJNog+rtjhKYs0suQNPdQxbFqYJ8uVSqXmmCgHL/XvZZJkyKRJMIITXl5WG9MS1o5RyqlkFXWXtfZfG1EJDRXC5PL43Gi+y8yea9igcXoZyI5MisSfY3mIed5ofSxp/J4wOG45UZlckZKWYjaXnNRq0h0rdUXjr7ILEQa+wmnjyIpRYTS41DM5KiO5RrrFgl9kel0VR4IpBgy2vMWoUxF+iQvq+6X1CYS+iJT2dJSb5tDgVAqovJ+SS0i0Ueen3E+KWFqEorM8GTa/l3kLX4X0YpE54tIX2SNc3lL3kTd51BUyrkKhUluf5U4MiQ8jFUkB46H8XJ2tIxhFKYebrTcOeNQ3DLIRPJ7dCJhqPdOGfPc0QdpCilzjih3bqlkSLgykVDSfCMvY1a5hhvnTBNK6uXOS98lTpUiSX2UhhRCOgkV76M4lYiEUZrbXshzUkjQvNUtVbyO4lQlklQnnok4pCfEkG4cyFDxq0RLHa8T1byv2ZpJ5FGiEpFS5h9IJCqk7Pyna37RpyaQHuZTX/+YV5Fog3U3wZMio1O/JnpBWkiRvyZ6A9jx9X4c34nkqUvvgbzHmkToh8TNc91S40lQIlGz7XDxQeQ3hV8Suyl0dN3kYBLJk4QO/qoKhH6IwbifYMLcXfbdOF5E");
WriteLiteral(@"ojNYO4kc9FVHU9U6W3qOU3mUYW3Z69lXInmayAHPJUJTNQ2ZpNRAf7RMKllaJFpfpTANHomkR0rnfGWZVOIjkexyQQHn3gRPdDnUekWSSBpBIpDSNVAqGLSb+KFcQBDptfDM2R/N2SmTSkqLJJE0cohEYIx8NMe6TAoHhHadPywymCcC02Tyi/F97BYdwSklkgTSCK+FgFlsO9szmguP4JRNJJYXLOo6pr0DN5tC80oKi0SfqbG6TIDMZHzBdwQKlL9dw6lk4X0rk0isppFVlQhP8UIRLF8zC/dBC4lEh4WsGpgRGih7A7LafF3T5+i8JxKrNeGOo7kK5ZHm677h74Z3kVhcbyRf7R1gGfaNpvXuIhPUFhaJDvlaXP2M1d7BF1Znvj70mUgsppE9x3tnwG+6tVjizP3uLyQSjTYdTjrAQjcnayXO3KbroonkocETTkkDlDieUknbxz8S6UGhpIEq0+6esX2a+fzNXJFkf1lmsVp6riZ/Gx5Alew7e2u+dpdJJNbSyJ5LZ1FfaL58RiTz/nKkkZMGK9TFtrHvz9Typp1YWYNEoG5+TiGVzEsklsoaeY6GafDAddeASCzFMhqsQBKuqLxpJ1LWdB3DvdAcD6ynkvacSGYFShoglfijU0QkVsoaa3cD4DqMI5FoDWTl2RpGaiAUfjSyHyva+pibSKxIZJU0AgFhaV5JNyWR7HHtQmBYubFtLSKSLU4aQGXXpIUngzszRaL9EQuvm5DJdDxTA9zgKkJfTTM1kVgpax5yvQIldz2pxKpIaLJCyDww0j7YmiWSDSNlDQDlTbVsWk8klDXAza56vs0nuSOS+5NMIi5rSCRAeVMPG5MSCWUNAOVN4fKmPa3moawB4KaXciJhuQCIqbyJfa5TZ5JIYm+0yvx/3lUDpJIakRfotcf/QBoBaOTmFzvr44lknZMCwM2vTHnTNlTWkEggRqQUj30YeGVcJCukEQBugCXYGBfJBicDoBFiTyTrlhLJFtcjRMoPkf/+a+Mi2eRkAHAT");
WriteLiteral(@"LMOtSKa9zzMyWMQIYibqHl/bSBqh0QqxE/X0izYnAYBE7UskG5wEgEaJuk+SiyT251MQCcRO1N9BK6UNIoHYiXoelJXShh4JQAAiiX34l0QCFoi2T9Lm3AEEQ7R9EgsiYWo8ACJJ1+IA94i212dlZiuABaLt9VlptgIApQ0AIBIAQCQAAIgEABAJACASAEAkAACIBAACEUmfQwHQODckEg4+wLJ8RCTNccX1B4BIAMBIaTPiBACQrpcVySdqSwBIvbQhkQBpBJGkfRIAXOTtBSvzSK65DiFyeiSS5vnMdQiU582LZEBpA9AoUQ8Y3Iqk1WpZGP6lvAFuhgGUNkOMDtAI11ZKGyH2PgPlDXATbIbRuEhin5T2gesRIqUX+e8/GBdJ7H0SEgmQSJphOC6S2OeS3CATIJE0L5KRgRNCeQNcs02WNq1Wa2Bgh3pclxAZ7w3sw/D+zNbYyxsSCXDN1oyEkPsiiX0uyQ0ygYiQ+SOx9/Vuw8d9kVgob95zfQJppL6yZpJIPhnYsUuuT+CmVxuD70SS1ToWXkthIS6CfW6M3PSuJiUSK+XNOdcpkJyrJx/tbU8zDCcJgLJmDt8qGKuJRMobRm8g5OvTTFkzTSRWXt/5P65XIDFXymCqSLKaR4ZzhgZ2UvokrC4PIXJmZD9mljaWUglNVwiND87Gan6D8ZUVrYvkjOsWAuMPI/txZ1DGukisNLWA6zE0enNFon2SgZEdJpVAKLy1siP3J6+2F40ukZuToWBoGmn8nxv6TrlFRWKpJHjLdQwk4wZEolNfR4Z2nFQCTaYRSyLpF0kkE81DKgEolUaszGkaaA81WZGQSqAJro3dxCa2PGaKJDNPz1B5QyoBrjk/N+RiIjGaSpjtCnVxZex6m1jWpCiS/A7BMzhQB/81tj9TR3LnisRgeSM1K5PUoGrODd6Ee6VFMs9EEacSlmOEqpDEe2xsn/rTypqURWIxdkI4HBssn2c6YCGR6OS0gbED06PEgQr44Ow19EfzyrR2gX/swuBJ");
WriteLiteral(@"lxLnmmsfPJY0bwzuV2987ZFlRWKt6Zqf+Ndc/+CJN0ZvTHNDxMIiUSNZfEn3lWOiGvjpIVjsJQ7yV074SiRWy5u8xGH6PJTl2mhJs/B3vpBI1Ex9owfslWOiGpQvjy1eO6PsO79QymqX+McvDV8Qv/G9gIIcO7tzkhauQAqLRA01NHrgrgxHVPDPubP97NbC+9Yu+QPecXFA4nwwftO5nDfk60MkFoeCx3njaL7C7OT6yvg+FgoLpUSiprowfiBfOZ7Hge+x3FwdTyOF2hftJX7YufFUkjdfkQncvyasz4Yu3LooLZJEUolcOEeOYWFI58ZSOI0sm0hSSCV5PfwbMkmeVNJpqYGUpUSSSCpBJvAmEYmUSiM+EkkqqQSZpF3OpDIdoPS0jqVFoqnkNJEDncuEpQfSkUgvkf0tnUZ8JRLrs10nyeTfjtGcFCSSyjleOgy0Pf4ypwleaExa40ZhgYsis1grFYmuNt9P6OCLTP7jmE5viQ8Jlq7D7Lu79CMvbc+/1EmCF5909I/5DkbPud4YUmume6kkvIpEmzUXCV6EZ44RnZiT5RuX5lPffa0kwhKJIjFplOBJkRPyL0cTNiauXVrDu5VVEK0qfrsvX750s4/DhC/Qfd0gXC41haSaIv/00RupVCQqk2fZRyfhC1VkKsfgAd/Z4EqZY5d2k1warC99/oNVimQt+3iRbSsJn7BVTSZ7fH+DIF+MKPUJhUeZSLyOsLaq/G0zmTzKPp5y/ZJOSCHBIHNGvM/5alX9W1Pi3Ekne47eSd2cO5vv4i1V0mTb62UnnzUlEkqcu0gqeZ5t2xyKSpHRM3lRfI9DUV1JU5tIVCY72ccB5/G7cufnbNviUHhF+h9vKWPqKWlqFYnK5FC/PHCXx1ru0D9ZDildzhyvX52EvHbz9yp/QJ0iWdESZ43zilAqEMiZow8yiZGWNIMqf0irzj3KZCJN12ec27lC+dHRQ1m0hLlEIDM5WfS1m9GIRGWym3084fzOpatSecyhuIPMBfnD2X11");
WriteLiteral(@"rE9ksaKTOn5Qq4m9o19SiFWVyV7CZc+1iuPMMZlsUQZa0tTy3FtTIqFfUo4tlcpOAlK5UXm8J30Uppa+SOMiUZlsuq/9EuaXIBXk4ZdjX8sDBC8SlQnzS/zwQIUi5eK2lkOxID2PnoqDJRiWx+tTvVGIRGUiz+I84vx7Tyvb+vmDC2fSm/Q3Pqo48k/wRy+TSCOr9bVC2PtMJgd6R4XqkLSyruklb3RXNcR8pXV6T8uVj/r/GKatjlqbq6GKRPok0i/Z5HpoLMHk5dAPBUqjXBLf7ogcykYQebxsSiLBiGRMJozkABSXSK0jNJNoh3I01KbHLs31XgHKcty0RIISicrkts5DJgALcVLVsgBRi2RMJrwnBmC+RIKZa9MO8QipZU+4VgAmchqSRIIVicrkEpkAfIc8iBfcS+haoR81Zr8C3JFIkDfXVgxHD5kAhCuRaESCTACJhCuRqESCTCBRTkPsiUQtEpVJV2XC8gNgnZPQRmfMiERlwlomgEQQCTIBmMLtoyKhzFg1LxKVCU8NgzWJHIXw7ExSIhmTyYFjMWmIm0bXE0leJGNCYaU1iBVZx+UkVomYEonKhOFhiI1G1lhFJPNlQhMWYmCkKcTEqnIti2dI+ybyEq4O1ysEiPRD3sbYVE1KJGNC4fWgEBoyN+Q05n5IciJRmXQ0nVDqQNOlzGlMk8wQCaUOUMogkgqFIsPDu6QTqJGLTCCn1neyldpZ1VGdfcdsWKiWoQtocWZEUp1QaMRCZSkk295Za6gikukykZdxHTh6J0AKQSQehELvBJbFxAxVRLK8TEQi8rwOLzOHIvQ1hQxTPgiI5HuhSJnzk6MZC/PLmFMrU9wRSXVC2dFyh5eawzjSQL1IuYxBJOXKncfu6/IE9E/A5PR2RFKvUHYd652kLJB3qfdBEIk/oaypUGjIIhBAJN6E0qXkQSCASHyUPPRQEAgi4RB4E0rXMcoTI7ejMNl2ThMVkYQkFRHKjmNV+9CRR/ovrK4PgkjsCGVNy54uKSWo9NFT");
WriteLiteral(@"gQw4HIiElAJFkGnskjx6lC+IxIJQ8l5KF6nUUrrk8qB5ikiQCiAPRAJFpNJxzE0pSk+3PvJAJHBXLJsqlC3HokuTUseVpo4+hwORwOJi6ahQRCybiSWWvopjoKmDZikiAY+JZUOlsmEotYg0hnnqYIgWkUD9cpG5KusqlTXdQkwvIxXFcEwaQ6SBSCCOBLOiclnX/70xJpl1t/ykOZHC57E/X+nnTbZ9EoEgC4DE044mHoCJ/F+AAQAgl3zNeDGxuQAAAABJRU5ErkJggg==""");
BeginWriteAttribute("alt", "\r\n alt=\"", 23261, "\"", 23329, 1);
#line 176 "WelcomePage.cshtml"
WriteAttributeValue("", 23288, Resources.WelcomePageImageText_LightBulb, 23288, 41, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 23330, "\"", 23379, 1);
#line 176 "WelcomePage.cshtml"
WriteAttributeValue("", 23338, Resources.WelcomePageImageText_LightBulb, 23338, 41, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(@" width=""274"" height=""274"" /></div>
<div class=""bulb"">
<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAVoAAAKSCAYAAACTAhMyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2OEMyQkI4M0Q4NzIxMUUyQTdDN0Y3QzMzMkU0QTgyQiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo2OEMyQkI4NEQ4NzIxMUUyQTdDN0Y3QzMzMkU0QTgyQiI+IDx4");
WriteLiteral(@"bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjY4QzJCQjgxRDg3MjExRTJBN0M3RjdDMzMyRTRBODJCIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjY4QzJCQjgyRDg3MjExRTJBN0M3RjdDMzMyRTRBODJCIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+zKbSDwAAExlJREFUeNrs3b1uXFkBwPF7UbaABiNBB9qJQEABWruEJuMSsSxOgaBix0BBl+QJ4jyBsx0FaLxPYKdAovPkCexIFIhF8tADMd0WKJdz7Du7E68/Z+bcz99PupnsJvHHmev/nDlz5968KIoMgHS+ZAgAhBZAaAEQWgChBRBaAIQWQGgBhBYAoQUQWgCEFkBoAYQWAKEFEFoAoQVAaAGEFkBoARBaAKEFQGgBhBZAaAEQWgChBRBaAIQWQGgBEFoAoQUQWgCEFkBoAYQWAKEFEFoAoQVAaAGEFgChBRBaAKEFQGgBhBZAaAEQWgChBUBoAYQWoCvuxV/yPDcSQOsURTG8+P9CzyYN+xrLXwDaEdZB2B6H7ai4Xvzznfj3hRbgdrFaC9u4WMy4zuAKLdCGyG6F7XWxnPjvR0IL8MVI7RarNRZagHSRrSW2Qgs0NbKjIq1Rhd+L0AKNi+xgBWuyt1mzHVQV2nvuVqBhnoZtLfHniB8/LiFsXhHH4cX/t9TxuWa0QMNms1Van49r2PZvmAWPL4uwpQOgTaHdrTi04zLuh3f8dzHIa7f8nrL87BdvwQWaEdqTcDOo8FOezi0lLPJvN0M/j4UWaM2yQbg5admXfWNsY2OdvQtoikELv+azF9VuWkYQWqDqmetaeZzs/vxhXOGPDlv6LcUX1B5f9xcsHQBVRjYGqYrDt+pYQrgfWnpq6QCoM7LxuNXdDkZ2toSwZekAqDuyo45/mw+EFqhz");
WriteLiteral(@"uWDUg291cNUfWKMFUkY2PqU+6ehywUWnoaVfu2QMzGiBpLZ6EtlrCS2Q0oc9+l6PhRaow3qPvtep0AJ16NOywWjuhDPD+T/wYhiQTNHv0wNuh7buOakMILRpxROLTywdAClNev79x7cbW6MFknrR8+9/GH+xdAAk07M3LFwlN6MF0hXm/GxWH/V+HMxogQpmtoezp9E9E9/EsGFGC1ThYXbNO6c67Fn8RWiB9E+d8zyecGVjFp6e2Avf88HZ92/pAKhSeRHGR9n5UkIX36IbZ+7PZpE9O5TY8cQASR9YLB0ApCa0AEILILQACC1Afe4ZAtqiKIp4KFB8z/w0z/OpEUFo4W4RjQGNIR2G7d3s/NLNs+2yvz//n/G4xdPy9p/xNoR4YlRpCm9YoM64xiukPsjSHbgeYxtP0zcJ+/ixEaem/dwbFqh8pxuGbRy210W1TsK2U74rCYSW7i0LhG1Uxq4JDi9ePA+EljYHdqeG2etdZrkj9xRCS1t3rlGDA2uGi9DS6p1qPWxHRTuNy6MfQGhp7A61U7Tf6/JoCBBazGLNbmlLaB1Hy7I7UZz9jbNuXuU0Hnv70LvQWDa0znXAMjvQ43Czn3X3UtLxTRRH5Vt/YWFCy6KRjbPY3R58q/FB5NBhYCzD0gGLRraP4dkOPyt79gAsHSCy6YzNbDGjRWSrseEkNZjRkmJnGYnsZw69QIYZLauO7DDGxUi8Jc5oN8PPzqmh4KYZrdBy004SX3U/ybp7CNcyDsLPzkPDgKUDltXl42SXtVUeSwyWDlj4kThGZNdIXCsuHWx49xiWDlhk5xiEm6PmzmbjOToas9/GS+Vs2muwdMBd7TZ7ySCfC27tho6vxdIBd30EHmaOMrirabmE4CgEzGi5laeG4M4GYfPCGGa0mM0mFmez981qMaPFbDadNbNazGi56ZH37PyrRmIp0/DzdN8wYEbLVR4ZgqUNXHOMi4SW2aNufNorEKvxoSFAaLlMjKy32q5oLF3YEaHlMj83BCt/4AKhRRg8");
WriteLiteral(@"cCG0VMKLNx64EFrSe2AIkjyADY0CQsuMy7KkIbQILYKQ2HuGAKElc5HBpAaGAKElcrxnOh7EEFrODA2BZwwILXjGgNDSal6wAaHFjKuCp/jprj02NLoILcTIFoVhQGghHSe+R2gh8Xz2TcqlAxBayMOPQW5Wi9BC6toKLUJLOi6NnRUpZ7QT44vQ8soQgNBCYkmXDabGF6HFU9uUCc9zoUVosUab0LEhQGiJMy4xSMdsFqHlMxNDkIQXGhFaPMX1AIbQUpWXhmDlTvM8F1qElnMhCAdGwWwWoSU9sV2tF4YAoUUYPHAhtNQQBsfUrmgs8zw3lggtbyvDYBa2Gh8bAt76+SqKIv6QGQlml8Y+MhJLmYafp/uGgbmfKzNa3prVxuNpJzXukg35GEv5yJ6EGS03PfoOw82hkVhIXH65b30WM1pumtVOMseALjybFVnMaDGrTWcatg2hxYyW24oz2j3DcCdPRBYzWu70CByshe2kvOWGB6bwM7RpGDCj5a7i7OyZYbjVOG0bBq4jtFzneeZNDDd55nI1WDpg0aWDGUsIV4tvtX1oGLB0wCqeGlt//KJjSwZYOkBU0j74bDvKAKFl1fYyL459NsN3UUuEllR2MsfXPhFZ7uqeIeCiG14c3S5fLBv1cGjicsGePQShpYoQ9y22cbngoYstsvDPjMO7WFTYd2Joxz2IrDVZlvk5EVqW3omG4WY/6+ZxtsdlZB1dwFKh9WIYyy4jxKfTG2WUuuR5+N6cjYuVEFpWEdt4+ZYY2y4c/jVbKnjinmVlPyOWDljx06RR1t51W+uxWDqgFbPbvez8ZDRtJLJYOqA1sY1Puyct+7K9EQFLB7Tu6dIgO790eRuORnDibiwd0MpZ7TRrz6W3nTAHM1pa/Wgez2U7aPCX+NwRBpjR0nZNPuTL5XqohNCS9inT+VEI04Z+eQfekIDQ0hUfm23T6wmHNVpSC/tYPPLgdcO+LEcaUNX+b0ZLBY/m50/Pm3Y13Y/dM1RFaKnKi4Z9PS6jjtDS");
WriteLiteral(@"OU0KmxfBEFq6pwzbpCFfzkv3CEJLVzUlcBN3BUJLVzUhcKdOHoPQ0lkNubihyCK0dF7dobM+i9DSeVMzWoQW0nrV89AjtNDt0HkhDKFFaNPyJgWEFqFNzGwWoaX7ykvcgNBCR1k6QGghsVeGAKGlL6yVIrTgKTwILUBr3DMEVO0n739gEDCjBUBoAYQWAKEFEFoAoQXgRg7vonI/+P7/avvcf/mz8Udo6YG//s1uR79YOgAQWgChBUBoAerjVQkq56gDhBYSc9QBfWPpAEBoAYQWAKEFEFqAzvLyL3X4OGwvL/uDf3zy9wf/+fe/hot+4B++t/7sy1/+ylV/PDH01KIoCoNAkwzibrngdmj4aGRjhZYGGi8Y2qGhQ2jhdoYLRPbEsNHU0N6zfHC5PM8NQn0m5XaXGeozw0ZTeTGMpvpo9puvf/0b6++8887a/B++fv2f408//fR07n/tGTIaO3EzmzWjbbrf/u73h5fMbjf/9Mc/TIwObVg6cBwtQGJCCyC0AEILgNACCC2A0AIgtABCCyC0AAgtgNACILQAQgsgtAAILYDQAggtAEILILQAQmsIAIQWQGgBEFoAoQUQWgCEFkBoAYQWAKEFEFoAhBZAaAGEFgChBRBaAKEFQGgBhBZAaAEQWgChBUBoAYQWQGgBEFoAoQUQWgCaEto8z5fagkFRFI/Ddhh+X1zcgv1wOwrb2h0+JoAZbQjoWth2wm9PQhx3wza8IuRb4WYc/u7JmzdvHrurAKG9XWQH5Qz26R1mznFGuxtiux8j7S4D2uZexZE9iuFccKliK36M8NsNdxtgRnt5aPcXjexcbNfDzHbX3QYI7RcjuxMjuYqPFT5OfAFt6K4DhPbzyMYXvx6t+GM+ddcBbbGyNdoyqKPw2wdhW5v7/6fLLhlcMqsdho+7Hm6P3YVAL0IbAxu23VUH9YbPGZcPhBbo/tJBeYzruMrIlh64+4DOz2jDrDK+qaCuowAcUwt0f0YblwsMIUCiGW05mx0YQoB0M9r1mr92");
WriteLiteral(@"L4QB3Q5tmNG+V+cXHt+48ObNm3jCmbFzIABdndHWLsR2ELZ4aNlJeR4EgO6ENgTuVYOCu+aFOaCLM9pGrZGW568F6NSM9iDMIqeGEOB6S71hIcR2O9wcGkb47G3hcXs3u/rQx5dhixOUSfj5MVER2luFdhJ2rhjbcQN28j3XDaOG/W4Ubn4ettsuXQ3n/m0M7UHYPhJdSwc3xXYv3DyscxkhfO7j8HU8cXdS4T63E492KScZi74+EGe98Vwh8aiZeKmmdSNrRntdbOOj8kF5Fq8HWbXvGHsRYx+20/C53aOkDuzs/B6r3sfjx42Xa4oTlydxfzbaHQvtqp5yl7Pbvbq+GUsHJAzsWhnYUeJPNSqD+zAuzRl5SwfQl8jG2ethBZGdiVE/DJ/3sdEXWuhDZOO66VFWz7k9dsPnH7sXhBa6HtnDrN5zH4/EVmihq5GNcR1nzTjB/Kg8jAyhhU4ZZ/WfCvStr8fhX0ILXZrNxtljE8+dse/eEVroypJBU88EN4hvlHAvtc89QwBviYdUNflE8o9CbJ9f94aG8sEiLjMMw/bV7PMlkPhvXpW38VwLrlIitFDLbPZRw7/MtfLBYOeSr3+U3Xzeha25vz/NnGvB0gFUbJS14zL2jy4EdmvB8y4Mss/PtTB2lRKhhSp82JKvc62Ma7yNx/nuZ8ufeyE+yBx5N5qlA7js6X4MzDBss5MZDeaiMy23uBYZ1yYPrlrbLD9Omw6fepSt/jjfsxcC44VXy3NNY0ZLn33wwfvDcjY3e8o8KoM7uPDUeFg+PY5/53V5OsLhJR9y2LIhGGbpljm8G82Mlj771re+mf3ql7/Ivve97z5d8EPMTkc4Cbfbcy8CPTC6X4htZmYrtPRvFpt98LOfrnJGGF8Eiud+fZ5Vew7lNsX2VTk+CC1d95vtX2c//vGPUnzoszXJrF3rs1V6GsbnwOFfy8nLpwdGgsb65JN/HH3nO98WwvrsWUJY3FljhZaG76SzF7qo132z2sVD66gDmryDbolsYzwy");
WriteLiteral(@"BJYO6F5k46FL8dCtNaPRCNPQifuGwYyWbmn6yV36ZuB8uIsTWpo6m/VUtXmGhmAxDu+ijpAOsvM3DsTDqgYX/vhldn5qP7PZ5nGfCC0tCWx8R9fIrKmV3jMEQkuzIxvjumtWZEYrtJAmso6Fpde8GEbqyO6IbGe49I3Q0sDIDrPzNVm64b+GQGhpHpHtlokhWIx3hpFyNntoJDoZ2ngI3p5zH9z6Z0FoSbZzeQGs++IVdLevu/Q5QkvanSuep2BgJDovRnYzNMQLZUJLDTtXYRR6Iy4hbJjZXh1aL4YBy4rPXHYNw9XMaDGjZVWcHNyMFkhsyxBcTmhJxcymf941BEJLtSaGoHecGFxoqdgLQ9A7jjoQWqqU53k8mH1qJHrllSEQWqq3bQh65cAQCC3Vz2on4ea5keiFiXeHXfOz4DhaUnPeg17YENor938zWiqZ2W6b2XbatshaOqAZsX0SbjYzh311STzK4GG4b/cMhaUDmvdUKh5v+WF2ftxl3Fz0r13i7DUevvfciWRut3QgtDTeb3/3+3gC8eGF/735pz/+YbLkD8AgcyrHOwVWWBcLravg0t+nc+cnQJkaCVKzRgsgtABCC4DQAggtgNACILQAQgsgtAAILYDQAiC0AEILILQACC2A0AIILQBCCyC0AEJrCACEFkBoARBaAKEFEFoAhBZAaAGEFgChBRBaAIQWQGgBhBYAoQUQWgChBUBoAYQWQGgBEFoAoQVAaAGEFkBoARBaAKEFEFoAhBZAaAEQWgChBRBaAIQWQGgBhBYAoQUQWgChBUBoAYQWAKEFEFoAoQVAaAGEFkBoARBaAKEFQGgBhBZAaAEQWgChBRBaAIQWQGgBhBYAoQUQWgCEFkBoAYQWAKEFEFoAoQVAaAGEFgChBRBaAKEFQGgBhBZAaAEQWgChBRBaAIQWQGgBEFoAoQUQWgCEFkBoAYQWAKEFEFoAhBZAaAGEFgChBRBaAKEFQGgBhBZAaAEQWgChBUBoAYQWQGgBEFoAoQUQWgCE");
WriteLiteral(@"FkBoARBaAKEFEFoAhBZAaAGEFgChBRBaAKEFQGgBhBYAoQUQWgChBUBoAYQWQGgBEFoAoQVAaAGEFkBoARBaAKEFEFoAhBZAaAGEFgChBRBaAIQWQGgBhBYAoQUQWgChBUBoAYQWAKEFEFoAoQVAaAGEFkBoARBaAKEFEFoAhBZAaAEQWgChBRBaAIQWQGgBhBYAoQUQWgCEFkBoAYQWAKEFEFoAoQVAaAGEFkBoARBaAKEFQGgBhBZAaAEQWgChBRBaAIQWQGgBEFoAoQUQWgCEFkBoAYQWAKEFEFoAoQVAaAGEFgChBRBaAKEFQGgBhBZAaAEQWgChBUBoAYQWQGgBEFoAoQUQWgCEFkBoAYQWAKEFEFoAhBZAaAGEFgChBRBaAKEFQGgBhBYAoQUQWgChBUBoAYQWQGgBEFoAoQUQWgCEFkBoARBaAKEFEFoAhBZAaAGEFgChBRBaAIQWQGgBhBYAoQUQWgChBUBoAYQWQGgBEFoAoQVAaAGEFkBoARBaAKEFEFoAhBZAaAGE1hAACC2A0AIgtABCCyC0AAgtgNACCC0AQgsgtAAILYDQAggtAEILILQAQguA0AIILYDQAiC0AEILgNACCC2A0AIgtABCCyC0AAgtgNACMCcvisIoACT0fwEGAL+BBlr+j4JHAAAAAElFTkSuQmCC""");
BeginWriteAttribute("alt", "\r\n alt=\"", 31229, "\"", 31298, 1);
#line 179 "WelcomePage.cshtml"
WriteAttributeValue("", 31257, Resources.WelcomePageImageText_LightBulb, 31257, 41, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 31299, "\"", 31348, 1);
#line 179 "WelcomePage.cshtml"
WriteAttributeValue("", 31307, Resources.WelcomePageImageText_LightBulb, 31307, 41, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(@" width=""346"" height=""658"" /></div>
<div class=""bottom"">
<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABLwAAADKCAYAAACv61n1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAKsZJREFUeNrs3VtsXPed2PEzc87ceBlxJFKKR6Iskk5sL1U1m6hoyVYdF4VhAoMt7D64LwEmfUqQPGwKC32owTgbgy/BGNuXBA7ysNA2C7RddJ3dxQBFXTQQ7I4LrNEkgp2E3shkZVqOJVO8Dzn3nj95KFPk3M7M/9zmfD/A0VDkmXPO/M9l5vzm9//9g4qPZfOpaQUAAAAAAAB9Jejz1/+vOAQAAAAAAAD6i28DXkZ2V0J/nOIwAAAAAAAA6B9+zvA6DHTRrREAAAAAAKCP+DngNX3sEQAAAAAAAH3AlwGvbD6V1B8Sxn9Ft8YEhwIAAAAAAEB/8GuG13Sb/wMAAAAAAMCjCHgduMyhAAAAAAAA0B98F/Ayui8mj/16Uv99jMMBAAAAAADA+/yY4TXV5Pd0awQAAAAAAOgDfgx4NQtsTXI4AAAAAAAAeB8Br/a/BwAAAAAAgIf4KuCVzadaBbVi+t+nOCQAAAAAAAC8zW8ZXtM9/h0AAAAAAAAu57eAV7sMLgJeAAAAAAAAHuebgFc2n0rqD4k2syX0+RIcFgAAAAAAAN6l+ei1Xu1wPpHl9TaHBgDguGuZXN3M/G/dSAdoNQB+vQZyPQQAOMlPXRonO5zvMocFAAAAAACAd/ki4GV0U0x2OPukPn+MQwMAAAAAAMCb/JLhNW3x/AAAAAAAAHAJvwS8pkzOP8mhAQAAAAAA4E19H/AyuieS4QUAAAAAAOATfsjw6iZbK5bNp6Y4PAAAAAAAALzHDwGvaZufBwAAAAAAAAcR8JL/PAAAAAAAADiorwNeRrfEWJdPT+");
WriteLiteral(@"jPT3CIAAAAAAAAeEu/Z3hNO/x8AAAAAAAA2IyAV2uXOUQAAAAAAAC8pW8DXkZ3xF67JE7qy4lxmAAAAAAAAHhHP2d4TbtsOQAAAAAAALBBPwe8ZHVHJOAFAAAAAADgIX0Z8DK6IU5KWtwkhwkAAAAAAIB39GuGl8ysrFg2nyLLCwAAAAAAwCP6NeAlOytrikMFAAAAAADAG8jwcmZ5AAAAAAAAsEjfBbyM7ocxyYtN6MtNcrgAAAAAAAC4Xz9meFnV/ZDi9QAAAAAAAB7QjwEvq7ofXuVwAQAAAAAAcL++CngZ3Q4TFi0+qS8/xiEDAAAAAADgbv2W4WV1t0OK1wMAAAAAALhcvwW8rO52SMALAAAAAADA5bR+eSFGd0OrR1KkcD0AwPOuZXJ1L2//WzfSAfYiAL9eB7kGAkBn+inDy47sq1g2nyLLCwAAAAAAwMUIeJk3xWEDAAAAAADgXgS83LseAAAAAAAAdKEvAl42dzNM6OtLcugAAAAAAAC4U79keNmddUXxegAAAAAAAJfql4CX3XW1rnLoAAAAAAAAuJPnA15G98KEzatN6uuNcfgAAAAAAAC4Tz9keE37bL0AAAAAAABogYCX99YLAAAAAACAFjwd8MrmU6Iro1MjJlK4HgAAAAAAwIW8nuHlZJZVLJtPkeUFAAAAAADgMl4PeE35fP0AAAAAAAA4xrMBL2OURKczrMjwAgAAAAAAcBkvZ3i5oYZWIptPJTmMAAAAAAAA3MPLAS+3ZFdRvB4AAAAAAMBFCHj17iqHEQAAAAAAgHt4MuBldCOMuWRzkkY9MQAAAAAAALiAVzO83JZVRfF6AAAAAAAAl/BqwMttdbMIeAEAAAAAALiE5wJe2XwqoT+4bWRECtcDAAAAAAC4hObBbXZjNlUsm09NX5+9+T6HVG/SuUw8l76xSUtAlmuZXP347966kQ7QMgCsvM6YZeV16fj2cQ0E4LfrIAB/8mKXxssu3a4pDicp/k06l5mjGQAAAAAAQLc8FfAyRkN0a/");
WriteLiteral(@"dB6njJ8aI+zdAMAAAAAACgW17L8HJzUCmRzaeSHFLdE90ZjX1MhhcAAAAAAOia12p4TXpg++5yWHXtMNA1ns5lpnPpG9REA/qcjJofVqCOCACug1wHAQDeRoaXXFc5pHoy2+RnAAAAAACAjnkm4JXNp0RR+JjLNzNp1BlDd+aa/AwAAAAAANAxL2V4TbOd/Ut0YdQf4kd+NWPU9AIAAAAAADCFgJd/t9NtXmzwO7o1AgAAAAAA0zwR8DJGP0x4pE0nOay60ii4RbdGAAAAAABgmlcyvLwURIpl8ymyvExI5zLjSuPMOAJeAAAAAADANK8EvLw2+uEUh5YpM01+HzdqewEAAAAAAHTM9QEvY9TDpMfalSCNOXNd/g0AAAAAAOAEL2R4eTF4lDDqjqEzrYrTE/ACAAAAAACmEPCyDsXrO5DOZURAK95q/xs1vgAAAAAAADrihYCXVwNHVzm8OjIjaR4AAAAAAIB9mps3zhjtMObRtk2K+mPXZ2/ucpi1NNfhPP+VpgIAuMm1TO4Z/SFDSwDw8XXwkv7wCi0BwI00l2+f10c7FAG7dznMGjO6KnbSXXGW1kKbD1t1WfO/dSMdoEUBtLmGPGPc4D3jxetgu3m5DgLo4DpyybgOfp3WAOBWbg94eX20QwJerXVakD6ezmVmc+kbeZoMAODgDd4zissCXQBg83VwRH/4jj79sT6N0CIA3My1AS9jlMOEx9uXwvWtmRmB8Tl9IuAFAHDiBu8ZhUAXAK6F31MIdAHwEDdneE33QfvGRB2y67M33+dQe1Q6lxEjM5opRj+nUB8AAGDvzd0zCoEuAFwLv25cCy/RGgC8hICX9UQdMgJeJ5mtyzUuan7l0jc+oukAeOgmoe70NlCPqav99oxCoAvoi+sh18Cer4V/phDoAuBRQTduVDafEl0Zk33SxtMcZg3N2fQcAADM3OD9XH8Q0zO0BgCuhQS7AHhX0KXbNdVHbZww6pHhUTM2PQcAADOeoQkAgGshAO9za8Cr37KiKF5/RD");
WriteLiteral(@"qXEft3vIunzhm1vwAAAAAAAJoi4GWPqxxqj+ila+IszQcAAAAAAFpxXcBLjGrYh+2c1F9XjMPtoTmHngsAAAAAAHzAjRle/VrkneL1yn53xniPbUEdLwAAAAAA0BIBL16X3XrN0Bo3aoABAAAAAAA05KqAlzGaYb92/aNw/QEZXRKp4wUAAAAAAJrSXLY9/VzcPSbqk12fvfm+z485GcGqF/XpJ5y+/eVaJlfvh+1460Y6wN4E4OVrYS/bwDUQAAC4hdu6NPZ7FtSUnw+2dC4jgl1xCYuaNmqBAQAAAAAAnOCagFc2n0roD8k+b2+/1556TuKyGK0RAAAAAAA05KYMLz8EgxJGnTK/mnXpsgAAAAAAQB9xU8DLL939fFm8Pp3LjCtyg5pkeAEAAAAAgIZcUbQ+m0+JkRn90t1PFOZ/24fHmuwAVTydy0zn0jfe5zSG38gsak2BaQBcB7kOAgDQj9yS4eWn2lZJI8DnNzMWLPNFTmEAAAAAAHCcWwJefuvm58fi9VZ0QaSOFwAAAAAAOEFzyXb4LQAkXu+7fnmx6VzGqnpb06I2WC594yNOZXdq1eWELiQAAAAAAKs4nuGVzadEsXq/dfHzW0ablQXmZziNAQAAAADAUW7o0ujH7n2xbD5l3etemB/Qp6dc9HqtDEo5Nlrj4vLElJi4jAAAAAAA4C5u6NI47dO2F4ESq0YY/Io+Pa5Pv3X6RYqRFPWHcQtXMeeCY/c2lxIA8B6ZI/0BANdBAHAXRzO8svlUQn9I+LTtrQz0fVU5CHq5geWF5S2sEdbJPvRrwBYAAAAAANdyukujn4MFiWw+lbRo2aI746iyMH/RBa/TjmCU7XW8FpcnDoO1CeNnAAAAAADgEk4HvC77vP3lF69fmBeZXQPG/xyt45XOZeKKPcEoJzK8ppv8DAAAAAAAHOZYwCubT4mRGSd93v5XLVjm00d+vubw67MrEDWezmXGbX5tl5v8DAAAAAAAHOZkhhdZMYqSNAJ/Mh2t3XVxf8RG58zauC");
WriteLiteral(@"7bsrwWlyeOB2snjd8BAAAAAAAXIODlPHntcFCza/TYb50sXj/Xp+ua5ngGAAAAAMC9nAx4TdL8+2QGShrV7PqqEy8qncuI1xW3cZUzRs0wp45djmcAAAAAAFzCkYBXNp8SwRC6gB2QGShpVLPLqQyvFx1Yp11dKMnwAgAAAADAxZzK8Jqi6R+KGQHA3hzU6rrY5G9OBL1mHVin5d0aF5cnxLHbKFgbM/4GAAAAAAAc5lTAi2yYR8kIlLQKatnardEYMdGJfTzn8LHLcQ0AAAAAgAtodq8wm08l9YcETf8IESj5mx6X0Sqo9ZTNr2fGoXaMi9phufSN9y3eV1buRwAucy2TG9EfvqNPf0xrAPDpdfB5/eFPaQkAgJc4keFFce+TEkYgsBetglqjxgiOdplzsC0tW/fi8oQI1LYK1iaMeQD0xw3eiD59T/9xSZ9e0acRWgWAz66Dl/Tp5/qPb+jTJVoEAOAlTgS8rtLsDXUfCDyo0TXQZi47uzXOOtiOVgbbpiXNA8D9N3nfUwh0AfD3dfBPjevgM7QGAMCLbA14ZfMpkf2SpNkb6iUQ+HQH89hSuD6dy4iAU9zBdpzWt8Gq9V+WNA8A9yPQBcDvvkMTAAC8zO4ML0axay6ZzadiXT63k2DWRWVhftSG1zHjgraUnuW1uDwh9k0nWXiTxrwAAAAAAMAhdge86O4lu30OanN1Gsiyo3j9nAvacc7hfcNxDgAAAACAgwh4uUs37WMmiGVpHa90LjOuP4y7oB2tqCE2adG8AAAAAABAMtsCXtl8imBXe9200TUT81pdx2vOJe0YT+cysw7uG451AAAAAAAcZGeGF0GADpgKDC7Mi5EZL5pawcGIjlaZcVFTPidrQYvLE6L2nJm6XDHjOQAAAAAAwAGajesiANAZEfB6v8N5uwleiW6N/1f2RhsjI865qB3FtrwicZ9085zbHM7+cy2Tq9MKALgGAgAAOMuWDK9sPpXUHxI0d0fMBAa7qcllVeH6WZe147hRU0yGaZueAw");
WriteLiteral(@"AAAAAAJLCrSyM3/51LGAHCTnQTvBo1RnaUbc6FbdnzNi0uT4hAbTfB2oTxXAAAAAAAYDMCXu7Uvr0OanENdLl8K0ZrnHFhO844fOxy3AMAAAAA4ADLA17ZfEpkuSRpalM6CZQ83cPypRauT+cyYnvHXdiOMrLOLjv0XAAAAAAA0CU7MrzIcjEvaQQKW+klaHVRWZgflbi9c25tyHQu0/W2LS5PiJEZJ3tY/aSxDAAAAAAAYCM7Al6Mzii73Q5qcPUasJJZvH7Oxe3Yy7bJCNYS8AUAAAAAwGaWBryy+VSMG/6utWo3GcEqKXW80rlM3OX7uJc6XpMS1j/JoQwAAAAAgL2szvDiZr97rYJI1yQsX1YdrzmXt+O4UWNM9j6wcxkAAAAAAMAEqwNe3Oz3IJtPnWy/hXkxMuNFKSs4GOmxV7MeaErT27i4PCG6lMqovxUzlgUAAAAAAGxCwMvdGrWfzBEWZXRrnPNAO845fOxyHgAAAAAAYCPLAl7ZfCqpyMmQ8bNGmUFflbj8nmqBpXMZkTkV90A7zhi1xswg4AUAAAAAgEdZmeF1lebtWcIIHB4lc3TFUWPEx24956G27DjLa3F5IiHaXuZ+NJYJAAAAAABsYGXAi6wW2e14UHNrQPLye8kYm/VQO846fOxyPgAAAAAAYBPNioVm8ynZGTJ+JgIlbxo/P23B8kUQ7Q2zT0rnMuOKt4I4Zup4XbZg/WKZb3M4w4uuZXJ1WgEA10EAAOAlVmV4kc0iT9IIIApfsWD5F5WF+dEunjfnsXaMp3OZtsfl4vKEqDs3acH6J41lAwAAAAAAi2kWLfcyTSvVlLIwf08RNbesIeqCmc0+mvFgO76oT6+0mcfKYK1Y9rtuaIhsPnVOORgUQQT3zhnTUTv6dNt4vHV99uZtTkMAAACg6efrIeOz9RV9Ovz5uFuHn7P1z9e3aDXAWpoFJ7pVGTJ+JgIlpy1cvqjjZTbgNefBduykjpeVx65YtmMBL/3cFAGuZ5WDYOW5Dp4yc+S54o");
WriteLiteral(@"05r0/v6G/OeU5JAAAA+J3xJfKs8Rm7k/uIK0eeKx7eOfIZe5sWBeSyIsOL7ozWtOkTFi7fVFfJdC4z59V2FLXHcukbHzl0/DpybuhvpuKN9WtH32C7MGi8kT9rBL9E3bef8cYMAAAAvzE+X7+g9N7rZcaYdvRl8vkakMyKGl5kd0lWKGvaYKhsbbDkYARIMxdmr2q67YvLEyIDyso6WzFjHXa9EU/p0w/0H8V0ReKiRfBLBNBu6Mt/gTMUAAAAfiAyuo58vpZ5T3T08/XXjO6RAHpkRcCLDC/Jfr16ZjSmVYYtXs1XTcw75+HmnHP42LXl/BBvlPrDDxW5ga5Gb8zf0Nf1I6O7JAAAANCXjC96f2TD5+v9z/F8vgZ6F5R8ERA384xEJ9nSenw0rFYHLF7NU53MZIx0OO7h5mxVx8vzAS/xbZAIQBlvlHYRWZ0/0Nf7LGcrAAAA+onx+VoMfPUN5SAgZQdRG+yHfL4GeiM7w4sotAXuFwZG1EA9FFGrUQtXM6oszF/sYL5ZjzdnvFENssXliYT+kLBh/QljXVa8GYvz74biTLdi8eb/Em/KAAAA6BdG10LZ3RfNEJ+vX2JPAN2RHfCiO6Nk790fHS3XgvuDC7ikW+NcHzTrjMPHrvR1GcEu8WY86HDbEvQCAACA5x0Jdjldo/pZgl5Ad4ISLwhJxZ4MGV9Z2RoaOfw5qlWsLl7YsnB9OpeJK94uWH+oUdDuso3rl7quI2/Ggy5pX4JeAAAA8CwXBbsOiaDXN9kzgDkyM7wYndECH20Njx7+HArWolqwFrJwdReVhfnRFn+f65NmHU/nMg/rkC0uT8RsPn4njXXK4qZg16GXKLQJAAAAj3rJhfe3z/OlMmCOzIDXVZpTrpWtoaFCWXukbldUqzhZvH62j5r3aPDOia64UtZpfNPj1mDzd7VQmRMZAAAAnmGMxujWXi3f1LfvHHsJ6IyUgJd+0olslSTNKdcHDxInsq0cruM110fN63TAa1LCeSeGRH7exW187vGnf8");
WriteLiteral(@"mJDAAAAE8wgklfc/Em7g8UxZ4COiMrw4ti9Ra4szl8IuAVVatWB7wa1vFK5zJiH8f7qHlnjJpkghMZUjLOGdf34x+7sKzEz9znZAYAAIAXiM/Xgy7fxivZfGqWXQW0R8DLpVZ3o9GNYqRhkfrBUNnaoNfCfKOg11wfNvPs4vKEOHZjDqw7pq+76xpXRv99T9TNu/DF9zmhAQAA4GpG7wmvDND1DfYY0J6sgBcF6yVb2jg10uxvDnVr7MeAl3hNThZW7yVQ/IJXGjl++r4yGF/npAYAAICbveChbT1HAXugvZ4DXvqJ5lSGTF9bWo83HS0xrFZtLVxvjGjYj1l8Mw6/rukuzzkRpPNUkPkLl/6ekxoAAACuZNTumvHYZhPwAtqQkeFFd0YL3N0eahrwUgP1UEStRi1c/aiyMH/xyP9n+rGNR0LF8fVyxMnAUWJxeSLRxfOe91pbnz73MSc1AAAA3MqLNbGuMGIj0JomYRlTNKNc790fHW03j+jWWKyqexZuhujWeMf4uR+7Mypj4V3ls1JsfCRUXHNwM0TA+G2zb25ubtfdihb8/c5gZH0vEnqw/vk4B4FzK8rug1ElWo5ykgMAAMB5C/OiZvLk//74d/+6UgueOfz1xfhWIapWao8N7RRd/gpEoO4NdiTQWE8Br2w+ldQfEjSjXLfXT7UNeEW1ypBSjFg5/N1Xjlw8+3IUkEsDm8pmJSy6a95ycDMuKyYCXkZ3Rtd9k7O2Fw393SdfGPl4eyi2uhuNPLzAFD8PbpWHPlVK2pai1lRlsDSgPP3tP//F6PaZf/vWjfQvOesBAABgi4V58Vn6WeMeZzIYqAff+Tj5SBKH/rn29MN7hlOb21Mj6zt/eO7epgtfzRWFgBfQVK8ZXnRntMC9wsBIu3lCwVpUC9ZClVqwbNFmXNTfDEbTX77zJf3neL+1sd5+okujUqypiVJNDYeD1ZJDmzK5uDwRe/LS0m6n87upHT/ZHoz8rzsXx/THtnX8gmp1/7EarCqb0S0xffnB0N");
WriteLiteral(@"ovLrz0oz9Zee1b3+PMB+Bn1zK5P9Mf/h0tAQAWOQh0fU05VvtKvy+ItHra8kZ8SExvrZwf+4dn76+nxldWXfSqrrBjgRb3oD0+n4CXZCtbQ0OFstZRn6+oVrGjeP1z/djO56PbD3++VxoYd3hzzJxHrsnu+h9Ll8b+4tdPX+wk2CWoWuXE70pqWdmJFF5J/IfsL/ZCe1wAAPjZ1/Xp5zQDAFhgYV4Eum4oDQq9twt4PfzcWlWDIvPr9V9eubS0ccotg7YNZvOpIXYw0FjXGV76iSW6MiZpQrk+eJAY7XReUcdruxTesHBzRB2vvqzflYzuPPx5rRy5cCG6ddvBzRFZW+92OK/j3+KIGl3/+TdPXTjadbFTgUBdqdcDjf705d+dXVIurCWVkcIpLgQAWrqWydX79KV9mb0LwMfXQPkOanR9t9Vn6EBAUc0sUr//Cv23xS9e+GcXPr7/T5KfrLvgVYp7iVvsbOCkXro0UqzeAnc2hzsOeEXV6rClB0ew9k/1h/F+bOez4cLDnwtVzemsKc9kSooujH+5+KUL4huubp4vujVWK80vOyuJu/uPBL0AAADQk4Ng1w+UNiVBwmq1q2ytt1fOj90vDET+6Inbn9LYgDv10qWR7oySre5GoxvFiKmU1MFQ2bKgVzRUHVvfifRdO4vujKKG16FaPRD+rBRzMugVW1yecH0AWWR2/fXvph7rNtjVKRH0Wh/Y4IIAAACA7nQY7OrV4oNE/OZHF87Q4IA7dXXjms2nRBScgJdkSxunRsw+R3RrtGp7QlotsV4I9107j0VO1odfLUW9VMfLEX/1wReTIoXbjnWJoBc1vQAAANCllxSbBnsSdb1+s3qaOlqAC3WbqTFJ08m3tB4fNfucsFq1pHB9MFDXwmrt7NZuqO/a+Wj9rkM71RDdGlsQ31x1WpxeljtnVvZHdAQAAAA6tjAvCtPP2LnKN5cfPyd6Q9D4gLt0e1KS3WWBu9tDpgNeaqAeiqjVqOxtiYSqp8VjsaIqhZLWN208Ei");
WriteLiteral(@"oqg2r5xO+LNTWxUw05+c1MYnF5IuHGNlvbi4Z+dW9sRMaymhSsb0iM4Lg6tMaFAQAAAJ056Mr4TTNPqdYC5V5XK0p+/M/lx8fYAYC7EPByiffuj452+1wrujVGtNrDC3Y/1fEaC+82/dv9YuyCw5vXyXlle1HMt1fOn5ZVt6tWNTUIjrI6+IAsLwAAAHTqeX0aNPOEaj1YkbFiUc9LfFHswGveYbcDjZm+ic3mU0n9IUbTyXV7/VTXAa+oVpGemRRSaw+zjdZ3+qeO16WBzaZ/26qGne7WeLmDeWwNeInU7KWNuJTjq14zHzMTwS4K2AMAAKBDz5r+vFnvPcPr0N998oURu1/w9dmbt9ntQGPd9FW7SrPJd68w0PXFMRSsRbVgLVSpBaVcrMNqbTgYqD8MaooujaWKqoQ1b2faiJEZRZfGZrYrIacL108uLk/Enry0tNtinlt2btBvV08POZXddWhtYEM5s32aiwTQpWuZXJ1WAMA1EH1vYX5W/9f0F9jlarAoaxM+3IiL7LL7Nr7qD9nxQHPd3MhSsF6yla2hoUJZ66kOV1SrSCteH9aqJ2pJ9UPx+vPR7bbzfFIcdPtojba+qd1eHxmUtaxqtbtjSIzWWFbLXCgAAADQypVunlSuBYv1eqAmYwPEiOafbA9aVg+mVg8Ei1U1djjd2RxeVRbmr7DrgcZMZXhl8ykRCEnSbHJ98CAx2usyRB0v/QIrpe9XNFQ9sY/XCmHlzPCep9u50eiMx22Ww+cei+x85OBmioDyu83+eH325rZ+Hn6o2BR4/mw3Ku0Nu1rpfvCD3dCeEqqGuFgAAACg1eforhSrwe2oVo3L2Ij/txmPPTa0Iy1rTAS59irqUKGijVRqwUc+m7+5/Pi/0B/+kbIwL/77jj69obz86i0OBeCA2TtQitVb4M7mcM8Br6halVK4Phioa2qwfmJZ/VC4/my40HaerUpYZHi96+BmdnKOvalP37BjY8S3VDKWI+p3ddulUdgLF5X43jAXCwvQ1QMA10");
WriteLiteral(@"Gug0Cf6DrTaa+q7sgKeG0WI9K+pd2raEMbpdC5ej1womdWqarWfrN6+mgXlpn9aWFeBLx+rLz8KrW94HtmuzRO0WRyre5GoxvFiJSi4IOhcs8RgVioerbZ37wc9BLdGUUNr3bK9eDgejmScHBTY4vLE+3Oszft2BCZ6djlUk89dpVqgJEaAQAAYI29irYtq3j9/d2YlM/Q68XIufVi+LFGwS5haSPerF6LCPz9UFmYf5Y9C7/rOOCVzadEEXMyvCRb2jglbSQP0a2x12WEtFrTYM96wbujNY5Fdjt/cylHnB6tseV5Jro1KjYEvfaqWk/F6gP1wH4Gqf4mrVRKvR07oo4XAAAAYNln34q25ZZtEcGuvYraMuPs7ZXzD9os5iWCXvA7Mze0BLsssLQeH5W1rLBaHZCwjKYZXl4uXN9J/a5DG5WI2wvXCz91b2sHgsFK6IxailwU/6uUovtBLwAAAMCtdsramqzi9b3YKIbH2gW7Fh8kNtf2op1kpL1EUXv4mZmAF6MzWuDu9pC0gJcaqIciarXrvmORUDURCDSv61asqEqhpHmujUdCRWXQxCh/hap2rlRTnUxnSywuT7TsVnl99uan+sPPrNyIqFox/YYfrGqntGLkYrCqnhL/F4GucrH3rO7B0iAXCwAAAFimVg/UdsraqpPbIEZe3K1oLXsAidpdHWR3HfWKsjA/xB6GH5Hh5aD37o+Oyl5mL90ao1rz7K5DXqzjNRbeNf2ce6UBr2R5fWrVBpgZXSZQC8a0UuRisKKdOXpdKe4Okt0FAAAAT9guh9YrtWBPIyxeGN7a7fa5W6XQWLt5fnVvbL3D7K5D4pvj59m78KOOAl7ZfEoU0Y7RXHLdXj8lPeAV1SpdR+9Daq1tsfb1He/V8bo0sGn6OZuVkNN1vK62m8Go5fWalRsxFC61fDMVdbrUcjipT48pRs2uQ6JuV7UspxtstBThggEAAIBWbslYyEYx/GkvXRsjarWr0ZZEdlelFmz5ofeT7cHdmx9d6CYL7Q");
WriteLiteral(@"UOD/hRpxleZHdZ4F5hYET2MkPBWlQL1kxHGfTnxNRgvW12mOjSWKqonmljMTKj6NJo1lYlfMHhTU8uLk+0DTJfn715MOywRc4P7TT5hioQVMuhMVGnK1ALnuhGW6uqSmlvQNp2DJYGuGAAAACglQ9lLKRcCxa3yqH73T7/8fhmVxleuxWtZd0u0ZXxrz744t1uP04rC/OzHCLwGwJeDlnZGhoqlLWoFcuOahXT0YGI1j6765CXitefj2539bxaPRBeL0cSDm9+R+fd9dmbbygWjdrYKCU7WNESok5XoKY2DJCKLox7O8PSujJGy1FFralcNAAAANDKLVkL0u/TNrdL5oNeoneEmbIgR1VqgabZXSLY9ZeLX1rZrWi9FNWnJjd8p23AK5tPiZv+BE0l1wcPEqNWLbubOl7hUHWs03nXCt7p1mhmdMbjPivFvFDHa9/12Zuia6P0oNdTZx5sh9Xq/htroKYO7tfpqmqJZtcO2cEuIVE4xQUDAAAArb38al6RWN9W1PParWjrZp7z9JkHW92ur1l3xsNg1yfbg8UeXxKjNcJ3OsnwIrvLAnc2hy0LeEXVqvmAl1o72+m8XipcfzZc6Pq5m5Ww0wEvU9/CGEEvqSM3xrRK7crptb2DOl2hc8frdB0lujHubsf3H2URmV0jBLwAAADQGalfAG8Uw/c3S+GOg2hXxj7blLl+icEuwJc6CXhdpZnkWt2NRjeKEUuHhh0MlTsOesXClbNml++FoJfozihqeHWrWFMTO9WQk0P4xhaXJ0wFnK/P3nxdOShkvyNrI6aC6mV9b7fsfiuK0+9ndtWCUhvgzM5pujMCAACgUz+T+TlYEN0b1/YiK+0K2V8Z+2w9Ed0ry1qvKFD/k1/9gyWCXUD3Wt6dZvMpUTQ7STPJtbRxasTqdZjp1hhWa6a7rK57oFvjWGS352WslaNOj9Y4ZfYJ12dvim+2vqVIqmMQDtaUyyONs7P3uzAWhvYnmd0Y99dbDSlnN0e5YAAAAKAzL79qySjmxa");
WriteLiteral(@"q6e383uqQ/bje+n6rWro2vrMpYl8jqenvl/P2/+PXTvdbsAnyvXToG3RktsLQet/wuXr/odly4PqzVxswu3wuF63up33VorRxxerTGrs7B67M3P9Wnf6//+H1FQi2DJ+Pbytno518uieBWuRhTdrdO7Wd3WeHi6gUuFgAAADDnoJaX9Nq2tXqgtrYX+URke5VrwUe+Wf+jJz68K0qB9LJ8NVAvLz5IbP6n95++83/uPrZuQct8yMEBvyHg5YC720OWB7z0C2YoolbbjgIZVmvDwUA9Znb5xYqqFEqaa9t4JFRUBtXeM4oLVc3pDK/E4vJE11mW12dv5vUpoxx80/VOLxty7ewD5ZRWfRjoKu1FpWd1HbqwltwfnREAAADowo8ViwI8IttrdTe6IgJfIuPrXz5+59OJUxu9dC0R39L/7M/f/4P/8re/m/p0bS9atqhNbnFYwG/aRSwYulSy9+6P2tZHS3Rr1C/Ce63mCWvVrkfgFHW8BsIVV7bzWHhXynJq9UD4k+Lg+GORnY8cfDniPLzbywKMbo5vZvMpEcATI7TMGsttG9DbfDCmbK6eVdY+TSqntoeVB6N3lHpoz7IXK4JdFKoHAABA10TXxoV50dvhB1bd04rAlz795A/P3RN1w2aMz9hXOvl8rRwEn0RATnw5fRCIWvjn4vP5P7aoRXYUAl7woabpGfqNscjuytBEcv313089tbwR/4Id6yrXgnu/3xlcajXPmcHiVa2LGl6CCHb9wYU1V7bzs2N39rO8ZDgd2vvtk0Nr7zr4cu4+eWnpP1q1cP1c/1GTDwI/1d+Af3otk6sf/WU1WFWWRu8oe5KDXqI4/WMb5wh2AQAA+NBbN9Lyuw4szIsBqF5SDgJSsr2mvPzqm00+X4tA25UGf/q+6IHRYntvKJ0FzMx6U9/W1zjK4DetujRO0Tzy3SsMjNi1rlCwFtWCtaYFloKButZtsEsQXRpLFfeNoCdGZpQV7BK2KuFxh19ScnF5Imbh8rfNzCwCU0/cm1DObr");
WriteLiteral(@"Uu/VbV98PRqR6oN513sDigTHx2kWAXAAAA5BGZXi+/+ifKQRfHVgV+h45NrUboEplZ324W7Orxc/ePLWiFHYuWC7heq4AX9bskW9kaGiqUNVsLE0W1StPi9ZFQ9XSvy3dj8frz0W2pyyvXg4M71dCQwy/LdeejGEHxyd8/oSSaBKlEBtjRqaKe7P4qRmIUXRgnPnucml0AAACwxsuvvqEcjGLeLEg1eWxqlBQgBoISWV3f0qfbFm2nyP56R/JSXzdGrwR8p2ENr2w+lWxykqMHHzxIjNq9TlHHa7sU3mj0t0gXozMet1YIK2eG91zVzjJGZzzufjF2YXCg/FsHX5YIeL3rtmM6VA0p59eSytnNMWUztqWsDWy07eooglwio2t4d1iJ7w1zYQAAAID1Xn71IGC1MC+ynZ5VPq+71Yq4sTgIQh0Eo+wguh7Kqj32ZpeZaEBf0FrcXEOyO5vDtge8omq1aUQhrFbP9rp8Ubjebc6GC9KXuVUNi770Tga8XD2AhAh8ndk+vT/tfzKIFJT3zv/mkXlGdk7tZ3OJeQEAAABHHGQ7vWFMom6WCHr992NziSDRa0aQzP7tk1Nw/2f6sl5nh8PPmnVpJOAl2epuNLpRjDjSLW4wVD4R9AqrteFAoO0onR1xU9BLdGcUNbxk266Exks1NezgS4stLk945rwUGVwnjrlqmGAXAAAA3OXlVxuNXvipI8Guz7dpe7/rpKL8tMFfxT3JuSPTyW1XlO8T7AIaBLyy+ZToypikaeRa2jg14tS6RbfG47+LhnrP7jq0Xgi7pp3HIruWLXu1HD3n8MtjIAkAAADAL15+VQS8MorI1vq86H6zgJcopi+6a37bxu6XgKtp3FTbY2k9PurUusNq9US6TVirjslavpsK11tRv+vQWjky/lhk5yMHX57I8PobziYAAADAJw4yzV7fnxbmxb26qD/23SNzfF+fbjuakQa4VLDJTTUku7s95FjASw3UQxG1+nAIvGCgrqnBurRq4cWKqhRKmuNtPB");
WriteLiteral(@"IqKoNq2bLlFyohpzO8EovLE2RfAgAAAH50MDrkrWO/yxPsAhoj4GWD9+6Pjjq9DUe7NcYkdmc85IY6XmPhXUuXX64HB9fLEadHL53kjAIAAAAAoLVHAl7ZfIpglwVur59yPOAV1SoPC+aHQ/K6Mx5a33G+jtelgU3L1/FZKTbu8Mu8yhkFAAAAAEBrxzO8CHhZ4F5hYMTpbQgFa1EtWAsZP5+WvXzRpbFUUZ18fftdGq22WQk7HfBKLi5PxDirAAAAAABo7njAi4L1kq1sDQ0VylrUDdsS1SoDkVA1EQgolhTccrJ4/fnoti3rKdbURKmmOp3ORmAaAAAAAIAWHga8svmUKIadoEnk+uBBYtQt2yLqeEU1+fW7Dq0VnIsDWTk643H3SgNOZ3kR8AIAAAAAoIWjGV7UBrLAnc1h1wS8omp1OKzVxqxavihcX60FHHltZ8MF29a16fxojRSuBwAAAACghf8vwABfcA5F9k0oGQAAAABJRU5ErkJggg==""");
BeginWriteAttribute("alt", "\r\n alt=\"", 46196, "\"", 46262, 1);
#line 182 "WelcomePage.cshtml"
WriteAttributeValue("", 46223, Resources.WelcomePageImageText_Skyline, 46223, 39, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 46263, "\"", 46310, 1);
#line 182 "WelcomePage.cshtml"
WriteAttributeValue("", 46271, Resources.WelcomePageImageText_Skyline, 46271, 39, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(" width=\"1212\" height=\"202\" /></div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"content\">\r\n <div class=\"bodyHeadline\">");
#line 187 "WelcomePage.cshtml"
Write(Resources.WelcomeHeader);
#line default
#line hidden
WriteLiteral("</div>\r\n <div class=\"bodyContent\">");
#line 188 "WelcomePage.cshtml"
Write(Resources.WelcomeStarted);
#line default
#line hidden
WriteLiteral("</div>\r\n <a class=\"bodyCTA longer\" href=\"http://go.microsoft.com/fwlink/?LinkID=398596&amp;clcid=0x409\">");
#line 189 "WelcomePage.cshtml"
Write(Resources.WelcomeLearnMicrosoftAspNet);
#line default
#line hidden
WriteLiteral(@"<div>
<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADoAAAAdCAYAAAD7En+mAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozMjVCMDEwM0FBQkExMUUyQjdGNEEwODg0RjhFODY4OCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozMjVCMDEwNEFBQkExMUUyQjdGNEEwODg0RjhFODY4OCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjMyNUIwM");
WriteLiteral(@"TAxQUFCQTExRTJCN0Y0QTA4ODRGOEU4Njg4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjMyNUIwMTAyQUFCQTExRTJCN0Y0QTA4ODRGOEU4Njg4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+I1MZRAAAA4FJREFUeNq8md1x2kAQx3UaCoAKAg0YkgYQHTgV2KoAeMqjncfkBbsCSAd0AK5AOA1Y6YAOyJ7mf5rV6T4l8M3c2ALd/fZ/u/exh0gCy+VyyeiPrHPtqzPVd6p7IcTJ0rbxTO8FMe++/vIy/xY/TiF9CY+4If1ZUV1SHQb0V1L9Q/WFxJy7CCVxnZkk+hwtlIyTsCcGk53sMZJ8FGcY8Ux7NydB+xihJLI3k8Tug4TCi1uq92zEfpJxu4DwfoShY3y0o3a5Tyi82GKS0buA8G4xqV3uFAqRB4xYAoHPSURBH08IvwosR9omFCIbTDI0iok+GkxdrC5UjuqjHnpdCry7xaOcs2uLkQ2mLfQCBTeY1Ne6JRRzcoPH731EWsQuqM+jYU7WzD4iLWIX1GfFTLVwU+HaG4gQ3WExSRhcDzcVrldhYl63mAJCnwEtybiJx0tjNvETtCk9c/YDq2OuFjUSWjPJuInHSy0mtSk9c7ZmSvEpvntQIxswaGeE2wG1IDEzh1fl+694XLKvejFJzMzh1RZTwMhCdkZGjSJWVr5SnjEHT44o+MDjaPrt91gxyahRxMraYtpORoiCmpmyvesYMfcqCNvEKyNsnkVoq3ezLkx4qcW0eRahXTOl0C94eI9caGxiM0uTEzvVdGI6xHqZAzbJT4aQO8ADoUWJzQ0nqX/sfyuTjO7EpHa54SRVM1Ntwl+rbALf+zTmwDDKJtf7SqYZvwhs92nMATrOTFDbsY2F9gwrITdywVM0Vqbae0YmP7ZZVlMj05KiTXnoqjieRx7vFHAYIDJh28KxK5OJH");
WriteLiteral(@"AaIbDCFvsc5DO0sku3VMkqEvse5EuauIvF+gSgRqbbHrW7gSX4i2hn2uNUNPNliCi3LkA0nIV6NDPFCz2BYllExQ7waGeIFz2BSlmWUGLHtFUXy/o48TcOed3Umu62omI00DUVl5PdIwK+1t81UUm34vmYiAb8ZUzgS5eq+p4cnN7g5cCbyWqJsvO+J8GSDyXNc0+XYlr18RA5ZRt7/btjSnqsFwXE51mK68k3L/W+DqR8HRcAViFq5Xm1pGBP4wAyu751Crjs1z9ZM1wU1BLaYptsK4VktN9pRq0R9Y5/NMZL8slmC1ioSIu51ezNtkSACQ3HJckjXAX1v8nzsTxLwVBTT99OEiFxkMsNIVpu/J6yjhBpEG5mhv7vI8l+AAQB7WiwH/DuungAAAABJRU5ErkJggg==""");
BeginWriteAttribute("alt", "\r\n alt=\"", 49142, "\"", 49206, 1);
#line 191 "WelcomePage.cshtml"
WriteAttributeValue("", 49165, Resources.WelcomePageImageText_LearnMore, 49165, 41, false);
#line default
#line hidden
EndWriteAttribute();
BeginWriteAttribute("title", " title=\"", 49207, "\"", 49256, 1);
#line 191 "WelcomePage.cshtml"
WriteAttributeValue("", 49215, Resources.WelcomePageImageText_LearnMore, 49215, 41, false);
#line default
#line hidden
EndWriteAttribute();
WriteLiteral(" width=\"58\" height=\"29\" /></div>\r\n </a>\r\n </div>\r\n\r\n</body>\r\n</html>\r\n");
}
#pragma warning restore 1998
}
}

View File

@ -1,7 +1,7 @@
@using System
@using System
@using Microsoft.AspNetCore.Diagnostics
@{
Response.ContentType = "text/html";
Response.ContentType = "text/html; charset=utf-8";
}
<!DOCTYPE html>
<html lang="@System.Globalization.CultureInfo.CurrentUICulture.TwoLetterISOLanguageName">

View File

@ -1,11 +1,10 @@
// 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.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.Views;
using Microsoft.AspNetCore.Diagnostics.RazorViews;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;

View File

@ -31,6 +31,10 @@
"Microsoft.Extensions.FileProviders.Physical": "1.1.0-*",
"Microsoft.Extensions.Logging.Abstractions": "1.1.0-*",
"Microsoft.Extensions.Options": "1.1.0-*",
"Microsoft.Extensions.RazorViews.Sources": {
"type": "build",
"version": "1.1.0-*"
},
"Microsoft.Extensions.StackTrace.Sources": {
"type": "build",
"version": "1.1.0-*"
@ -42,6 +46,9 @@
"System.Diagnostics.DiagnosticSource": "4.0.0-*",
"System.Reflection.Metadata": "1.3.0-*"
},
"tools": {
"RazorPageGenerator": "1.1.0-*"
},
"frameworks": {
"net451": {},
"netstandard1.3": {

View File

@ -5,6 +5,7 @@ using System;
namespace Microsoft.AspNetCore.DiagnosticsViewPage.Views
{
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class AttributeValue
{
public AttributeValue(string prefix, object value, bool literal)

View File

@ -17,6 +17,7 @@ namespace Microsoft.AspNetCore.DiagnosticsViewPage.Views
/// <summary>
/// Infrastructure
/// </summary>
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public abstract class BaseView
{
/// <summary>

View File

@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.DiagnosticsViewPage.Views
/// <summary>
/// Represents a deferred write operation in a <see cref="BaseView"/>.
/// </summary>
[Obsolete("This type is for internal use only and will be removed in a future version.")]
public class HelperResult
{
/// <summary>

View File

@ -1,18 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>4d4a785a-ecb9-4916-a88f-0fd306ee3b74</ProjectGuid>
<ProjectGuid>aa3661a1-ce8d-4597-adfd-a5a30834e5d0</ProjectGuid>
<RootNamespace>ClassLibraryWithPortablePdbs</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<DevelopmentServerPort>0</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,20 @@
// 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;
namespace ClassLibraryWithPortablePdbs
{
public class ExceptionType
{
public static void StaticMethodThatThrows()
{
throw new Exception();
}
public void MethodThatThrows()
{
throw new Exception();
}
}
}

View File

@ -0,0 +1,13 @@
{
"version": "1.1.0-*",
"buildOptions": {
"debugType": "portable",
"keyFile": "../../tools/Key.snk"
},
"dependencies": {
"System.Runtime": "4.1.0-*"
},
"frameworks": {
"netstandard1.0": {}
}
}

View File

@ -7,7 +7,7 @@ using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views;
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.RazorViews;
using Microsoft.AspNetCore.Testing.xunit;
using Xunit;

View File

@ -3,7 +3,7 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests.Helpers;
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views;
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.RazorViews;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Moq;
@ -153,7 +153,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
Assert.Contains("Something bad happened", content);
Assert.Contains("Because something more badder happened", content);
}
[Fact]
public async Task MigrationsEndPointPath_is_respected()
{

View File

@ -1,12 +1,13 @@
{
"buildOptions": {
"warningsAsErrors": true,
"compile": {
"include": [
"../Shared/ApiConsistencyTestBase.cs",
"../Shared/TestHelpers.cs"
]
}
},
"keyFile": "../../tools/Key.snk",
"warningsAsErrors": true
},
"dependencies": {
"dotnet-test-xunit": "2.2.0-*",

View File

@ -2,424 +2,19 @@
// 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.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.Diagnostics
{
public class DeveloperExceptionPageMiddlewareTest
{
public static TheoryData RelativePathsData
{
get
{
var data = new TheoryData<string>
{
"TestFiles/SourceFile.txt"
};
if (!(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)))
{
data.Add(@"TestFiles\SourceFile.txt");
}
return data;
}
}
[Theory]
[MemberData(nameof(RelativePathsData))]
public void UsesDefaultFileProvider_IfNotProvidedOnOptions(string relativePath)
{
// Arrange & Act
var middleware = GetErrorPageMiddleware(fileProvider: null);
var stackFrame = middleware.GetStackFrame("func1", relativePath, lineNumber: 10);
// Assert
// Lines 4-16 (inclusive) is the code block
Assert.Equal(4, stackFrame.PreContextLine);
Assert.Equal(GetCodeLines(4, 9), stackFrame.PreContextCode);
Assert.Equal(GetCodeLines(10, 10), stackFrame.ContextCode);
Assert.Equal(GetCodeLines(11, 16), stackFrame.PostContextCode);
}
public static TheoryData<string> AbsolutePathsData
{
get
{
var rootPath = Directory.GetCurrentDirectory();
var data = new TheoryData<string>()
{
Path.Combine(rootPath, "TestFiles/SourceFile.txt")
};
if (!TestPlatformHelper.IsMono)
{
Path.Combine(rootPath, @"TestFiles\SourceFile.txt");
}
return data;
}
}
[Theory]
[MemberData(nameof(AbsolutePathsData))]
public void DisplaysSourceCodeLines_ForAbsolutePaths(string absoluteFilePath)
{
// Arrange
var rootPath = Directory.GetCurrentDirectory();
// PhysicalFileProvider handles only relative paths but we fall back to work with absolute paths too
using (var provider = new PhysicalFileProvider(rootPath))
{
// Act
var middleware = GetErrorPageMiddleware(provider);
var stackFrame = middleware.GetStackFrame("func1", absoluteFilePath, lineNumber: 10);
// Assert
// Lines 4-16 (inclusive) is the code block
Assert.Equal(4, stackFrame.PreContextLine);
Assert.Equal(GetCodeLines(4, 9), stackFrame.PreContextCode);
Assert.Equal(GetCodeLines(10, 10), stackFrame.ContextCode);
Assert.Equal(GetCodeLines(11, 16), stackFrame.PostContextCode);
}
}
[Theory]
[MemberData(nameof(RelativePathsData))]
public void DisplaysSourceCodeLines_ForRelativePaths(string relativePath)
{
// Arrange
var rootPath = Directory.GetCurrentDirectory();
using (var provider = new PhysicalFileProvider(rootPath))
{
// Act
var middleware = GetErrorPageMiddleware(provider);
var stackFrame = middleware.GetStackFrame("func1", relativePath, lineNumber: 10);
// Assert
// Lines 4-16 (inclusive) is the code block
Assert.Equal(4, stackFrame.PreContextLine);
Assert.Equal(GetCodeLines(4, 9), stackFrame.PreContextCode);
Assert.Equal(GetCodeLines(10, 10), stackFrame.ContextCode);
Assert.Equal(GetCodeLines(11, 16), stackFrame.PostContextCode);
}
}
[Theory]
[InlineData("TestFiles/EmbeddedSourceFile.txt")]
//[InlineData(@"TestFiles\EmbeddedSourceFile.txt")]
public void DisplaysSourceCodeLines_ForRelativeEmbeddedPaths(string relativePath)
{
// Arrange
var provider = new EmbeddedFileProvider(
GetType().GetTypeInfo().Assembly,
baseNamespace: $"{typeof(DeveloperExceptionPageMiddlewareTest).GetTypeInfo().Assembly.GetName().Name}.Resources");
// Act
var middleware = GetErrorPageMiddleware(provider);
var stackFrame = middleware.GetStackFrame("func1", relativePath, lineNumber: 10);
// Assert
// Lines 4-16 (inclusive) is the code block
Assert.Equal(4, stackFrame.PreContextLine);
Assert.Equal(GetCodeLines(4, 9), stackFrame.PreContextCode);
Assert.Equal(GetCodeLines(10, 10), stackFrame.ContextCode);
Assert.Equal(GetCodeLines(11, 16), stackFrame.PostContextCode);
}
public static TheoryData<ErrorData> DisplaysSourceCodeLines_PreAndPostErrorLineData
{
get
{
return new TheoryData<ErrorData>()
{
new ErrorData()
{
AllLines = GetCodeLines(1, 30),
ErrorStartLine = 10,
ErrorEndLine = 10,
ExpectedPreContextLine = 4,
ExpectedPreErrorCode = GetCodeLines(4, 9),
ExpectedErrorCode = GetCodeLines(10, 10),
ExpectedPostErrorCode = GetCodeLines(11, 16)
},
new ErrorData()
{
AllLines = GetCodeLines(1, 30),
ErrorStartLine = 10,
ErrorEndLine = 13, // multi-line error
ExpectedPreContextLine = 4,
ExpectedPreErrorCode = GetCodeLines(4, 9),
ExpectedErrorCode = GetCodeLines(10, 13),
ExpectedPostErrorCode = GetCodeLines(14, 19)
},
// PreErrorCode less than source code line count
new ErrorData()
{
AllLines = GetCodeLines(1, 10),
ErrorStartLine = 1,
ErrorEndLine = 1,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = Enumerable.Empty<string>(),
ExpectedErrorCode = GetCodeLines(1, 1),
ExpectedPostErrorCode = GetCodeLines(2, 7)
},
new ErrorData()
{
AllLines = GetCodeLines(1, 10),
ErrorStartLine = 3,
ErrorEndLine = 5,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = GetCodeLines(1, 2),
ExpectedErrorCode = GetCodeLines(3, 5),
ExpectedPostErrorCode = GetCodeLines(6, 10)
},
// PostErrorCode less than source code line count
new ErrorData()
{
AllLines = GetCodeLines(1, 10),
ErrorStartLine = 10,
ErrorEndLine = 10,
ExpectedPreContextLine = 4,
ExpectedPreErrorCode = GetCodeLines(4, 9),
ExpectedErrorCode = GetCodeLines(10, 10),
ExpectedPostErrorCode = Enumerable.Empty<string>()
},
new ErrorData()
{
AllLines = GetCodeLines(1, 10),
ErrorStartLine = 7,
ErrorEndLine = 10,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = GetCodeLines(1, 6),
ExpectedErrorCode = GetCodeLines(7, 10),
ExpectedPostErrorCode = Enumerable.Empty<string>()
},
new ErrorData()
{
AllLines = GetCodeLines(1, 10),
ErrorStartLine = 5,
ErrorEndLine = 8,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = GetCodeLines(1, 4),
ExpectedErrorCode = GetCodeLines(5, 8),
ExpectedPostErrorCode = GetCodeLines(9, 10)
},
// Pre and Post error code less than source code line count
new ErrorData()
{
AllLines = GetCodeLines(1, 4),
ErrorStartLine = 2,
ErrorEndLine = 3,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = GetCodeLines(1, 1),
ExpectedErrorCode = GetCodeLines(2, 3),
ExpectedPostErrorCode = GetCodeLines(4, 4)
},
new ErrorData()
{
AllLines = GetCodeLines(1, 4),
ErrorStartLine = 1,
ErrorEndLine = 4,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = Enumerable.Empty<string>(),
ExpectedErrorCode = GetCodeLines(1, 4),
ExpectedPostErrorCode = Enumerable.Empty<string>()
},
// change source code line count
new ErrorData()
{
SourceCodeLineCount = 1,
AllLines = GetCodeLines(1, 1),
ErrorStartLine = 1,
ErrorEndLine = 1,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = Enumerable.Empty<string>(),
ExpectedErrorCode = GetCodeLines(1, 1),
ExpectedPostErrorCode = Enumerable.Empty<string>()
},
};
}
}
[Theory]
[MemberData(nameof(DisplaysSourceCodeLines_PreAndPostErrorLineData))]
public void DisplaysSourceCodeLines_PreAndPostErrorLine(ErrorData errorData)
{
// Arrange
var middleware = GetErrorPageMiddleware();
var stackFrame = new Views.StackFrame();
// Act
middleware.ReadFrameContent(
stackFrame, errorData.AllLines, errorData.ErrorStartLine, errorData.ErrorEndLine);
// Assert
Assert.Equal(errorData.ExpectedPreContextLine, stackFrame.PreContextLine);
Assert.Equal(errorData.ExpectedPreErrorCode, stackFrame.PreContextCode);
Assert.Equal(errorData.ExpectedErrorCode, stackFrame.ContextCode);
Assert.Equal(errorData.ExpectedPostErrorCode, stackFrame.PostContextCode);
}
private static IEnumerable<string> GetCodeLines(int fromLine, int toLine)
{
var start = fromLine;
var count = toLine - fromLine + 1;
return Enumerable.Range(start, count).Select(i => string.Format("Line{0}", i));
}
private DeveloperExceptionPageMiddleware GetErrorPageMiddleware(
IFileProvider fileProvider = null, int sourceCodeLineCount = 6)
{
var options = new DeveloperExceptionPageOptions();
options.SourceCodeLineCount = sourceCodeLineCount;
if (fileProvider != null)
{
options.FileProvider = fileProvider;
}
var middleware = new DeveloperExceptionPageMiddleware(
(httpContext) => { return Task.FromResult(0); },
Options.Create(options),
new LoggerFactory(),
Mock.Of<IHostingEnvironment>(),
new DiagnosticListener("Microsoft.Aspnet"));
return middleware;
}
private class TestFileProvider : IFileProvider
{
private readonly IEnumerable<string> _sourceCodeLines;
public TestFileProvider(IEnumerable<string> sourceCodeLines)
{
_sourceCodeLines = sourceCodeLines;
}
public IDirectoryContents GetDirectoryContents(string subpath)
{
throw new NotImplementedException();
}
public IFileInfo GetFileInfo(string subpath)
{
return new TestFileInfo(_sourceCodeLines);
}
public IChangeToken Watch(string filter)
{
throw new NotImplementedException();
}
}
private class TestFileInfo : IFileInfo
{
private readonly MemoryStream _stream;
public TestFileInfo(IEnumerable<string> sourceCodeLines)
{
_stream = new MemoryStream();
using (var writer = new StreamWriter(_stream, Encoding.UTF8, 1024, leaveOpen: true))
{
foreach (var line in sourceCodeLines)
{
writer.WriteLine(line);
}
}
_stream.Seek(0, SeekOrigin.Begin);
}
public bool Exists
{
get
{
return true;
}
}
public bool IsDirectory
{
get
{
throw new NotImplementedException();
}
}
public DateTimeOffset LastModified
{
get
{
throw new NotImplementedException();
}
}
public long Length
{
get
{
throw new NotImplementedException();
}
}
public string Name
{
get
{
throw new NotImplementedException();
}
}
public string PhysicalPath
{
get
{
return null;
}
}
public Stream CreateReadStream()
{
return _stream;
}
}
public class ErrorData
{
public int SourceCodeLineCount { get; set; } = 6;
public IEnumerable<string> AllLines { get; set; }
public int ErrorStartLine { get; set; }
public int ErrorEndLine { get; set; }
public int ExpectedPreContextLine { get; set; }
public IEnumerable<string> ExpectedPreErrorCode { get; set; }
public IEnumerable<string> ExpectedErrorCode { get; set; }
public IEnumerable<string> ExpectedPostErrorCode { get; set; }
}
[Fact]
public async Task UnhandledErrorsWriteToDiagnosticWhenUsingExceptionPage()
{

View File

@ -0,0 +1,392 @@
// 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.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using Microsoft.Extensions.StackTrace.Sources;
using Xunit;
namespace Microsoft.Extensions.Internal
{
public class ExceptionDetailsProviderTest
{
public static TheoryData RelativePathsData
{
get
{
var data = new TheoryData<string>
{
"TestFiles/SourceFile.txt"
};
if (!(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)))
{
data.Add(@"TestFiles\SourceFile.txt");
}
return data;
}
}
public static TheoryData<string> AbsolutePathsData
{
get
{
var rootPath = Directory.GetCurrentDirectory();
var data = new TheoryData<string>()
{
Path.Combine(rootPath, "TestFiles/SourceFile.txt")
};
if (!TestPlatformHelper.IsMono)
{
Path.Combine(rootPath, @"TestFiles\SourceFile.txt");
}
return data;
}
}
[Theory]
[MemberData(nameof(AbsolutePathsData))]
public void DisplaysSourceCodeLines_ForAbsolutePaths(string absoluteFilePath)
{
// Arrange
var rootPath = Directory.GetCurrentDirectory();
// PhysicalFileProvider handles only relative paths but we fall back to work with absolute paths too
using (var provider = new PhysicalFileProvider(rootPath))
{
// Act
var exceptionDetailProvider = new ExceptionDetailsProvider(provider, sourceCodeLineCount: 6);
var stackFrame = exceptionDetailProvider.GetStackFrameSourceCodeInfo(
"func1",
absoluteFilePath,
lineNumber: 10);
// Assert
// Lines 4-16 (inclusive) is the code block
Assert.Equal(4, stackFrame.PreContextLine);
Assert.Equal(GetCodeLines(4, 9), stackFrame.PreContextCode);
Assert.Equal(GetCodeLines(10, 10), stackFrame.ContextCode);
Assert.Equal(GetCodeLines(11, 16), stackFrame.PostContextCode);
}
}
[Theory]
[MemberData(nameof(RelativePathsData))]
public void DisplaysSourceCodeLines_ForRelativePaths(string relativePath)
{
// Arrange
var rootPath = Directory.GetCurrentDirectory();
using (var provider = new PhysicalFileProvider(rootPath))
{
// Act
var exceptionDetailProvider = new ExceptionDetailsProvider(provider, sourceCodeLineCount: 6);
var stackFrame = exceptionDetailProvider.GetStackFrameSourceCodeInfo(
"func1",
relativePath,
lineNumber: 10);
// Assert
// Lines 4-16 (inclusive) is the code block
Assert.Equal(4, stackFrame.PreContextLine);
Assert.Equal(GetCodeLines(4, 9), stackFrame.PreContextCode);
Assert.Equal(GetCodeLines(10, 10), stackFrame.ContextCode);
Assert.Equal(GetCodeLines(11, 16), stackFrame.PostContextCode);
}
}
[Theory]
[InlineData("TestFiles/EmbeddedSourceFile.txt")]
//[InlineData(@"TestFiles\EmbeddedSourceFile.txt")]
public void DisplaysSourceCodeLines_ForRelativeEmbeddedPaths(string relativePath)
{
// Arrange
var provider = new EmbeddedFileProvider(
GetType().GetTypeInfo().Assembly,
baseNamespace: $"{typeof(ExceptionDetailsProviderTest).GetTypeInfo().Assembly.GetName().Name}.Resources");
// Act
var exceptionDetailProvider = new ExceptionDetailsProvider(provider, sourceCodeLineCount: 6);
var stackFrame = exceptionDetailProvider.GetStackFrameSourceCodeInfo(
"func1",
relativePath,
lineNumber: 10);
// Assert
// Lines 4-16 (inclusive) is the code block
Assert.Equal(4, stackFrame.PreContextLine);
Assert.Equal(GetCodeLines(4, 9), stackFrame.PreContextCode);
Assert.Equal(GetCodeLines(10, 10), stackFrame.ContextCode);
Assert.Equal(GetCodeLines(11, 16), stackFrame.PostContextCode);
}
public static TheoryData<ErrorData> DisplaysSourceCodeLines_PreAndPostErrorLineData
{
get
{
return new TheoryData<ErrorData>()
{
new ErrorData()
{
AllLines = GetCodeLines(1, 30),
ErrorStartLine = 10,
ErrorEndLine = 10,
ExpectedPreContextLine = 4,
ExpectedPreErrorCode = GetCodeLines(4, 9),
ExpectedErrorCode = GetCodeLines(10, 10),
ExpectedPostErrorCode = GetCodeLines(11, 16)
},
new ErrorData()
{
AllLines = GetCodeLines(1, 30),
ErrorStartLine = 10,
ErrorEndLine = 13, // multi-line error
ExpectedPreContextLine = 4,
ExpectedPreErrorCode = GetCodeLines(4, 9),
ExpectedErrorCode = GetCodeLines(10, 13),
ExpectedPostErrorCode = GetCodeLines(14, 19)
},
// PreErrorCode less than source code line count
new ErrorData()
{
AllLines = GetCodeLines(1, 10),
ErrorStartLine = 1,
ErrorEndLine = 1,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = Enumerable.Empty<string>(),
ExpectedErrorCode = GetCodeLines(1, 1),
ExpectedPostErrorCode = GetCodeLines(2, 7)
},
new ErrorData()
{
AllLines = GetCodeLines(1, 10),
ErrorStartLine = 3,
ErrorEndLine = 5,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = GetCodeLines(1, 2),
ExpectedErrorCode = GetCodeLines(3, 5),
ExpectedPostErrorCode = GetCodeLines(6, 10)
},
// PostErrorCode less than source code line count
new ErrorData()
{
AllLines = GetCodeLines(1, 10),
ErrorStartLine = 10,
ErrorEndLine = 10,
ExpectedPreContextLine = 4,
ExpectedPreErrorCode = GetCodeLines(4, 9),
ExpectedErrorCode = GetCodeLines(10, 10),
ExpectedPostErrorCode = Enumerable.Empty<string>()
},
new ErrorData()
{
AllLines = GetCodeLines(1, 10),
ErrorStartLine = 7,
ErrorEndLine = 10,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = GetCodeLines(1, 6),
ExpectedErrorCode = GetCodeLines(7, 10),
ExpectedPostErrorCode = Enumerable.Empty<string>()
},
new ErrorData()
{
AllLines = GetCodeLines(1, 10),
ErrorStartLine = 5,
ErrorEndLine = 8,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = GetCodeLines(1, 4),
ExpectedErrorCode = GetCodeLines(5, 8),
ExpectedPostErrorCode = GetCodeLines(9, 10)
},
// Pre and Post error code less than source code line count
new ErrorData()
{
AllLines = GetCodeLines(1, 4),
ErrorStartLine = 2,
ErrorEndLine = 3,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = GetCodeLines(1, 1),
ExpectedErrorCode = GetCodeLines(2, 3),
ExpectedPostErrorCode = GetCodeLines(4, 4)
},
new ErrorData()
{
AllLines = GetCodeLines(1, 4),
ErrorStartLine = 1,
ErrorEndLine = 4,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = Enumerable.Empty<string>(),
ExpectedErrorCode = GetCodeLines(1, 4),
ExpectedPostErrorCode = Enumerable.Empty<string>()
},
// change source code line count
new ErrorData()
{
SourceCodeLineCount = 1,
AllLines = GetCodeLines(1, 1),
ErrorStartLine = 1,
ErrorEndLine = 1,
ExpectedPreContextLine = 1,
ExpectedPreErrorCode = Enumerable.Empty<string>(),
ExpectedErrorCode = GetCodeLines(1, 1),
ExpectedPostErrorCode = Enumerable.Empty<string>()
},
};
}
}
[Theory]
[MemberData(nameof(DisplaysSourceCodeLines_PreAndPostErrorLineData))]
public void DisplaysSourceCodeLines_PreAndPostErrorLine(ErrorData errorData)
{
// Arrange
var stackFrame = new StackFrameSourceCodeInfo();
// Act
var exceptionDetailProvider = new ExceptionDetailsProvider(
new PhysicalFileProvider(Directory.GetCurrentDirectory()),
sourceCodeLineCount: 6);
exceptionDetailProvider.ReadFrameContent(
stackFrame,
errorData.AllLines,
errorData.ErrorStartLine,
errorData.ErrorEndLine);
// Assert
Assert.Equal(errorData.ExpectedPreContextLine, stackFrame.PreContextLine);
Assert.Equal(errorData.ExpectedPreErrorCode, stackFrame.PreContextCode);
Assert.Equal(errorData.ExpectedErrorCode, stackFrame.ContextCode);
Assert.Equal(errorData.ExpectedPostErrorCode, stackFrame.PostContextCode);
}
private static IEnumerable<string> GetCodeLines(int fromLine, int toLine)
{
var start = fromLine;
var count = toLine - fromLine + 1;
return Enumerable.Range(start, count).Select(i => string.Format("Line{0}", i));
}
private class TestFileProvider : IFileProvider
{
private readonly IEnumerable<string> _sourceCodeLines;
public TestFileProvider(IEnumerable<string> sourceCodeLines)
{
_sourceCodeLines = sourceCodeLines;
}
public IDirectoryContents GetDirectoryContents(string subpath)
{
throw new NotImplementedException();
}
public IFileInfo GetFileInfo(string subpath)
{
return new TestFileInfo(_sourceCodeLines);
}
public IChangeToken Watch(string filter)
{
throw new NotImplementedException();
}
}
private class TestFileInfo : IFileInfo
{
private readonly MemoryStream _stream;
public TestFileInfo(IEnumerable<string> sourceCodeLines)
{
_stream = new MemoryStream();
using (var writer = new StreamWriter(_stream, Encoding.UTF8, 1024, leaveOpen: true))
{
foreach (var line in sourceCodeLines)
{
writer.WriteLine(line);
}
}
_stream.Seek(0, SeekOrigin.Begin);
}
public bool Exists
{
get
{
return true;
}
}
public bool IsDirectory
{
get
{
throw new NotImplementedException();
}
}
public DateTimeOffset LastModified
{
get
{
throw new NotImplementedException();
}
}
public long Length
{
get
{
throw new NotImplementedException();
}
}
public string Name
{
get
{
throw new NotImplementedException();
}
}
public string PhysicalPath
{
get
{
return null;
}
}
public Stream CreateReadStream()
{
return _stream;
}
}
public class ErrorData
{
public int SourceCodeLineCount { get; set; } = 6;
public IEnumerable<string> AllLines { get; set; }
public int ErrorStartLine { get; set; }
public int ErrorEndLine { get; set; }
public int ExpectedPreContextLine { get; set; }
public IEnumerable<string> ExpectedPreErrorCode { get; set; }
public IEnumerable<string> ExpectedErrorCode { get; set; }
public IEnumerable<string> ExpectedPostErrorCode { get; set; }
}
}
}

View File

@ -0,0 +1,159 @@
// 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.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using ClassLibraryWithPortablePdbs;
using Microsoft.Extensions.StackTrace.Sources;
using Xunit;
namespace Microsoft.Extensions.Internal.Test
{
public class StackTraceTest
{
public static TheoryData CanGetStackTraceData => new TheoryData<Action, string>
{
{
ThrowsException,
$"{typeof(StackTraceTest).GetTypeInfo().FullName}.{nameof(ThrowsException)}()"
},
{
new ExceptionType().MethodThatThrows,
$"{typeof(ExceptionType).GetTypeInfo().FullName}.{nameof(ExceptionType.MethodThatThrows)}()"
},
{
ExceptionType.StaticMethodThatThrows,
$"{typeof(ExceptionType).GetTypeInfo().FullName}.{nameof(ExceptionType.StaticMethodThatThrows)}()"
}
};
[Theory]
[MemberData(nameof(CanGetStackTraceData))]
public void GetFrames_CanGetStackTrace(Action action, string expectedDisplay)
{
try
{
action();
}
catch (Exception exception)
{
// Arrange and Act
var frames = StackTraceHelper.GetFrames(exception);
// Assert
Assert.Equal(expectedDisplay, frames.First().MethodDisplayInfo.ToString());
Assert.Equal(
$"{typeof(StackTraceTest).GetTypeInfo().FullName}.{nameof(GetFrames_CanGetStackTrace)}" +
"(Action action, string expectedDisplay)",
frames.Last().MethodDisplayInfo.ToString());
}
}
[Fact]
public void GetFrames_DoesNotFailForDynamicallyGeneratedAssemblies()
{
// Arrange
var action = (Action)Expression.Lambda(
Expression.Throw(
Expression.New(typeof(Exception)))).Compile();
// Act
try
{
action();
}
catch (Exception exception)
{
var frames = StackTraceHelper.GetFrames(exception);
// Assert
Assert.Null(frames.First().FilePath);
Assert.Equal(
$"{typeof(StackTraceTest).GetTypeInfo().FullName}.{nameof(GetFrames_DoesNotFailForDynamicallyGeneratedAssemblies)}()",
frames.Last().MethodDisplayInfo.ToString());
}
}
public static TheoryData GetMethodDisplayString_ReturnsTypeNameQualifiedMethodsData
{
get
{
var thisType = typeof(StackTraceTest);
var intParse = ((Func<string, int>)int.Parse).GetMethodInfo();
var dateTimeOffsetTryParse = typeof(DateTimeOffset).GetMethods()
.First(m => m.Name == nameof(DateTimeOffset.TryParse) && m.GetParameters().Length == 2);
var genericTypeMethod = typeof(List<Process>).GetMethod(nameof(List<Process>.Remove));
var genericMethod = thisType.GetMethod(nameof(GenericMethod));
var multiGenericMethod = thisType.GetMethod(nameof(MultiParameterGenericMethod));
var byRefMethod = thisType.GetMethod(nameof(ByRefMethod));
var asyncMethod = thisType.GetMethod(nameof(AsyncMethod));
var nullableParam = thisType.GetMethod(nameof(MethodWithNullableParams));
var nestedMethod = thisType.GetNestedType(nameof(NestedType), BindingFlags.Public)
.GetMethod(nameof(NestedType.NestedMethod));
var nestedGenericMethod = thisType.GetNestedType(nameof(NestedType), BindingFlags.Public)
.GetMethod(nameof(NestedType.NestedGenericMethod));
return new TheoryData<MethodBase, string>
{
{ intParse, "int.Parse(string s)" },
{ dateTimeOffsetTryParse, "System.DateTimeOffset.TryParse(string input, out DateTimeOffset result)" },
{ genericTypeMethod, "System.Collections.Generic.List<System.Diagnostics.Process>.Remove(Process item)" },
{ genericMethod, $"{thisType}.{nameof(GenericMethod)}<TVal>(TVal value)" },
{ multiGenericMethod, $"{thisType}.{nameof(MultiParameterGenericMethod)}<TKey, TVal>(KeyValuePair<TKey, TVal> keyValuePair)" },
{ byRefMethod, $"{thisType}.{nameof(ByRefMethod)}(int a, CultureInfo b, ref long c)" },
{ asyncMethod, $"{thisType}.{nameof(AsyncMethod)}(string name)" },
{ nullableParam, $"{thisType}.{nameof(MethodWithNullableParams)}(Nullable<int> name, string value)" },
{ nestedMethod, $"{typeof(NestedType)}.{nameof(NestedType.NestedMethod)}(string value)" },
{ nestedGenericMethod, $"{typeof(NestedType)}.{nameof(NestedType.NestedGenericMethod)}<TKey>(NestedParameterType a, TKey key)" }
};
}
}
[Theory]
[MemberData(nameof(GetMethodDisplayString_ReturnsTypeNameQualifiedMethodsData))]
public void GetMethodDisplayString_ReturnsTypeNameQualifiedMethods(MethodBase method, string expected)
{
// Act
var actual = StackTraceHelper.GetMethodDisplayString(method);
// Assert
Assert.Equal(expected, actual.ToString());
}
public static void ThrowsException()
{
throw new Exception();
}
public string GenericMethod<TVal>(TVal value) => value.ToString();
public void MultiParameterGenericMethod<TKey, TVal>(KeyValuePair<TKey, TVal> keyValuePair)
{
}
public decimal ByRefMethod(int a, CultureInfo b, ref long c) => a + c;
public async Task<object> AsyncMethod(string name) => await Task.FromResult(0);
public void MethodWithNullableParams(int? name, string value)
{
}
public class NestedType
{
public void NestedMethod(string value) => Console.WriteLine("Hello world");
public TKey NestedGenericMethod<TKey>(NestedParameterType a, TKey key) => key;
}
public class NestedParameterType
{
}
}
}

View File

@ -14,7 +14,7 @@
}
},
"dependencies": {
"System.Runtime.InteropServices.RuntimeInformation": "4.0.0-*",
"ClassLibraryWithPortablePdbs": "1.1.0-*",
"dotnet-test-xunit": "2.2.0-*",
"Microsoft.AspNetCore.Diagnostics": "1.1.0-*",
"Microsoft.AspNetCore.Diagnostics.Elm": "0.2.0-*",
@ -24,6 +24,7 @@
"Microsoft.Extensions.DiagnosticAdapter": "1.1.0-*",
"Microsoft.Extensions.FileProviders.Embedded": "1.1.0-*",
"Moq": "4.6.36-*",
"System.Runtime.InteropServices.RuntimeInformation": "4.0.0-*",
"xunit": "2.2.0-*"
},
"frameworks": {

View File

@ -1,130 +0,0 @@
// 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 Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.CodeGenerators;
namespace PageGenerator
{
public class Program
{
private const int NumArgs = 1;
public static void Main(string[] args)
{
if (args.Length != NumArgs)
{
throw new ArgumentException(string.Format("Requires {0} argument (Project Directory), {1} given", NumArgs, args.Length));
}
var diagnosticsDir = args[0];
var viewDirectories = Directory.EnumerateDirectories(diagnosticsDir, "Views", SearchOption.AllDirectories);
var fileCount = 0;
foreach (var viewDir in viewDirectories)
{
Console.WriteLine();
Console.WriteLine(" Generating code files for views in {0}", viewDir);
var cshtmlFiles = Directory.EnumerateFiles(viewDir, "*.cshtml");
if (!cshtmlFiles.Any())
{
Console.WriteLine(" No .cshtml files were found.");
continue;
}
foreach (var fileName in cshtmlFiles)
{
Console.WriteLine(" Generating code file for view {0}...", Path.GetFileName(fileName));
var rootNamespace = Path.GetDirectoryName(diagnosticsDir);
GenerateCodeFile(fileName, $"{rootNamespace}.Views");
Console.WriteLine(" Done!");
fileCount++;
}
}
Console.WriteLine();
Console.WriteLine("{0} files successfully generated.", fileCount);
Console.WriteLine();
}
private static void GenerateCodeFile(string cshtmlFilePath, string rootNamespace)
{
var basePath = Path.GetDirectoryName(cshtmlFilePath);
var fileName = Path.GetFileName(cshtmlFilePath);
var fileNameNoExtension = Path.GetFileNameWithoutExtension(fileName);
var codeLang = new CSharpRazorCodeLanguage();
var host = new RazorEngineHost(codeLang);
host.DefaultBaseClass = "Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView";
host.GeneratedClassContext = new GeneratedClassContext(
executeMethodName: GeneratedClassContext.DefaultExecuteMethodName,
writeMethodName: GeneratedClassContext.DefaultWriteMethodName,
writeLiteralMethodName: GeneratedClassContext.DefaultWriteLiteralMethodName,
writeToMethodName: "WriteTo",
writeLiteralToMethodName: "WriteLiteralTo",
templateTypeName: "HelperResult",
defineSectionMethodName: "DefineSection",
generatedTagHelperContext: new GeneratedTagHelperContext());
var engine = new RazorTemplateEngine(host);
using (var fileStream = File.OpenText(cshtmlFilePath))
{
var code = engine.GenerateCode(
input: fileStream,
className: fileNameNoExtension,
rootNamespace: Path.GetFileName(rootNamespace),
sourceFileName: fileName);
var source = code.GeneratedCode;
var startIndex = 0;
while (startIndex < source.Length)
{
var startMatch = @"<%$ include: ";
var endMatch = @" %>";
startIndex = source.IndexOf(startMatch, startIndex);
if (startIndex == -1)
{
break;
}
var endIndex = source.IndexOf(endMatch, startIndex);
if (endIndex == -1)
{
break;
}
var includeFileName = source.Substring(startIndex + startMatch.Length, endIndex - (startIndex + startMatch.Length));
includeFileName = SanitizeFileName(includeFileName);
Console.WriteLine(" Inlining file {0}", includeFileName);
var replacement = File.ReadAllText(Path.Combine(basePath, includeFileName)).Replace("\"", "\\\"").Replace("\n", "\\n").Replace("\r", "\\r");
source = source.Substring(0, startIndex) + replacement + source.Substring(endIndex + endMatch.Length);
startIndex = startIndex + replacement.Length;
}
File.WriteAllText(Path.Combine(basePath, string.Format("{0}.cs", fileNameNoExtension)), source);
}
}
private static string SanitizeFileName(string fileName)
{
// The Razor generated code sometimes splits strings across multiple lines
// which can hit the include file name, so we need to strip out the non-filename chars.
//ErrorPage.j" +
//"s
var invalidChars = new List<char>(Path.GetInvalidFileNameChars());
invalidChars.Add('+');
invalidChars.Add(' ');
//These are already in the list on windows, but for other platforms
//it seems like some of them are missing, so we add them explicitly
invalidChars.Add('"');
invalidChars.Add('\'');
invalidChars.Add('\r');
invalidChars.Add('\n');
return string.Join(string.Empty, fileName.Where(c => !invalidChars.Contains(c)).ToArray());
}
}
}

View File

@ -1,18 +0,0 @@
{
"version": "1.1.0-*",
"description": "Builds the pages for the Diagnostics projects. Runs in build.cmd.",
"buildOptions": {
"warningsAsErrors": true,
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.AspNetCore.Razor": "1.0.0",
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
}
},
"frameworks": {
"netcoreapp1.0": {}
}
}