Browse Source

Merge source code from aspnet/Diagnostics to this repo

Nate McMaster 7 years ago
parent
commit
6a6c88d80b
100 changed files with 12577 additions and 12 deletions
  1. 0 4
      .gitmodules
  2. 0 4
      build/artifacts.props
  3. 0 1
      build/buildorder.props
  4. 2 0
      build/dependencies.props
  5. 0 1
      build/submodules.props
  6. 37 0
      eng/Baseline.props
  7. 2 0
      eng/Dependencies.props
  8. 4 0
      eng/ProjectReferences.props
  9. 0 1
      eng/dependencies.temp.props
  10. 4 0
      eng/tools/BaselineGenerator/baseline.xml
  11. 0 1
      modules/Diagnostics
  12. 83 0
      src/Middleware/Diagnostics.Abstractions/src/CompilationFailure.cs
  13. 64 0
      src/Middleware/Diagnostics.Abstractions/src/DiagnosticMessage.cs
  14. 22 0
      src/Middleware/Diagnostics.Abstractions/src/ICompilationException.cs
  15. 12 0
      src/Middleware/Diagnostics.Abstractions/src/IExceptionHandlerFeature.cs
  16. 17 0
      src/Middleware/Diagnostics.Abstractions/src/IExceptionHandlerPathFeature.cs
  17. 16 0
      src/Middleware/Diagnostics.Abstractions/src/IStatusCodePagesFeature.cs
  18. 14 0
      src/Middleware/Diagnostics.Abstractions/src/IStatusCodeReExecuteFeature.cs
  19. 11 0
      src/Middleware/Diagnostics.Abstractions/src/Microsoft.AspNetCore.Diagnostics.Abstractions.csproj
  20. 356 0
      src/Middleware/Diagnostics.Abstractions/src/baseline.netcore.json
  21. 62 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/DatabaseErrorPageExtensions.cs
  22. 253 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/DatabaseErrorPageMiddleware.cs
  23. 21 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/DatabaseErrorPageOptions.cs
  24. 153 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/Internal/DiagnosticsEntityFrameworkCoreLoggerExtensions.cs
  25. 21 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.csproj
  26. 51 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/MigrationsEndPointExtensions.cs
  27. 159 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/MigrationsEndPointMiddleware.cs
  28. 26 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/MigrationsEndPointOptions.cs
  29. 8 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/Properties/AssemblyInfo.cs
  30. 408 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/Properties/Strings.Designer.cs
  31. 201 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/Strings.resx
  32. 424 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/DatabaseErrorPage.Designer.cs
  33. 135 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/DatabaseErrorPage.cshtml
  34. 35 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/DatabaseErrorPageModel.cs
  35. 78 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/ErrorPage.css
  36. 795 0
      src/Middleware/Diagnostics.EntityFrameworkCore/src/baseline.netcore.json
  37. 526 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/DatabaseErrorPageMiddlewareTest.cs
  38. 16 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/Diagnostics.EFCore.FunctionalTests.csproj
  39. 18 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/Helpers/PlatformHelper.cs
  40. 19 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/Helpers/StringHelpers.cs
  41. 61 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/Helpers/TestLoggerProvider.cs
  42. 224 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/MigrationsEndPointMiddlewareTest.cs
  43. 60 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/SqlServerTestStore.cs
  44. 13 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/TestModels/Blog.cs
  45. 18 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/TestModels/BloggingContext.cs
  46. 71 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/TestModels/BloggingContextWithMigrations.cs
  47. 33 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/TestModels/BloggingContextWithPendingModelChanges.cs
  48. 39 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/TestModels/BloggingContextWithSnapshotThatThrows.cs
  49. 28 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/DatabaseErrorPageOptionsTest.cs
  50. 199 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/DatabaseErrorPageTest.cs
  51. 41 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/Helpers/AssertHelpers.cs
  52. 19 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/Helpers/StringHelpers.cs
  53. 13 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests.csproj
  54. 21 0
      src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/TestHelperExtensions.cs
  55. 7 0
      src/Middleware/Diagnostics/src/.csslintrc
  56. 3 0
      src/Middleware/Diagnostics/src/.jshintrc
  57. 53 0
      src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageExtensions.cs
  58. 210 0
      src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs
  59. 37 0
      src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageOptions.cs
  60. 30 0
      src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/CompilationErrorModel.cs
  61. 751 0
      src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/CompilationErrorPage.Designer.cs
  62. 116 0
      src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/CompilationErrorPage.cshtml
  63. 1109 0
      src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/ErrorPage.Designer.cs
  64. 258 0
      src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/ErrorPage.cshtml
  65. 196 0
      src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/ErrorPage.css
  66. 192 0
      src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/ErrorPage.js
  67. 42 0
      src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/ErrorPageModel.cs
  68. 98 0
      src/Middleware/Diagnostics/src/ExceptionHandler/ExceptionHandlerExtensions.cs
  69. 14 0
      src/Middleware/Diagnostics/src/ExceptionHandler/ExceptionHandlerFeature.cs
  70. 115 0
      src/Middleware/Diagnostics/src/ExceptionHandler/ExceptionHandlerMiddleware.cs
  71. 14 0
      src/Middleware/Diagnostics/src/ExceptionHandler/ExceptionHandlerOptions.cs
  72. 54 0
      src/Middleware/Diagnostics/src/Internal/DiagnosticsLoggerExtensions.cs
  73. 30 0
      src/Middleware/Diagnostics/src/Microsoft.AspNetCore.Diagnostics.csproj
  74. 9 0
      src/Middleware/Diagnostics/src/Properties/AssemblyInfo.cs
  75. 618 0
      src/Middleware/Diagnostics/src/Properties/Resources.Designer.cs
  76. 253 0
      src/Middleware/Diagnostics/src/Resources.resx
  77. 24 0
      src/Middleware/Diagnostics/src/StatusCodePage/StatusCodeContext.cs
  78. 206 0
      src/Middleware/Diagnostics/src/StatusCodePage/StatusCodePagesExtensions.cs
  79. 13 0
      src/Middleware/Diagnostics/src/StatusCodePage/StatusCodePagesFeature.cs
  80. 55 0
      src/Middleware/Diagnostics/src/StatusCodePage/StatusCodePagesMiddleware.cs
  81. 48 0
      src/Middleware/Diagnostics/src/StatusCodePage/StatusCodePagesOptions.cs
  82. 14 0
      src/Middleware/Diagnostics/src/StatusCodePage/StatusCodeReExecuteFeature.cs
  83. 373 0
      src/Middleware/Diagnostics/src/WelcomePage/Views/Obsolete/WelcomePage.cs
  84. 167 0
      src/Middleware/Diagnostics/src/WelcomePage/Views/Obsolete/WelcomePage.cshtml
  85. 366 0
      src/Middleware/Diagnostics/src/WelcomePage/Views/WelcomePage.Designer.cs
  86. 167 0
      src/Middleware/Diagnostics/src/WelcomePage/Views/WelcomePage.cshtml
  87. 90 0
      src/Middleware/Diagnostics/src/WelcomePage/WelcomePageExtensions.cs
  88. 60 0
      src/Middleware/Diagnostics/src/WelcomePage/WelcomePageMiddleware.cs
  89. 19 0
      src/Middleware/Diagnostics/src/WelcomePage/WelcomePageOptions.cs
  90. 32 0
      src/Middleware/Diagnostics/src/_gruntfile.js
  91. 1 0
      src/Middleware/Diagnostics/src/_gruntfile.readme
  92. 12 0
      src/Middleware/Diagnostics/src/_package.json
  93. 1543 0
      src/Middleware/Diagnostics/src/baseline.netcore.json
  94. 38 0
      src/Middleware/Diagnostics/test/FunctionalTests/DatabaseErrorPageSampleTest.cs
  95. 36 0
      src/Middleware/Diagnostics/test/FunctionalTests/DeveloperExceptionPageSampleTest.cs
  96. 25 0
      src/Middleware/Diagnostics/test/FunctionalTests/Diagnostics.FunctionalTests.csproj
  97. 35 0
      src/Middleware/Diagnostics/test/FunctionalTests/ExceptionHandlerSampleTest.cs
  98. 34 0
      src/Middleware/Diagnostics/test/FunctionalTests/MiddlewareAnalysisSampleTest.cs
  99. 76 0
      src/Middleware/Diagnostics/test/FunctionalTests/StatusCodeSampleTest.cs
  100. 41 0
      src/Middleware/Diagnostics/test/FunctionalTests/TestFixture.cs

+ 0 - 4
.gitmodules

@@ -10,10 +10,6 @@
 	path = modules/CORS
 	url = https://github.com/aspnet/CORS.git
 	branch = release/2.1
-[submodule "modules/Diagnostics"]
-	path = modules/Diagnostics
-	url = https://github.com/aspnet/Diagnostics.git
-	branch = release/2.1
 [submodule "modules/EntityFrameworkCore"]
 	path = modules/EntityFrameworkCore
 	url = https://github.com/aspnet/EntityFrameworkCore.git

+ 0 - 4
build/artifacts.props

@@ -67,9 +67,7 @@
     <PackageArtifact Include="Microsoft.AspNetCore.DataProtection" AllMetapackage="true" AppMetapackage="true" Category="ship" />
     <PackageArtifact Include="Microsoft.AspNetCore.DeveloperCertificates.XPlat" Category="shipoob" />
     <PackageArtifact Include="Microsoft.AspNetCore.Diagnostics.Abstractions" AllMetapackage="true" AppMetapackage="true" Category="ship" />
-    <PackageArtifact Include="Microsoft.AspNetCore.Diagnostics.Elm" Category="noship" />
     <PackageArtifact Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" AllMetapackage="true" AppMetapackage="true" Category="ship" />
-    <PackageArtifact Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Category="noship" />
     <PackageArtifact Include="Microsoft.AspNetCore.Diagnostics" AllMetapackage="true" AppMetapackage="true" Category="ship" />
     <PackageArtifact Include="Microsoft.AspNetCore.HostFiltering" AllMetapackage="true" AppMetapackage="true" Category="ship" />
     <PackageArtifact Include="Microsoft.AspNetCore.Hosting.Abstractions" AllMetapackage="true" AppMetapackage="true" Category="ship" />
@@ -179,8 +177,6 @@
     <PackageArtifact Include="Microsoft.EntityFrameworkCore.Tools" AllMetapackage="true" AppMetapackage="true" Category="ship" />
     <PackageArtifact Include="Microsoft.EntityFrameworkCore" AllMetapackage="true" AppMetapackage="true" Category="ship" />
     <PackageArtifact Include="Microsoft.Extensions.ApplicationModelDetection" Category="noship" />
-    <PackageArtifact Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Category="noship" />
-    <PackageArtifact Include="Microsoft.Extensions.Diagnostics.HealthChecks" Category="noship" />
     <PackageArtifact Include="Microsoft.Extensions.Identity.Core" AllMetapackage="true" AppMetapackage="true" Category="ship" />
     <PackageArtifact Include="Microsoft.Extensions.Identity.Stores" AllMetapackage="true" AppMetapackage="true" Category="ship" />
     <PackageArtifact Include="Microsoft.Extensions.Localization.Abstractions" AllMetapackage="true" AppMetapackage="true" Category="ship" />

+ 0 - 1
build/buildorder.props

@@ -19,7 +19,6 @@
     <RepositoryBuildOrder Include="ResponseCaching" Order="11" />
     <RepositoryBuildOrder Include="Session" Order="11" RootPath="$(RepositoryRoot)src\Session\" />
     <RepositoryBuildOrder Include="ServerTests" Order="11" RootPath="$(RepositoryRoot)src\ServerTests\" />
-    <RepositoryBuildOrder Include="Diagnostics" Order="12" />
     <RepositoryBuildOrder Include="Localization" Order="12" />
     <RepositoryBuildOrder Include="Security" Order="13" />
     <RepositoryBuildOrder Include="MetaPackages" Order="13" RootPath="$(RepositoryRoot)src\MetaPackages\" />

+ 2 - 0
build/dependencies.props

@@ -92,6 +92,8 @@
     <MicrosoftExtensionsBuffersTestingSourcesPackageVersion>2.1.1</MicrosoftExtensionsBuffersTestingSourcesPackageVersion>
     <MicrosoftAspNetCoreHostingWebHostBuilderFactorySourcesPackageVersion>2.1.1</MicrosoftAspNetCoreHostingWebHostBuilderFactorySourcesPackageVersion>
     <MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>0.5.1</MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>
+    <MicrosoftEntityFrameworkCoreInMemoryPackageVersion>2.1.4</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
+    <MicrosoftEntityFrameworkCoreSqlServerPackageVersion>2.1.4</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
 
     <!-- External and partner dependencies -->
     <AngleSharpPackageVersion>0.9.9</AngleSharpPackageVersion>

+ 0 - 1
build/submodules.props

@@ -53,7 +53,6 @@
     <ShippedRepository Include="AzureIntegration" RootPath="$(RepositoryRoot)src\AzureIntegration\" />
     <ShippedRepository Include="BasicMiddleware" />
     <ShippedRepository Include="CORS" />
-    <ShippedRepository Include="Diagnostics" />
     <ShippedRepository Include="EntityFrameworkCore" />
     <ShippedRepository Include="HttpSysServer" />
     <ShippedRepository Include="Identity" />

+ 37 - 0
eng/Baseline.props

@@ -126,6 +126,34 @@
     <BaselinePackageReference Include="System.Security.Cryptography.Xml" Version="[4.5.0, )" />
     <BaselinePackageReference Include="System.Security.Principal.Windows" Version="[4.5.0, )" />
   </ItemGroup>
+  <!-- Package: Microsoft.AspNetCore.Diagnostics.Abstractions-->
+  <PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Diagnostics.Abstractions' ">
+    <BaselinePackageVersion>2.1.1</BaselinePackageVersion>
+  </PropertyGroup>
+  <ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Diagnostics.Abstractions' AND '$(TargetFramework)' == 'netstandard2.0' " />
+  <!-- Package: Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore-->
+  <PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore' ">
+    <BaselinePackageVersion>2.1.1</BaselinePackageVersion>
+  </PropertyGroup>
+  <ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore' AND '$(TargetFramework)' == 'netstandard2.0' ">
+    <BaselinePackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="[2.1.1, )" />
+    <BaselinePackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="[2.1.1, )" />
+  </ItemGroup>
+  <!-- Package: Microsoft.AspNetCore.Diagnostics-->
+  <PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Diagnostics' ">
+    <BaselinePackageVersion>2.1.1</BaselinePackageVersion>
+  </PropertyGroup>
+  <ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Diagnostics' AND '$(TargetFramework)' == 'netstandard2.0' ">
+    <BaselinePackageReference Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="[2.1.1, )" />
+    <BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="[2.1.1, )" />
+    <BaselinePackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="[2.1.1, )" />
+    <BaselinePackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="[2.1.1, )" />
+    <BaselinePackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="[2.1.1, )" />
+    <BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[2.1.1, )" />
+    <BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.1.1, )" />
+    <BaselinePackageReference Include="System.Diagnostics.DiagnosticSource" Version="[4.5.0, )" />
+    <BaselinePackageReference Include="System.Reflection.Metadata" Version="[1.6.0, )" />
+  </ItemGroup>
   <!-- Package: Microsoft.AspNetCore.Hosting.Abstractions-->
   <PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting.Abstractions' ">
     <BaselinePackageVersion>2.1.1</BaselinePackageVersion>
@@ -224,6 +252,15 @@
     <BaselinePackageReference Include="Microsoft.CSharp" Version="[4.5.0, )" />
     <BaselinePackageReference Include="Newtonsoft.Json" Version="[11.0.2, )" />
   </ItemGroup>
+  <!-- Package: Microsoft.AspNetCore.MiddlewareAnalysis-->
+  <PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.MiddlewareAnalysis' ">
+    <BaselinePackageVersion>2.1.1</BaselinePackageVersion>
+  </PropertyGroup>
+  <ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.MiddlewareAnalysis' AND '$(TargetFramework)' == 'netstandard2.0' ">
+    <BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="[2.1.1, )" />
+    <BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[2.1.1, )" />
+    <BaselinePackageReference Include="System.Diagnostics.DiagnosticSource" Version="[4.5.0, )" />
+  </ItemGroup>
   <!-- Package: Microsoft.AspNetCore.Owin-->
   <PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Owin' ">
     <BaselinePackageVersion>2.1.1</BaselinePackageVersion>

+ 2 - 0
eng/Dependencies.props

@@ -13,6 +13,8 @@
     <LatestPackageReference Include="Microsoft.AspNetCore.Certificates.Generation.Sources" Version="$(MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion)" />
     <LatestPackageReference Include="Microsoft.AspNetCore.Testing" Version="$(MicrosoftAspNetCoreTestingPackageVersion)" />
     <LatestPackageReference Include="Microsoft.CSharp" Version="$(MicrosoftCSharpPackageVersion)" />
+    <LatestPackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="$(MicrosoftEntityFrameworkCoreInMemoryPackageVersion)" />
+    <LatestPackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="$(MicrosoftEntityFrameworkCoreSqlServerPackageVersion)" />
     <LatestPackageReference Include="Microsoft.Extensions.ActivatorUtilities.Sources" Version="$(MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion)" />
     <LatestPackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" Version="$(MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion)" />
     <LatestPackageReference Include="Microsoft.Extensions.CopyOnWriteDictionary.Sources" Version="$(MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion)" />

+ 4 - 0
eng/ProjectReferences.props

@@ -39,6 +39,10 @@
     <ProjectReferenceProvider Include="dotnet-user-secrets" ProjectPath="$(RepositoryRoot)src\Tools\dotnet-user-secrets\src\dotnet-user-secrets.csproj" />
     <ProjectReferenceProvider Include="dotnet-watch" ProjectPath="$(RepositoryRoot)src\Tools\dotnet-watch\src\dotnet-watch.csproj" />
     <ProjectReferenceProvider Include="Microsoft.AspNetCore.DeveloperCertificates.XPlat" ProjectPath="$(RepositoryRoot)src\Tools\FirstRunCertGenerator\src\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj" />
+    <ProjectReferenceProvider Include="Microsoft.AspNetCore.Diagnostics.Abstractions" ProjectPath="$(RepositoryRoot)src\Middleware\Diagnostics.Abstractions\src\Microsoft.AspNetCore.Diagnostics.Abstractions.csproj" />
+    <ProjectReferenceProvider Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" ProjectPath="$(RepositoryRoot)src\Middleware\Diagnostics.EntityFrameworkCore\src\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.csproj" />
+    <ProjectReferenceProvider Include="Microsoft.AspNetCore.Diagnostics" ProjectPath="$(RepositoryRoot)src\Middleware\Diagnostics\src\Microsoft.AspNetCore.Diagnostics.csproj" />
+    <ProjectReferenceProvider Include="Microsoft.AspNetCore.MiddlewareAnalysis" ProjectPath="$(RepositoryRoot)src\Middleware\MiddlewareAnalysis\src\Microsoft.AspNetCore.MiddlewareAnalysis.csproj" />
     <ProjectReferenceProvider Include="Microsoft.AspNetCore.WebSockets" ProjectPath="$(RepositoryRoot)src\Middleware\WebSockets\src\Microsoft.AspNetCore.WebSockets.csproj" />
   </ItemGroup>
 </Project>

+ 0 - 1
eng/dependencies.temp.props

@@ -4,7 +4,6 @@ This is required to provide dependencies for samples and tests.
  -->
 <Project>
   <ItemGroup>
-    <LatestPackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.1.1" />
     <LatestPackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.1.1" />
     <LatestPackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.1" />
   </ItemGroup>

+ 4 - 0
eng/tools/BaselineGenerator/baseline.xml

@@ -15,6 +15,9 @@
   <Package Id="Microsoft.AspNetCore.DataProtection.Redis" Version="0.4.1" />
   <Package Id="Microsoft.AspNetCore.DataProtection.SystemWeb" Version="2.1.1" />
   <Package Id="Microsoft.AspNetCore.DataProtection" Version="2.1.1" />
+  <Package Id="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="2.1.1" />
+  <Package Id="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="2.1.1" />
+  <Package Id="Microsoft.AspNetCore.Diagnostics" Version="2.1.1" />
   <Package Id="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.1.1" />
   <Package Id="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.1.1" />
   <Package Id="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.1.1" />
@@ -25,6 +28,7 @@
   <Package Id="Microsoft.AspNetCore.Http.Features" Version="2.1.1" />
   <Package Id="Microsoft.AspNetCore.Http" Version="2.1.1" />
   <Package Id="Microsoft.AspNetCore.JsonPatch" Version="2.1.1" />
+  <Package Id="Microsoft.AspNetCore.MiddlewareAnalysis" Version="2.1.1" />
   <Package Id="Microsoft.AspNetCore.Owin" Version="2.1.1" />
   <Package Id="Microsoft.AspNetCore.Server.Kestrel.Core" Version="2.1.3" />
   <Package Id="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.1.3" />

+ 0 - 1
modules/Diagnostics

@@ -1 +0,0 @@
-Subproject commit 8893337fb090c523843564a91054996bfcc3cc42

+ 83 - 0
src/Middleware/Diagnostics.Abstractions/src/CompilationFailure.cs

@@ -0,0 +1,83 @@
+// 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.Collections.Generic;
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    /// <summary>
+    /// Describes a failure compiling a specific file.
+    /// </summary>
+    public class CompilationFailure
+    {
+        /// <summary>
+        /// Initializes a new instance of <see cref="CompilationFailure"/>.
+        /// </summary>
+        /// <param name="sourceFilePath">Path for the file that produced the compilation failure.</param>
+        /// <param name="sourceFileContent">Contents of the file being compiled.</param>
+        /// <param name="compiledContent">For templated languages (such as Asp.Net Core Razor), the generated content.
+        /// </param>
+        /// <param name="messages">One or or more <see cref="DiagnosticMessage"/> instances.</param>
+        public CompilationFailure(
+            string sourceFilePath,
+            string sourceFileContent,
+            string compiledContent,
+            IEnumerable<DiagnosticMessage> messages)
+            : this(sourceFilePath, sourceFileContent, compiledContent, messages, failureSummary: null)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of <see cref="CompilationFailure"/>.
+        /// </summary>
+        /// <param name="sourceFilePath">Path for the file that produced the compilation failure.</param>
+        /// <param name="sourceFileContent">Contents of the file being compiled.</param>
+        /// <param name="compiledContent">For templated languages (such as Asp.Net Core Razor), the generated content.
+        /// </param>
+        /// <param name="messages">One or or more <see cref="DiagnosticMessage"/> instances.</param>
+        /// <param name="failureSummary">Summary message or instructions to fix the failure.</param>
+        public CompilationFailure(
+            string sourceFilePath,
+            string sourceFileContent,
+            string compiledContent,
+            IEnumerable<DiagnosticMessage> messages,
+            string failureSummary)
+        {
+            SourceFilePath = sourceFilePath;
+            SourceFileContent = sourceFileContent;
+            CompiledContent = compiledContent;
+            Messages = messages;
+            FailureSummary = failureSummary;
+        }
+
+        /// <summary>
+        /// Path of the file that produced the compilation failure.
+        /// </summary>
+        public string SourceFilePath { get; }
+
+        /// <summary>
+        /// Contents of the file.
+        /// </summary>
+        public string SourceFileContent { get; }
+
+        /// <summary>
+        /// Contents being compiled.
+        /// </summary>
+        /// <remarks>
+        /// For templated files, the <see cref="SourceFileContent"/> represents the original content and
+        /// <see cref="CompiledContent"/> represents the transformed content. This property can be null if
+        /// the exception is encountered during transformation.
+        /// </remarks>
+        public string CompiledContent { get; }
+
+        /// <summary>
+        /// Gets a sequence of <see cref="DiagnosticMessage"/> produced as a result of compilation.
+        /// </summary>
+        public IEnumerable<DiagnosticMessage> Messages { get; }
+
+        /// <summary>
+        /// Summary message or instructions to fix the failure.
+        /// </summary>
+        public string FailureSummary { get; }
+    }
+}

+ 64 - 0
src/Middleware/Diagnostics.Abstractions/src/DiagnosticMessage.cs

@@ -0,0 +1,64 @@
+// 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.
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    /// <summary>
+    /// A single diagnostic message.
+    /// </summary>
+    public class DiagnosticMessage
+    {
+        public DiagnosticMessage(
+            string message,
+            string formattedMessage,
+            string filePath,
+            int startLine,
+            int startColumn,
+            int endLine,
+            int endColumn)
+        {
+            Message = message;
+            SourceFilePath = filePath;
+            StartLine = startLine;
+            EndLine = endLine;
+            StartColumn = startColumn;
+            EndColumn = endColumn;
+            FormattedMessage = formattedMessage;
+        }
+
+        /// <summary>
+        /// Path of the file that produced the message.
+        /// </summary>
+        public string SourceFilePath { get; }
+
+        /// <summary>
+        /// Gets the error message.
+        /// </summary>
+        public string Message { get; }
+
+        /// <summary>
+        /// Gets the one-based line index for the start of the compilation error.
+        /// </summary>
+        public int StartLine { get; }
+
+        /// <summary>
+        /// Gets the zero-based column index for the start of the compilation error.
+        /// </summary>
+        public int StartColumn { get; }
+
+        /// <summary>
+        /// Gets the one-based line index for the end of the compilation error.
+        /// </summary>
+        public int EndLine { get; }
+
+        /// <summary>
+        /// Gets the zero-based column index for the end of the compilation error.
+        /// </summary>
+        public int EndColumn { get; }
+
+        /// <summary>
+        /// Gets the formatted error message.
+        /// </summary>
+        public string FormattedMessage { get; }
+    }
+}

+ 22 - 0
src/Middleware/Diagnostics.Abstractions/src/ICompilationException.cs

@@ -0,0 +1,22 @@
+// 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.Collections.Generic;
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    /// <summary>
+    /// Specifies the contract for an exception representing compilation failure.
+    /// </summary>
+    /// <remarks>
+    /// This interface is implemented on exceptions thrown during compilation to enable consumers
+    /// to read compilation-related data out of the exception
+    /// </remarks>
+    public interface ICompilationException
+    {
+        /// <summary>
+        /// Gets a sequence of <see cref="CompilationFailure"/> with compilation failures.
+        /// </summary>
+        IEnumerable<CompilationFailure> CompilationFailures { get; }
+    }
+}

+ 12 - 0
src/Middleware/Diagnostics.Abstractions/src/IExceptionHandlerFeature.cs

@@ -0,0 +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;
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    public interface IExceptionHandlerFeature
+    {
+        Exception Error { get; }
+    }
+}

+ 17 - 0
src/Middleware/Diagnostics.Abstractions/src/IExceptionHandlerPathFeature.cs

@@ -0,0 +1,17 @@
+// 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.
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    /// <summary>
+    /// Represents an exception handler with the original path of the request.
+    /// </summary>
+    public interface IExceptionHandlerPathFeature : IExceptionHandlerFeature
+    {
+        /// <summary>
+        /// The portion of the request path that identifies the requested resource. The value
+        /// is un-escaped.
+        /// </summary>
+        string Path { get; }
+    }
+}

+ 16 - 0
src/Middleware/Diagnostics.Abstractions/src/IStatusCodePagesFeature.cs

@@ -0,0 +1,16 @@
+// 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.
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    /// <summary>
+    /// Represents the Status code pages feature.
+    /// </summary>
+    public interface IStatusCodePagesFeature
+    {
+        /// <summary>
+        /// Indicates if the status code middleware will handle responses.
+        /// </summary>
+        bool Enabled { get; set; }
+    }
+}

+ 14 - 0
src/Middleware/Diagnostics.Abstractions/src/IStatusCodeReExecuteFeature.cs

@@ -0,0 +1,14 @@
+// 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.
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    public interface IStatusCodeReExecuteFeature
+    {
+        string OriginalPathBase { get; set; }
+
+        string OriginalPath { get; set; }
+
+        string OriginalQueryString { get; set; }
+    }
+}

+ 11 - 0
src/Middleware/Diagnostics.Abstractions/src/Microsoft.AspNetCore.Diagnostics.Abstractions.csproj

@@ -0,0 +1,11 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <Description>ASP.NET Core diagnostics middleware abstractions and feature interface definitions.</Description>
+    <TargetFramework>netstandard2.0</TargetFramework>
+    <NoWarn>$(NoWarn);CS1591</NoWarn>
+    <GenerateDocumentationFile>true</GenerateDocumentationFile>
+    <PackageTags>aspnetcore;diagnostics</PackageTags>
+  </PropertyGroup>
+
+</Project>

+ 356 - 0
src/Middleware/Diagnostics.Abstractions/src/baseline.netcore.json

@@ -0,0 +1,356 @@
+{
+  "AssemblyIdentity": "Microsoft.AspNetCore.Diagnostics.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
+  "Types": [
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.CompilationFailure",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_SourceFilePath",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_SourceFileContent",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_CompiledContent",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Messages",
+          "Parameters": [],
+          "ReturnType": "System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Diagnostics.DiagnosticMessage>",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_FailureSummary",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "sourceFilePath",
+              "Type": "System.String"
+            },
+            {
+              "Name": "sourceFileContent",
+              "Type": "System.String"
+            },
+            {
+              "Name": "compiledContent",
+              "Type": "System.String"
+            },
+            {
+              "Name": "messages",
+              "Type": "System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Diagnostics.DiagnosticMessage>"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "sourceFilePath",
+              "Type": "System.String"
+            },
+            {
+              "Name": "sourceFileContent",
+              "Type": "System.String"
+            },
+            {
+              "Name": "compiledContent",
+              "Type": "System.String"
+            },
+            {
+              "Name": "messages",
+              "Type": "System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Diagnostics.DiagnosticMessage>"
+            },
+            {
+              "Name": "failureSummary",
+              "Type": "System.String"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.DiagnosticMessage",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_SourceFilePath",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Message",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_StartLine",
+          "Parameters": [],
+          "ReturnType": "System.Int32",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_StartColumn",
+          "Parameters": [],
+          "ReturnType": "System.Int32",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_EndLine",
+          "Parameters": [],
+          "ReturnType": "System.Int32",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_EndColumn",
+          "Parameters": [],
+          "ReturnType": "System.Int32",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_FormattedMessage",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "message",
+              "Type": "System.String"
+            },
+            {
+              "Name": "formattedMessage",
+              "Type": "System.String"
+            },
+            {
+              "Name": "filePath",
+              "Type": "System.String"
+            },
+            {
+              "Name": "startLine",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "startColumn",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "endLine",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "endColumn",
+              "Type": "System.Int32"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.ICompilationException",
+      "Visibility": "Public",
+      "Kind": "Interface",
+      "Abstract": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_CompilationFailures",
+          "Parameters": [],
+          "ReturnType": "System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Diagnostics.CompilationFailure>",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature",
+      "Visibility": "Public",
+      "Kind": "Interface",
+      "Abstract": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_Error",
+          "Parameters": [],
+          "ReturnType": "System.Exception",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature",
+      "Visibility": "Public",
+      "Kind": "Interface",
+      "Abstract": true,
+      "ImplementedInterfaces": [
+        "Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature"
+      ],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_Path",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.IStatusCodePagesFeature",
+      "Visibility": "Public",
+      "Kind": "Interface",
+      "Abstract": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_Enabled",
+          "Parameters": [],
+          "ReturnType": "System.Boolean",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_Enabled",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Boolean"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.IStatusCodeReExecuteFeature",
+      "Visibility": "Public",
+      "Kind": "Interface",
+      "Abstract": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_OriginalPathBase",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_OriginalPathBase",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_OriginalPath",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_OriginalPath",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_OriginalQueryString",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_OriginalQueryString",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    }
+  ]
+}

+ 62 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/DatabaseErrorPageExtensions.cs

@@ -0,0 +1,62 @@
+// 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 Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore;
+using Microsoft.Extensions.Options;
+
+// ReSharper disable once CheckNamespace
+namespace Microsoft.AspNetCore.Builder
+{
+    /// <summary>
+    /// <see cref="IApplicationBuilder"/> extension methods for the <see cref="DatabaseErrorPageMiddleware"/>.
+    /// </summary>
+    public static class DatabaseErrorPageExtensions
+    {
+        /// <summary>
+        /// Captures synchronous and asynchronous database related exceptions from the pipeline that may be resolved using Entity Framework
+        /// migrations. When these exceptions occur an HTML response with details of possible actions to resolve the issue is generated.
+        /// </summary>
+        /// <param name="app">The <see cref="IApplicationBuilder"/> to register the middleware with.</param>
+        /// <returns>The same <see cref="IApplicationBuilder"/> instance so that multiple calls can be chained.</returns>
+        public static IApplicationBuilder UseDatabaseErrorPage(this IApplicationBuilder app)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            return app.UseDatabaseErrorPage(new DatabaseErrorPageOptions());
+        }
+
+        /// <summary>
+        /// Captures synchronous and asynchronous database related exceptions from the pipeline that may be resolved using Entity Framework
+        /// migrations. When these exceptions occur an HTML response with details of possible actions to resolve the issue is generated.
+        /// </summary>
+        /// <param name="app">The <see cref="IApplicationBuilder"/> to register the middleware with.</param>
+        /// <param name="options">A <see cref="DatabaseErrorPageOptions"/> that specifies options for the middleware.</param>
+        /// <returns>The same <see cref="IApplicationBuilder"/> instance so that multiple calls can be chained.</returns>
+        public static IApplicationBuilder UseDatabaseErrorPage(
+            this IApplicationBuilder app, DatabaseErrorPageOptions options)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            app = app.UseMiddleware<DatabaseErrorPageMiddleware>(Options.Create(options));
+
+            app.UseMigrationsEndPoint(new MigrationsEndPointOptions
+            {
+                Path = options.MigrationsEndPointPath
+            });
+
+            return app;
+        }
+    }
+}

+ 253 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/DatabaseErrorPageMiddleware.cs

@@ -0,0 +1,253 @@
+// 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.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Internal;
+using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views;
+using Microsoft.AspNetCore.Http;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
+{
+    /// <summary>
+    ///     Captures synchronous and asynchronous database related exceptions from the pipeline that may be resolved using Entity Framework
+    ///     migrations. When these exceptions occur an HTML response with details of possible actions to resolve the issue is generated.
+    /// </summary>
+    public class DatabaseErrorPageMiddleware : IObserver<DiagnosticListener>, IObserver<KeyValuePair<string, object>>
+    {
+        private static readonly AsyncLocal<DiagnosticHolder> _localDiagnostic = new AsyncLocal<DiagnosticHolder>();
+
+        private sealed class DiagnosticHolder
+        {
+            public void Hold(Exception exception, Type contextType)
+            {
+                Exception = exception;
+                ContextType = contextType;
+            }
+
+            public Exception Exception { get; private set; }
+            public Type ContextType { get; private set; }
+        }
+
+        private readonly RequestDelegate _next;
+        private readonly DatabaseErrorPageOptions _options;
+        private readonly ILogger _logger;
+
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="DatabaseErrorPageMiddleware" /> class
+        /// </summary>
+        /// <param name="next">Delegate to execute the next piece of middleware in the request pipeline.</param>
+        /// <param name="loggerFactory">
+        ///     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>
+        public DatabaseErrorPageMiddleware(
+            RequestDelegate next,
+            ILoggerFactory loggerFactory,
+            IOptions<DatabaseErrorPageOptions> options)
+        {
+            if (next == null)
+            {
+                throw new ArgumentNullException(nameof(next));
+            }
+
+            if (loggerFactory == null)
+            {
+                throw new ArgumentNullException(nameof(loggerFactory));
+            }
+
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            _next = next;
+            _options = options.Value;
+            _logger = loggerFactory.CreateLogger<DatabaseErrorPageMiddleware>();
+
+            // Note: this currently leaks if the server hosting this middleware is disposed.
+            // See aspnet/Home #2825
+            DiagnosticListener.AllListeners.Subscribe(this);
+        }
+
+        /// <summary>
+        ///     Process an individual request.
+        /// </summary>
+        /// <param name="httpContext">The HTTP context for the current request.</param>
+        /// <returns>A task that represents the asynchronous operation.</returns>
+        public virtual async Task Invoke(HttpContext httpContext)
+        {
+            if (httpContext == null)
+            {
+                throw new ArgumentNullException(nameof(httpContext));
+            }
+
+            try
+            {
+                // Because CallContext is cloned at each async operation we cannot
+                // lazily create the error object when an error is encountered, otherwise
+                // it will not be available to code outside of the current async context. 
+                // We create it ahead of time so that any cloning just clones the reference
+                // to the object that will hold any errors.
+
+                _localDiagnostic.Value = new DiagnosticHolder();
+
+                await _next(httpContext);
+            }
+            catch (Exception exception)
+            {
+                try
+                {
+                    if (ShouldDisplayErrorPage(exception))
+                    {
+                        var contextType = _localDiagnostic.Value.ContextType;
+                        var context = (DbContext)httpContext.RequestServices.GetService(contextType);
+
+                        if (context == null)
+                        {
+                            _logger.ContextNotRegisteredDatabaseErrorPageMiddleware(contextType.FullName);
+                        }
+                        else
+                        {
+                            var relationalDatabaseCreator = context.GetService<IDatabaseCreator>() as IRelationalDatabaseCreator;
+                            if (relationalDatabaseCreator == null)
+                            {
+                                _logger.NotRelationalDatabase();
+                            }
+                            else
+                            {
+                                var databaseExists = await relationalDatabaseCreator.ExistsAsync();
+
+                                var migrationsAssembly = context.GetService<IMigrationsAssembly>();
+                                var modelDiffer = context.GetService<IMigrationsModelDiffer>();
+
+                                // HasDifferences will return true if there is no model snapshot, but if there is an existing database
+                                // and no model snapshot then we don't want to show the error page since they are most likely targeting
+                                // and existing database and have just misconfigured their model
+
+                                var pendingModelChanges
+                                    = (!databaseExists || migrationsAssembly.ModelSnapshot != null)
+                                      && modelDiffer.HasDifferences(migrationsAssembly.ModelSnapshot?.Model, context.Model);
+
+                                var pendingMigrations
+                                    = (databaseExists
+                                        ? await context.Database.GetPendingMigrationsAsync()
+                                        : context.Database.GetMigrations())
+                                    .ToArray();
+
+                                if (pendingModelChanges || pendingMigrations.Any())
+                                {
+                                    var page = new DatabaseErrorPage
+                                    {
+                                        Model = new DatabaseErrorPageModel(
+                                            contextType, exception, databaseExists, pendingModelChanges, pendingMigrations, _options)
+                                    };
+
+                                    await page.ExecuteAsync(httpContext);
+
+                                    return;
+                                }
+                            }
+                        }
+                    }
+                }
+                catch (Exception e)
+                {
+                    _logger.DatabaseErrorPageMiddlewareException(e);
+                }
+
+                throw;
+            }
+        }
+
+        private bool ShouldDisplayErrorPage(Exception exception)
+        {
+            _logger.AttemptingToMatchException(exception.GetType());
+
+            var lastRecordedException = _localDiagnostic.Value.Exception;
+
+            if (lastRecordedException == null)
+            {
+                _logger.NoRecordedException();
+
+                return false;
+            }
+
+            var match = false;
+
+            for (var e = exception; e != null && !match; e = e.InnerException)
+            {
+                match = lastRecordedException == e;
+            }
+
+            if (!match)
+            {
+                _logger.NoMatch();
+
+                return false;
+            }
+
+            _logger.Matched();
+
+            return true;
+        }
+
+        void IObserver<DiagnosticListener>.OnNext(DiagnosticListener diagnosticListener)
+        {
+            if (diagnosticListener.Name == DbLoggerCategory.Name)
+            {
+                diagnosticListener.Subscribe(this);
+            }
+        }
+
+        void IObserver<KeyValuePair<string, object>>.OnNext(KeyValuePair<string, object> keyValuePair)
+        {
+            switch (keyValuePair.Value)
+            {
+                // NB: _localDiagnostic.Value can be null when this middleware has been leaked.
+
+                case DbContextErrorEventData contextErrorEventData:
+                    {
+                        _localDiagnostic.Value?.Hold(contextErrorEventData.Exception, contextErrorEventData.Context.GetType());
+
+                        break;
+                    }
+                case DbContextTypeErrorEventData contextTypeErrorEventData:
+                    {
+                        _localDiagnostic.Value?.Hold(contextTypeErrorEventData.Exception, contextTypeErrorEventData.ContextType);
+
+                        break;
+                    }
+            }
+        }
+
+        void IObserver<DiagnosticListener>.OnCompleted()
+        {
+        }
+
+        void IObserver<DiagnosticListener>.OnError(Exception error)
+        {
+        }
+
+        void IObserver<KeyValuePair<string, object>>.OnCompleted()
+        {
+        }
+
+        void IObserver<KeyValuePair<string, object>>.OnError(Exception error)
+        {
+        }
+    }
+}

+ 21 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/DatabaseErrorPageOptions.cs

@@ -0,0 +1,21 @@
+// 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 Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore;
+using Microsoft.AspNetCore.Http;
+
+// ReSharper disable once CheckNamespace
+namespace Microsoft.AspNetCore.Builder
+{
+    /// <summary>
+    /// Options for the <see cref="DatabaseErrorPageMiddleware"/>.
+    /// </summary>
+    public class DatabaseErrorPageOptions
+    {
+        /// <summary>
+        /// Gets or sets the path that <see cref="MigrationsEndPointMiddleware"/> will listen
+        /// for requests to execute migrations commands.
+        /// </summary>
+        public virtual PathString MigrationsEndPointPath { get; set; } = MigrationsEndPointOptions.DefaultPath;
+    }
+}

+ 153 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/Internal/DiagnosticsEntityFrameworkCoreLoggerExtensions.cs

@@ -0,0 +1,153 @@
+// 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 Microsoft.Extensions.Logging;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Internal
+{
+    internal static class DiagnosticsEntityFrameworkCoreLoggerExtensions
+    {
+        // MigrationsEndPointMiddleware
+        private static readonly Action<ILogger, Exception> _noContextType = LoggerMessage.Define(
+            LogLevel.Error,
+            new EventId(1, "NoContextType"),
+            "No context type was specified. Ensure the form data from the request includes a contextTypeName value, specifying the context to apply migrations for.");
+
+        private static readonly Action<ILogger, string, Exception> _invalidContextType = LoggerMessage.Define<string>(
+            LogLevel.Error,
+            new EventId(2, "InvalidContextType"),
+            "The context type '{ContextTypeName}' could not be loaded. Ensure this is the correct type name for the context you are trying to apply migrations for.");
+
+        private static readonly Action<ILogger, string, Exception> _contextNotRegistered = LoggerMessage.Define<string>(
+            LogLevel.Error,
+            new EventId(3, "ContextNotRegistered"),
+            "The context type '{ContextTypeName}' was not found in services. This usually means the context was not registered in services during startup. You probably want to call AddScoped<>() inside the UseServices(...) call in your application startup code.");
+
+        private static readonly Action<ILogger, string, Exception> _requestPathMatched = LoggerMessage.Define<string>(
+            LogLevel.Debug,
+            new EventId(4, "RequestPathMatched"),
+            "Request path matched the path configured for this migrations endpoint({RequestPath}). Attempting to process the migrations request.");
+
+        private static readonly Action<ILogger, string, Exception> _applyingMigrations = LoggerMessage.Define<string>(
+            LogLevel.Debug,
+            new EventId(5, "ApplyingMigrations"),
+            "Request is valid, applying migrations for context '{ContextTypeName}'");
+
+        private static readonly Action<ILogger, string, Exception> _migrationsApplied = LoggerMessage.Define<string>(
+            LogLevel.Debug,
+            new EventId(6, "MigrationsApplied"),
+            "Migrations successfully applied for context '{ContextTypeName}'.");
+
+        private static readonly Action<ILogger, string, Exception> _migrationsEndPointMiddlewareException = LoggerMessage.Define<string>(
+            LogLevel.Error,
+            new EventId(7, "MigrationsEndPointException"),
+            "An error occurred while applying the migrations for '{ContextTypeName}'. See InnerException for details:");
+
+        // DatabaseErrorPageMiddleware
+        private static readonly Action<ILogger, Type, Exception> _attemptingToMatchException = LoggerMessage.Define<Type>(
+            LogLevel.Debug,
+            new EventId(1, "AttemptingToMatchException"),
+            "{ExceptionType} occurred, checking if Entity Framework recorded this exception as resulting from a failed database operation.");
+
+        private static readonly Action<ILogger, Exception> _noRecordedException = LoggerMessage.Define(
+            LogLevel.Debug,
+            new EventId(2, "NoRecordedException"),
+            "Entity Framework did not record any exceptions due to failed database operations. This means the current exception is not a failed Entity Framework database operation, or the current exception occurred from a DbContext that was not obtained from request services.");
+
+        private static readonly Action<ILogger, Exception> _noMatch = LoggerMessage.Define(
+            LogLevel.Debug,
+            new EventId(3, "NoMatchFound"),
+            "The current exception (and its inner exceptions) do not match the last exception Entity Framework recorded due to a failed database operation. This means the database operation exception was handled and another exception occurred later in the request.");
+
+        private static readonly Action<ILogger, Exception> _matched = LoggerMessage.Define(
+            LogLevel.Debug,
+            new EventId(4, "MatchFound"),
+            "Entity Framework recorded that the current exception was due to a failed database operation. Attempting to show database error page.");
+
+        private static readonly Action<ILogger, string, Exception> _contextNotRegisteredDatabaseErrorPageMiddleware = LoggerMessage.Define<string>(
+            LogLevel.Error,
+            new EventId(5, "ContextNotRegistered"),
+            "The context type '{ContextTypeName}' was not found in services. This usually means the context was not registered in services during startup. You probably want to call AddScoped<>() inside the UseServices(...) call in your application startup code. Skipping display of the database error page.");
+
+        private static readonly Action<ILogger, Exception> _notRelationalDatabase = LoggerMessage.Define(
+            LogLevel.Debug,
+            new EventId(6, "NotRelationalDatabase"),
+            "The target data store is not a relational database. Skipping the database error page.");
+
+        private static readonly Action<ILogger, Exception> _databaseErrorPageMiddlewareException = LoggerMessage.Define(
+            LogLevel.Error,
+            new EventId(7, "DatabaseErrorPageException"),
+            "An exception occurred while calculating the database error page content. Skipping display of the database error page.");
+
+        public static void NoContextType(this ILogger logger)
+        {
+            _noContextType(logger, null);
+        }
+
+        public static void InvalidContextType(this ILogger logger, string contextTypeName)
+        {
+            _invalidContextType(logger, contextTypeName, null);
+        }
+
+        public static void ContextNotRegistered(this ILogger logger, string contextTypeName)
+        {
+            _contextNotRegistered(logger, contextTypeName, null);
+        }
+
+        public static void RequestPathMatched(this ILogger logger, string requestPath)
+        {
+            _requestPathMatched(logger, requestPath, null);
+        }
+
+        public static void ApplyingMigrations(this ILogger logger, string contextTypeName)
+        {
+            _applyingMigrations(logger, contextTypeName, null);
+        }
+
+        public static void MigrationsApplied(this ILogger logger, string contextTypeName)
+        {
+            _migrationsApplied(logger, contextTypeName, null);
+        }
+
+        public static void MigrationsEndPointMiddlewareException(this ILogger logger, string context, Exception exception)
+        {
+            _migrationsEndPointMiddlewareException(logger, context, exception);
+        }
+
+        public static void AttemptingToMatchException(this ILogger logger, Type exceptionType)
+        {
+            _attemptingToMatchException(logger, exceptionType, null);
+        }
+
+        public static void NoRecordedException(this ILogger logger)
+        {
+            _noRecordedException(logger, null);
+        }
+
+        public static void NoMatch(this ILogger logger)
+        {
+            _noMatch(logger, null);
+        }
+
+        public static void Matched(this ILogger logger)
+        {
+            _matched(logger, null);
+        }
+
+        public static void NotRelationalDatabase(this ILogger logger)
+        {
+            _notRelationalDatabase(logger, null);
+        }
+
+        public static void ContextNotRegisteredDatabaseErrorPageMiddleware(this ILogger logger, string contextTypeName)
+        {
+            _contextNotRegisteredDatabaseErrorPageMiddleware(logger, contextTypeName, null);
+        }
+
+        public static void DatabaseErrorPageMiddlewareException(this ILogger logger, Exception exception)
+        {
+            _databaseErrorPageMiddlewareException(logger, exception);
+        }
+    }
+}

+ 21 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.csproj

@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <Description>ASP.NET Core middleware for Entity Framework Core error pages. Use this middleware to detect and diagnose errors with Entity Framework Core migrations.</Description>
+    <TargetFrameworks>netstandard2.0</TargetFrameworks>
+    <NoWarn>$(NoWarn);CS1591</NoWarn>
+    <GenerateDocumentationFile>true</GenerateDocumentationFile>
+    <PackageTags>aspnetcore;diagnostics;entityframeworkcore</PackageTags>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Compile Include="$(SharedSourceRoot)Diagnostics\*.cs" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Reference Include="Microsoft.AspNetCore.Http.Abstractions" />
+    <Reference Include="Microsoft.EntityFrameworkCore.Relational" />
+    <Reference Include="Microsoft.Extensions.RazorViews.Sources" PrivateAssets="All" />
+  </ItemGroup>
+
+</Project>

+ 51 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/MigrationsEndPointExtensions.cs

@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore;
+using Microsoft.Extensions.Options;
+
+// ReSharper disable once CheckNamespace
+namespace Microsoft.AspNetCore.Builder
+{
+    /// <summary>
+    /// <see cref="IApplicationBuilder"/> extension methods for the <see cref="MigrationsEndPointMiddleware"/>.
+    /// </summary>
+    public static class MigrationsEndPointExtensions
+    {
+        /// <summary>
+        /// Processes requests to execute migrations operations. The middleware will listen for requests made to <see cref="MigrationsEndPointOptions.DefaultPath"/>.
+        /// </summary>
+        /// <param name="app">The <see cref="IApplicationBuilder"/> to register the middleware with.</param>
+        /// <returns>The same <see cref="IApplicationBuilder"/> instance so that multiple calls can be chained.</returns>
+        public static IApplicationBuilder UseMigrationsEndPoint(this IApplicationBuilder app)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            return app.UseMigrationsEndPoint(new MigrationsEndPointOptions());
+        }
+
+        /// <summary>
+        /// Processes requests to execute migrations operations. The middleware will listen for requests to the path configured in <paramref name="options"/>.
+        /// </summary>
+        /// <param name="app">The <see cref="IApplicationBuilder"/> to register the middleware with.</param>
+        /// <param name="options">An action to set the options for the middleware.</param>
+        /// <returns>The same <see cref="IApplicationBuilder"/> instance so that multiple calls can be chained.</returns>
+        public static IApplicationBuilder UseMigrationsEndPoint(this IApplicationBuilder app, MigrationsEndPointOptions options)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            return app.UseMiddleware<MigrationsEndPointMiddleware>(Options.Create(options));
+        }
+    }
+}

+ 159 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/MigrationsEndPointMiddleware.cs

@@ -0,0 +1,159 @@
+// Copyright (c) Microsoft Open Technologies, Inc. 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.Net;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Internal;
+using Microsoft.AspNetCore.Http;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
+{
+    /// <summary>
+    /// Processes requests to execute migrations operations. The middleware will listen for requests to the path configured in the supplied options.
+    /// </summary>
+    public class MigrationsEndPointMiddleware
+    {
+        private readonly RequestDelegate _next;
+        private readonly ILogger _logger;
+        private readonly MigrationsEndPointOptions _options;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="MigrationsEndPointMiddleware"/> class
+        /// </summary>
+        /// <param name="next">Delegate to execute the next piece of middleware in the request pipeline.</param>
+        /// <param name="logger">The <see cref="Logger{T}"/> to write messages to.</param>
+        /// <param name="options">The options to control the behavior of the middleware.</param>
+        public MigrationsEndPointMiddleware(
+            RequestDelegate next, 
+            ILogger<MigrationsEndPointMiddleware> logger, 
+            IOptions<MigrationsEndPointOptions> options)
+        {
+            if (next == null)
+            {
+                throw new ArgumentNullException(nameof(next));
+            }
+
+            if (logger == null)
+            {
+                throw new ArgumentNullException(nameof(logger));
+            }
+
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            _next = next;
+            _logger = logger;
+            _options = options.Value;
+        }
+
+        /// <summary>
+        /// Process an individual request.
+        /// </summary>
+        /// <param name="context">The context for the current request.</param>
+        /// <returns>A task that represents the asynchronous operation.</returns>
+        public virtual async Task Invoke(HttpContext context)
+        {
+            if (context == null)
+            {
+                throw new ArgumentNullException(nameof(context));
+            }
+
+            if (context.Request.Path.Equals(_options.Path))
+            {
+                _logger.RequestPathMatched(context.Request.Path);
+
+                var db = await GetDbContext(context, _logger);
+
+                if (db != null)
+                {
+                    try
+                    {
+                        _logger.ApplyingMigrations(db.GetType().FullName);
+
+                        db.Database.Migrate();
+
+                        context.Response.StatusCode = (int)HttpStatusCode.NoContent;
+                        context.Response.Headers.Add("Pragma", new[] { "no-cache" });
+                        context.Response.Headers.Add("Cache-Control", new[] { "no-cache" });
+
+                        _logger.MigrationsApplied(db.GetType().FullName);
+                    }
+                    catch (Exception ex)
+                    {
+                        var message = Strings.FormatMigrationsEndPointMiddleware_Exception(db.GetType().FullName) + ex;
+
+                        _logger.MigrationsEndPointMiddlewareException(db.GetType().FullName, ex);
+
+                        throw new InvalidOperationException(message, ex);
+                    }
+                }
+            }
+            else
+            {
+                await _next(context);
+            }
+        }
+
+        private static async Task<DbContext> GetDbContext(HttpContext context, ILogger logger)
+        {
+            var form = await context.Request.ReadFormAsync();
+            var contextTypeName = form["context"];
+
+            if (string.IsNullOrWhiteSpace(contextTypeName))
+            {
+                logger.NoContextType();
+
+                await WriteErrorToResponse(context.Response, Strings.MigrationsEndPointMiddleware_NoContextType);
+
+                return null;
+            }
+
+            var contextType = Type.GetType(contextTypeName);
+
+            if (contextType == null)
+            {
+                var message = Strings.FormatMigrationsEndPointMiddleware_InvalidContextType(contextTypeName);
+
+                logger.InvalidContextType(contextTypeName);
+
+                await WriteErrorToResponse(context.Response, message);
+
+                return null;
+            }
+
+            var db = (DbContext)context.RequestServices.GetService(contextType);
+
+            if (db == null)
+            {
+                var message = Strings.FormatMigrationsEndPointMiddleware_ContextNotRegistered(contextType.FullName);
+
+                logger.ContextNotRegistered(contextType.FullName);
+
+                await WriteErrorToResponse(context.Response, message);
+
+                return null;
+            }
+
+            return db;
+        }
+
+        private static async Task WriteErrorToResponse(HttpResponse response, string error)
+        {
+            response.StatusCode = (int)HttpStatusCode.BadRequest;
+            response.Headers.Add("Pragma", new[] { "no-cache" });
+            response.Headers.Add("Cache-Control", new[] { "no-cache" });
+            response.ContentType = "text/plain";
+
+            // Padding to >512 to ensure IE doesn't hide the message
+            // http://stackoverflow.com/questions/16741062/what-rules-does-ie-use-to-determine-whether-to-show-the-entity-body
+            await response.WriteAsync(error.PadRight(513));
+        }
+    }
+}

+ 26 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/MigrationsEndPointOptions.cs

@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore;
+using Microsoft.AspNetCore.Http;
+
+// ReSharper disable once CheckNamespace
+namespace Microsoft.AspNetCore.Builder
+{
+    /// <summary>
+    /// Options for the <see cref="MigrationsEndPointMiddleware"/>.
+    /// </summary>
+    public class MigrationsEndPointOptions
+    {
+        /// <summary>
+        /// The default value for <see cref="Path"/>.
+        /// </summary>
+        public static PathString DefaultPath = new PathString("/ApplyDatabaseMigrations");
+
+        /// <summary>
+        /// Gets or sets the path that the <see cref="MigrationsEndPointMiddleware"/> will listen
+        /// for requests to execute migrations commands.
+        /// </summary>
+        public virtual PathString Path { get; set; } = DefaultPath;
+    }
+}

+ 8 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/Properties/AssemblyInfo.cs

@@ -0,0 +1,8 @@
+// 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.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

+ 408 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/Properties/Strings.Designer.cs

@@ -0,0 +1,408 @@
+// <auto-generated />
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
+{
+    using System.Globalization;
+    using System.Reflection;
+    using System.Resources;
+
+    internal static class Strings
+    {
+        private static readonly ResourceManager _resourceManager
+            = new ResourceManager("Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Strings", typeof(Strings).GetTypeInfo().Assembly);
+
+        /// <summary>
+        /// The context type '{0}' was not found in services. This usually means the context was not registered in services during startup. You probably want to call AddScoped&lt;&gt;() inside the UseServices(...) call in your application startup code. Skipping display of the database error page.
+        /// </summary>
+        internal static string DatabaseErrorPageMiddleware_ContextNotRegistered
+        {
+            get => GetString("DatabaseErrorPageMiddleware_ContextNotRegistered");
+        }
+
+        /// <summary>
+        /// The context type '{0}' was not found in services. This usually means the context was not registered in services during startup. You probably want to call AddScoped&lt;&gt;() inside the UseServices(...) call in your application startup code. Skipping display of the database error page.
+        /// </summary>
+        internal static string FormatDatabaseErrorPageMiddleware_ContextNotRegistered(object p0)
+            => string.Format(CultureInfo.CurrentCulture, GetString("DatabaseErrorPageMiddleware_ContextNotRegistered"), p0);
+
+        /// <summary>
+        /// An exception occurred while calculating the database error page content. Skipping display of the database error page.
+        /// </summary>
+        internal static string DatabaseErrorPageMiddleware_Exception
+        {
+            get => GetString("DatabaseErrorPageMiddleware_Exception");
+        }
+
+        /// <summary>
+        /// An exception occurred while calculating the database error page content. Skipping display of the database error page.
+        /// </summary>
+        internal static string FormatDatabaseErrorPageMiddleware_Exception()
+            => GetString("DatabaseErrorPageMiddleware_Exception");
+
+        /// <summary>
+        /// &gt; dotnet ef migrations add [migration name]
+        /// </summary>
+        internal static string DatabaseErrorPage_AddMigrationCommandCLI
+        {
+            get => GetString("DatabaseErrorPage_AddMigrationCommandCLI");
+        }
+
+        /// <summary>
+        /// &gt; dotnet ef migrations add [migration name]
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_AddMigrationCommandCLI()
+            => GetString("DatabaseErrorPage_AddMigrationCommandCLI");
+
+        /// <summary>
+        /// Apply Migrations
+        /// </summary>
+        internal static string DatabaseErrorPage_ApplyMigrationsButton
+        {
+            get => GetString("DatabaseErrorPage_ApplyMigrationsButton");
+        }
+
+        /// <summary>
+        /// Apply Migrations
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_ApplyMigrationsButton()
+            => GetString("DatabaseErrorPage_ApplyMigrationsButton");
+
+        /// <summary>
+        /// Migrations Applied
+        /// </summary>
+        internal static string DatabaseErrorPage_ApplyMigrationsButtonDone
+        {
+            get => GetString("DatabaseErrorPage_ApplyMigrationsButtonDone");
+        }
+
+        /// <summary>
+        /// Migrations Applied
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_ApplyMigrationsButtonDone()
+            => GetString("DatabaseErrorPage_ApplyMigrationsButtonDone");
+
+        /// <summary>
+        /// Applying Migrations...
+        /// </summary>
+        internal static string DatabaseErrorPage_ApplyMigrationsButtonRunning
+        {
+            get => GetString("DatabaseErrorPage_ApplyMigrationsButtonRunning");
+        }
+
+        /// <summary>
+        /// Applying Migrations...
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_ApplyMigrationsButtonRunning()
+            => GetString("DatabaseErrorPage_ApplyMigrationsButtonRunning");
+
+        /// <summary>
+        /// An error occurred applying migrations, try applying them from the command line
+        /// </summary>
+        internal static string DatabaseErrorPage_ApplyMigrationsFailed
+        {
+            get => GetString("DatabaseErrorPage_ApplyMigrationsFailed");
+        }
+
+        /// <summary>
+        /// An error occurred applying migrations, try applying them from the command line
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_ApplyMigrationsFailed()
+            => GetString("DatabaseErrorPage_ApplyMigrationsFailed");
+
+        /// <summary>
+        /// In Visual Studio, you can use the Package Manager Console to apply pending migrations to the database:
+        /// </summary>
+        internal static string DatabaseErrorPage_HowToApplyFromPMC
+        {
+            get => GetString("DatabaseErrorPage_HowToApplyFromPMC");
+        }
+
+        /// <summary>
+        /// In Visual Studio, you can use the Package Manager Console to apply pending migrations to the database:
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_HowToApplyFromPMC()
+            => GetString("DatabaseErrorPage_HowToApplyFromPMC");
+
+        /// <summary>
+        /// Try refreshing the page
+        /// </summary>
+        internal static string DatabaseErrorPage_MigrationsAppliedRefresh
+        {
+            get => GetString("DatabaseErrorPage_MigrationsAppliedRefresh");
+        }
+
+        /// <summary>
+        /// Try refreshing the page
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_MigrationsAppliedRefresh()
+            => GetString("DatabaseErrorPage_MigrationsAppliedRefresh");
+
+        /// <summary>
+        /// In Visual Studio, use the Package Manager Console to scaffold a new migration and apply it to the database:
+        /// </summary>
+        internal static string DatabaseErrorPage_NoDbOrMigrationsInfoPMC
+        {
+            get => GetString("DatabaseErrorPage_NoDbOrMigrationsInfoPMC");
+        }
+
+        /// <summary>
+        /// In Visual Studio, use the Package Manager Console to scaffold a new migration and apply it to the database:
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_NoDbOrMigrationsInfoPMC()
+            => GetString("DatabaseErrorPage_NoDbOrMigrationsInfoPMC");
+
+        /// <summary>
+        /// Use migrations to create the database for {0}
+        /// </summary>
+        internal static string DatabaseErrorPage_NoDbOrMigrationsTitle
+        {
+            get => GetString("DatabaseErrorPage_NoDbOrMigrationsTitle");
+        }
+
+        /// <summary>
+        /// Use migrations to create the database for {0}
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_NoDbOrMigrationsTitle(object p0)
+            => string.Format(CultureInfo.CurrentCulture, GetString("DatabaseErrorPage_NoDbOrMigrationsTitle"), p0);
+
+        /// <summary>
+        /// In Visual Studio, use the Package Manager Console to scaffold a new migration for these changes and apply them to the database:
+        /// </summary>
+        internal static string DatabaseErrorPage_PendingChangesInfoPMC
+        {
+            get => GetString("DatabaseErrorPage_PendingChangesInfoPMC");
+        }
+
+        /// <summary>
+        /// In Visual Studio, use the Package Manager Console to scaffold a new migration for these changes and apply them to the database:
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_PendingChangesInfoPMC()
+            => GetString("DatabaseErrorPage_PendingChangesInfoPMC");
+
+        /// <summary>
+        /// There are pending model changes for {0}
+        /// </summary>
+        internal static string DatabaseErrorPage_PendingChangesTitle
+        {
+            get => GetString("DatabaseErrorPage_PendingChangesTitle");
+        }
+
+        /// <summary>
+        /// There are pending model changes for {0}
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_PendingChangesTitle(object p0)
+            => string.Format(CultureInfo.CurrentCulture, GetString("DatabaseErrorPage_PendingChangesTitle"), p0);
+
+        /// <summary>
+        /// There are migrations for {0} that have not been applied to the database
+        /// </summary>
+        internal static string DatabaseErrorPage_PendingMigrationsInfo
+        {
+            get => GetString("DatabaseErrorPage_PendingMigrationsInfo");
+        }
+
+        /// <summary>
+        /// There are migrations for {0} that have not been applied to the database
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_PendingMigrationsInfo(object p0)
+            => string.Format(CultureInfo.CurrentCulture, GetString("DatabaseErrorPage_PendingMigrationsInfo"), p0);
+
+        /// <summary>
+        /// Applying existing migrations for {0} may resolve this issue
+        /// </summary>
+        internal static string DatabaseErrorPage_PendingMigrationsTitle
+        {
+            get => GetString("DatabaseErrorPage_PendingMigrationsTitle");
+        }
+
+        /// <summary>
+        /// Applying existing migrations for {0} may resolve this issue
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_PendingMigrationsTitle(object p0)
+            => string.Format(CultureInfo.CurrentCulture, GetString("DatabaseErrorPage_PendingMigrationsTitle"), p0);
+
+        /// <summary>
+        /// &gt; dotnet ef database update
+        /// </summary>
+        internal static string DatabaseErrorPage_ApplyMigrationsCommandCLI
+        {
+            get => GetString("DatabaseErrorPage_ApplyMigrationsCommandCLI");
+        }
+
+        /// <summary>
+        /// &gt; dotnet ef database update
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_ApplyMigrationsCommandCLI()
+            => GetString("DatabaseErrorPage_ApplyMigrationsCommandCLI");
+
+        /// <summary>
+        /// The context type '{0}' was not found in services. This usually means the context was not registered in services during startup. You probably want to call AddScoped&lt;{0}&gt;() inside the UseServices(...) call in your application startup code.
+        /// </summary>
+        internal static string MigrationsEndPointMiddleware_ContextNotRegistered
+        {
+            get => GetString("MigrationsEndPointMiddleware_ContextNotRegistered");
+        }
+
+        /// <summary>
+        /// The context type '{0}' was not found in services. This usually means the context was not registered in services during startup. You probably want to call AddScoped&lt;{0}&gt;() inside the UseServices(...) call in your application startup code.
+        /// </summary>
+        internal static string FormatMigrationsEndPointMiddleware_ContextNotRegistered(object p0)
+            => string.Format(CultureInfo.CurrentCulture, GetString("MigrationsEndPointMiddleware_ContextNotRegistered"), p0);
+
+        /// <summary>
+        /// An error occurred while applying the migrations for '{0}'. See InnerException for details.
+        /// </summary>
+        internal static string MigrationsEndPointMiddleware_Exception
+        {
+            get => GetString("MigrationsEndPointMiddleware_Exception");
+        }
+
+        /// <summary>
+        /// An error occurred while applying the migrations for '{0}'. See InnerException for details.
+        /// </summary>
+        internal static string FormatMigrationsEndPointMiddleware_Exception(object p0)
+            => string.Format(CultureInfo.CurrentCulture, GetString("MigrationsEndPointMiddleware_Exception"), p0);
+
+        /// <summary>
+        /// The context type '{0}' could not be loaded. Ensure this is the correct type name for the context you are trying to apply migrations for.
+        /// </summary>
+        internal static string MigrationsEndPointMiddleware_InvalidContextType
+        {
+            get => GetString("MigrationsEndPointMiddleware_InvalidContextType");
+        }
+
+        /// <summary>
+        /// The context type '{0}' could not be loaded. Ensure this is the correct type name for the context you are trying to apply migrations for.
+        /// </summary>
+        internal static string FormatMigrationsEndPointMiddleware_InvalidContextType(object p0)
+            => string.Format(CultureInfo.CurrentCulture, GetString("MigrationsEndPointMiddleware_InvalidContextType"), p0);
+
+        /// <summary>
+        /// No context type was specified. Ensure the form data from the request includes a contextTypeName value, specifying the context to apply migrations for.
+        /// </summary>
+        internal static string MigrationsEndPointMiddleware_NoContextType
+        {
+            get => GetString("MigrationsEndPointMiddleware_NoContextType");
+        }
+
+        /// <summary>
+        /// No context type was specified. Ensure the form data from the request includes a contextTypeName value, specifying the context to apply migrations for.
+        /// </summary>
+        internal static string FormatMigrationsEndPointMiddleware_NoContextType()
+            => GetString("MigrationsEndPointMiddleware_NoContextType");
+
+        /// <summary>
+        /// A database operation failed while processing the request.
+        /// </summary>
+        internal static string DatabaseErrorPage_Title
+        {
+            get => GetString("DatabaseErrorPage_Title");
+        }
+
+        /// <summary>
+        /// A database operation failed while processing the request.
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_Title()
+            => GetString("DatabaseErrorPage_Title");
+
+        /// <summary>
+        /// Entity Framework did not record any exceptions due to failed database operations. This means the current exception is not a failed Entity Framework database operation, or the current exception occurred from a DbContext that was not obtained from request services.
+        /// </summary>
+        internal static string DatabaseErrorPage_NoRecordedException
+        {
+            get => GetString("DatabaseErrorPage_NoRecordedException");
+        }
+
+        /// <summary>
+        /// Entity Framework did not record any exceptions due to failed database operations. This means the current exception is not a failed Entity Framework database operation, or the current exception occurred from a DbContext that was not obtained from request services.
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_NoRecordedException()
+            => GetString("DatabaseErrorPage_NoRecordedException");
+
+        /// <summary>
+        /// PM&gt; Add-Migration [migration name]
+        /// </summary>
+        internal static string DatabaseErrorPage_AddMigrationCommandPMC
+        {
+            get => GetString("DatabaseErrorPage_AddMigrationCommandPMC");
+        }
+
+        /// <summary>
+        /// PM&gt; Add-Migration [migration name]
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_AddMigrationCommandPMC()
+            => GetString("DatabaseErrorPage_AddMigrationCommandPMC");
+
+        /// <summary>
+        /// PM&gt; Update-Database
+        /// </summary>
+        internal static string DatabaseErrorPage_ApplyMigrationsCommandPMC
+        {
+            get => GetString("DatabaseErrorPage_ApplyMigrationsCommandPMC");
+        }
+
+        /// <summary>
+        /// PM&gt; Update-Database
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_ApplyMigrationsCommandPMC()
+            => GetString("DatabaseErrorPage_ApplyMigrationsCommandPMC");
+
+        /// <summary>
+        /// Alternatively, you can scaffold a new migration and apply it from a command prompt at your project directory:
+        /// </summary>
+        internal static string DatabaseErrorPage_NoDbOrMigrationsInfoCLI
+        {
+            get => GetString("DatabaseErrorPage_NoDbOrMigrationsInfoCLI");
+        }
+
+        /// <summary>
+        /// Alternatively, you can scaffold a new migration and apply it from a command prompt at your project directory:
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_NoDbOrMigrationsInfoCLI()
+            => GetString("DatabaseErrorPage_NoDbOrMigrationsInfoCLI");
+
+        /// <summary>
+        /// Alternatively, you can scaffold a new migration and apply it from a command prompt at your project directory:
+        /// </summary>
+        internal static string DatabaseErrorPage_PendingChangesInfoCLI
+        {
+            get => GetString("DatabaseErrorPage_PendingChangesInfoCLI");
+        }
+
+        /// <summary>
+        /// Alternatively, you can scaffold a new migration and apply it from a command prompt at your project directory:
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_PendingChangesInfoCLI()
+            => GetString("DatabaseErrorPage_PendingChangesInfoCLI");
+
+        /// <summary>
+        /// Alternatively, you can apply pending migrations from a command prompt at your project directory:
+        /// </summary>
+        internal static string DatabaseErrorPage_HowToApplyFromCLI
+        {
+            get => GetString("DatabaseErrorPage_HowToApplyFromCLI");
+        }
+
+        /// <summary>
+        /// Alternatively, you can apply pending migrations from a command prompt at your project directory:
+        /// </summary>
+        internal static string FormatDatabaseErrorPage_HowToApplyFromCLI()
+            => GetString("DatabaseErrorPage_HowToApplyFromCLI");
+
+        private static string GetString(string name, params string[] formatterNames)
+        {
+            var value = _resourceManager.GetString(name);
+
+            System.Diagnostics.Debug.Assert(value != null);
+
+            if (formatterNames != null)
+            {
+                for (var i = 0; i < formatterNames.Length; i++)
+                {
+                    value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
+                }
+            }
+
+            return value;
+        }
+    }
+}

+ 201 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/Strings.resx

@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="DatabaseErrorPageMiddleware_ContextNotRegistered" xml:space="preserve">
+    <value>The context type '{0}' was not found in services. This usually means the context was not registered in services during startup. You probably want to call AddScoped&lt;&gt;() inside the UseServices(...) call in your application startup code. Skipping display of the database error page.</value>
+  </data>
+  <data name="DatabaseErrorPageMiddleware_Exception" xml:space="preserve">
+    <value>An exception occurred while calculating the database error page content. Skipping display of the database error page.</value>
+  </data>
+  <data name="DatabaseErrorPage_AddMigrationCommandCLI" xml:space="preserve">
+    <value>&gt; dotnet ef migrations add [migration name]</value>
+  </data>
+  <data name="DatabaseErrorPage_ApplyMigrationsButton" xml:space="preserve">
+    <value>Apply Migrations</value>
+  </data>
+  <data name="DatabaseErrorPage_ApplyMigrationsButtonDone" xml:space="preserve">
+    <value>Migrations Applied</value>
+  </data>
+  <data name="DatabaseErrorPage_ApplyMigrationsButtonRunning" xml:space="preserve">
+    <value>Applying Migrations...</value>
+  </data>
+  <data name="DatabaseErrorPage_ApplyMigrationsFailed" xml:space="preserve">
+    <value>An error occurred applying migrations, try applying them from the command line</value>
+  </data>
+  <data name="DatabaseErrorPage_HowToApplyFromPMC" xml:space="preserve">
+    <value>In Visual Studio, you can use the Package Manager Console to apply pending migrations to the database:</value>
+  </data>
+  <data name="DatabaseErrorPage_MigrationsAppliedRefresh" xml:space="preserve">
+    <value>Try refreshing the page</value>
+  </data>
+  <data name="DatabaseErrorPage_NoDbOrMigrationsInfoPMC" xml:space="preserve">
+    <value>In Visual Studio, use the Package Manager Console to scaffold a new migration and apply it to the database:</value>
+  </data>
+  <data name="DatabaseErrorPage_NoDbOrMigrationsTitle" xml:space="preserve">
+    <value>Use migrations to create the database for {0}</value>
+  </data>
+  <data name="DatabaseErrorPage_PendingChangesInfoPMC" xml:space="preserve">
+    <value>In Visual Studio, use the Package Manager Console to scaffold a new migration for these changes and apply them to the database:</value>
+  </data>
+  <data name="DatabaseErrorPage_PendingChangesTitle" xml:space="preserve">
+    <value>There are pending model changes for {0}</value>
+  </data>
+  <data name="DatabaseErrorPage_PendingMigrationsInfo" xml:space="preserve">
+    <value>There are migrations for {0} that have not been applied to the database</value>
+  </data>
+  <data name="DatabaseErrorPage_PendingMigrationsTitle" xml:space="preserve">
+    <value>Applying existing migrations for {0} may resolve this issue</value>
+  </data>
+  <data name="DatabaseErrorPage_ApplyMigrationsCommandCLI" xml:space="preserve">
+    <value>&gt; dotnet ef database update</value>
+  </data>
+  <data name="MigrationsEndPointMiddleware_ContextNotRegistered" xml:space="preserve">
+    <value>The context type '{0}' was not found in services. This usually means the context was not registered in services during startup. You probably want to call AddScoped&lt;{0}&gt;() inside the UseServices(...) call in your application startup code.</value>
+  </data>
+  <data name="MigrationsEndPointMiddleware_Exception" xml:space="preserve">
+    <value>An error occurred while applying the migrations for '{0}'. See InnerException for details.</value>
+  </data>
+  <data name="MigrationsEndPointMiddleware_InvalidContextType" xml:space="preserve">
+    <value>The context type '{0}' could not be loaded. Ensure this is the correct type name for the context you are trying to apply migrations for.</value>
+  </data>
+  <data name="MigrationsEndPointMiddleware_NoContextType" xml:space="preserve">
+    <value>No context type was specified. Ensure the form data from the request includes a contextTypeName value, specifying the context to apply migrations for.</value>
+  </data>
+  <data name="DatabaseErrorPage_Title" xml:space="preserve">
+    <value>A database operation failed while processing the request.</value>
+  </data>
+  <data name="DatabaseErrorPage_NoRecordedException" xml:space="preserve">
+    <value>Entity Framework did not record any exceptions due to failed database operations. This means the current exception is not a failed Entity Framework database operation, or the current exception occurred from a DbContext that was not obtained from request services.</value>
+  </data>
+  <data name="DatabaseErrorPage_AddMigrationCommandPMC" xml:space="preserve">
+    <value>PM&gt; Add-Migration [migration name]</value>
+  </data>
+  <data name="DatabaseErrorPage_ApplyMigrationsCommandPMC" xml:space="preserve">
+    <value>PM&gt; Update-Database</value>
+  </data>
+  <data name="DatabaseErrorPage_NoDbOrMigrationsInfoCLI" xml:space="preserve">
+    <value>Alternatively, you can scaffold a new migration and apply it from a command prompt at your project directory:</value>
+  </data>
+  <data name="DatabaseErrorPage_PendingChangesInfoCLI" xml:space="preserve">
+    <value>Alternatively, you can scaffold a new migration and apply it from a command prompt at your project directory:</value>
+  </data>
+  <data name="DatabaseErrorPage_HowToApplyFromCLI" xml:space="preserve">
+    <value>Alternatively, you can apply pending migrations from a command prompt at your project directory:</value>
+  </data>
+</root>

+ 424 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/DatabaseErrorPage.Designer.cs

@@ -0,0 +1,424 @@
+// <auto-generated/>
+#pragma warning disable 1591
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views
+{
+    #line hidden
+#line 1 "DatabaseErrorPage.cshtml"
+using System;
+
+#line default
+#line hidden
+    using System.Threading.Tasks;
+#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.Views;
+
+#line default
+#line hidden
+    internal class DatabaseErrorPage : Microsoft.Extensions.RazorViews.BaseView
+    {
+        #pragma warning disable 1998
+        public async override global::System.Threading.Tasks.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"
+         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"
+     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"
+                 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
+#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
+    }
+}
+#pragma warning restore 1591

+ 135 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/DatabaseErrorPage.cshtml

@@ -0,0 +1,135 @@
+@using System
+@using System.Linq
+@using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
+@using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views
+@{
+    Response.StatusCode = 500;
+    Response.ContentType = "text/html; charset=utf-8";
+    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>

+ 35 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/DatabaseErrorPageModel.cs

@@ -0,0 +1,35 @@
+// 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.EntityFrameworkCore.Views
+{
+    internal class DatabaseErrorPageModel
+    {
+        public DatabaseErrorPageModel(
+            Type contextType,
+            Exception exception,
+            bool databaseExists,
+            bool pendingModelChanges,
+            IEnumerable<string> pendingMigrations,
+            DatabaseErrorPageOptions options)
+        {
+            ContextType = contextType;
+            Exception = exception;
+            DatabaseExists = databaseExists;
+            PendingModelChanges = pendingModelChanges;
+            PendingMigrations = pendingMigrations;
+            Options = options;
+        }
+
+        public virtual Type ContextType { get; }
+        public virtual Exception Exception { get; }
+        public virtual bool DatabaseExists { get; }
+        public virtual bool PendingModelChanges { get; }
+        public virtual IEnumerable<string> PendingMigrations { get; }
+        public virtual DatabaseErrorPageOptions Options { get; }
+    }
+}

+ 78 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/Views/ErrorPage.css

@@ -0,0 +1,78 @@
+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: normal;
+    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;
+}

+ 795 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/src/baseline.netcore.json

@@ -0,0 +1,795 @@
+{
+  "AssemblyIdentity": "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
+  "Types": [
+    {
+      "Name": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_Prefix",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Value",
+          "Parameters": [],
+          "ReturnType": "System.Object",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Literal",
+          "Parameters": [],
+          "ReturnType": "System.Boolean",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "FromTuple",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Tuple<System.String, System.Object, System.Boolean>"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue",
+          "Static": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "FromTuple",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Tuple<System.String, System.String, System.Boolean>"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue",
+          "Static": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "op_Implicit",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Tuple<System.String, System.Object, System.Boolean>"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue",
+          "Static": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "prefix",
+              "Type": "System.String"
+            },
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            },
+            {
+              "Name": "literal",
+              "Type": "System.Boolean"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "Abstract": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_Context",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.HttpContext",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Request",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.HttpRequest",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Response",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.HttpResponse",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Output",
+          "Parameters": [],
+          "ReturnType": "System.IO.StreamWriter",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_HtmlEncoder",
+          "Parameters": [],
+          "ReturnType": "System.Text.Encodings.Web.HtmlEncoder",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_HtmlEncoder",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Text.Encodings.Web.HtmlEncoder"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_UrlEncoder",
+          "Parameters": [],
+          "ReturnType": "System.Text.Encodings.Web.UrlEncoder",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_UrlEncoder",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Text.Encodings.Web.UrlEncoder"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_JavaScriptEncoder",
+          "Parameters": [],
+          "ReturnType": "System.Text.Encodings.Web.JavaScriptEncoder",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_JavaScriptEncoder",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Text.Encodings.Web.JavaScriptEncoder"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "ExecuteAsync",
+          "Parameters": [
+            {
+              "Name": "context",
+              "Type": "Microsoft.AspNetCore.Http.HttpContext"
+            }
+          ],
+          "ReturnType": "System.Threading.Tasks.Task",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "ExecuteAsync",
+          "Parameters": [],
+          "ReturnType": "System.Threading.Tasks.Task",
+          "Virtual": true,
+          "Abstract": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteLiteral",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteLiteral",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteAttributeValue",
+          "Parameters": [
+            {
+              "Name": "thingy",
+              "Type": "System.String"
+            },
+            {
+              "Name": "startPostion",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            },
+            {
+              "Name": "endValue",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "dealyo",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "yesno",
+              "Type": "System.Boolean"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "BeginWriteAttribute",
+          "Parameters": [
+            {
+              "Name": "name",
+              "Type": "System.String"
+            },
+            {
+              "Name": "begining",
+              "Type": "System.String"
+            },
+            {
+              "Name": "startPosition",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "ending",
+              "Type": "System.String"
+            },
+            {
+              "Name": "endPosition",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "thingy",
+              "Type": "System.Int32"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "EndWriteAttribute",
+          "Parameters": [],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteAttributeTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            },
+            {
+              "Name": "name",
+              "Type": "System.String"
+            },
+            {
+              "Name": "leader",
+              "Type": "System.String"
+            },
+            {
+              "Name": "trailer",
+              "Type": "System.String"
+            },
+            {
+              "Name": "values",
+              "Type": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue[]",
+              "IsParams": true
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "Write",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "Write",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "Write",
+          "Parameters": [
+            {
+              "Name": "result",
+              "Type": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.HelperResult"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            },
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            },
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteLiteralTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            },
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteLiteralTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            },
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "HtmlEncodeAndReplaceLineBreaks",
+          "Parameters": [
+            {
+              "Name": "input",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.String",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Protected",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.HelperResult",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_WriteAction",
+          "Parameters": [],
+          "ReturnType": "System.Action<System.IO.TextWriter>",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "action",
+              "Type": "System.Action<System.IO.TextWriter>"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [
+        "System.IObserver<System.Diagnostics.DiagnosticListener>",
+        "System.IObserver<System.Collections.Generic.KeyValuePair<System.String, System.Object>>"
+      ],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "Invoke",
+          "Parameters": [
+            {
+              "Name": "httpContext",
+              "Type": "Microsoft.AspNetCore.Http.HttpContext"
+            }
+          ],
+          "ReturnType": "System.Threading.Tasks.Task",
+          "Virtual": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "next",
+              "Type": "Microsoft.AspNetCore.Http.RequestDelegate"
+            },
+            {
+              "Name": "loggerFactory",
+              "Type": "Microsoft.Extensions.Logging.ILoggerFactory"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Builder.DatabaseErrorPageOptions>"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "Invoke",
+          "Parameters": [
+            {
+              "Name": "context",
+              "Type": "Microsoft.AspNetCore.Http.HttpContext"
+            }
+          ],
+          "ReturnType": "System.Threading.Tasks.Task",
+          "Virtual": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "next",
+              "Type": "Microsoft.AspNetCore.Http.RequestDelegate"
+            },
+            {
+              "Name": "logger",
+              "Type": "Microsoft.Extensions.Logging.ILogger<Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware>"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Builder.MigrationsEndPointOptions>"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.DatabaseErrorPageExtensions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "Abstract": true,
+      "Static": true,
+      "Sealed": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "UseDatabaseErrorPage",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseDatabaseErrorPage",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.AspNetCore.Builder.DatabaseErrorPageOptions"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.DatabaseErrorPageOptions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_MigrationsEndPointPath",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.PathString",
+          "Virtual": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_MigrationsEndPointPath",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "Microsoft.AspNetCore.Http.PathString"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Virtual": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.MigrationsEndPointExtensions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "Abstract": true,
+      "Static": true,
+      "Sealed": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "UseMigrationsEndPoint",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseMigrationsEndPoint",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.AspNetCore.Builder.MigrationsEndPointOptions"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.MigrationsEndPointOptions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_Path",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.PathString",
+          "Virtual": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_Path",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "Microsoft.AspNetCore.Http.PathString"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Virtual": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Field",
+          "Name": "DefaultPath",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.PathString",
+          "Static": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    }
+  ]
+}

+ 526 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/DatabaseErrorPageMiddlewareTest.cs

@@ -0,0 +1,526 @@
+// 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.Data.SqlClient;
+using System.Diagnostics;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.FunctionalTests.Helpers;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.TestHost;
+using Microsoft.AspNetCore.Testing.xunit;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Internal;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
+{
+    public class DatabaseErrorPageMiddlewareTest
+    {
+        [Fact]
+        public async Task Successful_requests_pass_thru()
+        {
+            var builder = new WebHostBuilder().Configure(app => app
+                .UseDatabaseErrorPage()
+                .UseMiddleware<SuccessMiddleware>());
+            var server = new TestServer(builder);
+
+            HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
+
+            Assert.Equal("Request Handled", await response.Content.ReadAsStringAsync());
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+        }
+
+        class SuccessMiddleware
+        {
+            public SuccessMiddleware(RequestDelegate next)
+            { }
+
+            public virtual async Task Invoke(HttpContext context)
+            {
+                context.Response.StatusCode = (int)HttpStatusCode.OK;
+                await context.Response.WriteAsync("Request Handled");
+            }
+        }
+
+        [Fact]
+        public async Task Non_database_exceptions_pass_thru()
+        {
+            var builder = new WebHostBuilder().Configure(app => app
+                .UseDatabaseErrorPage()
+                .UseMiddleware<ExceptionMiddleware>());
+            var server = new TestServer(builder);
+
+            var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
+                await server.CreateClient().GetAsync("http://localhost/"));
+
+            Assert.Equal("Exception requested from TestMiddleware", ex.Message);
+        }
+
+        class ExceptionMiddleware
+        {
+            public ExceptionMiddleware(RequestDelegate next)
+            { }
+
+            public virtual Task Invoke(HttpContext context)
+            {
+                throw new InvalidOperationException("Exception requested from TestMiddleware");
+            }
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Existing_database_not_using_migrations_exception_passes_thru()
+        {
+            using (var database = SqlServerTestStore.CreateScratch())
+            {
+                TestServer server = SetupTestServer<BloggingContext, DatabaseErrorButNoMigrationsMiddleware>(database);
+                var ex = await Assert.ThrowsAsync<DbUpdateException>(async () =>
+                    await server.CreateClient().GetAsync("http://localhost/"));
+
+                Assert.Equal("Invalid column name 'Name'.", ex.InnerException.Message);
+            }
+        }
+
+        class DatabaseErrorButNoMigrationsMiddleware
+        {
+            public DatabaseErrorButNoMigrationsMiddleware(RequestDelegate next)
+            { }
+
+            public virtual Task Invoke(HttpContext context)
+            {
+                var db = context.RequestServices.GetService<BloggingContext>();
+                db.Database.EnsureCreated();
+                db.Database.ExecuteSqlCommand("ALTER TABLE dbo.Blogs DROP COLUMN Name");
+
+                db.Blogs.Add(new Blog());
+                db.SaveChanges();
+                throw new Exception("SaveChanges should have thrown");
+            }
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Error_page_displayed_no_migrations()
+        {
+            using (var database = SqlServerTestStore.CreateScratch())
+            {
+                TestServer server = SetupTestServer<BloggingContext, NoMigrationsMiddleware>(database);
+                HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
+
+                Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
+                var content = await response.Content.ReadAsStringAsync();
+                Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", typeof(BloggingContext).Name), content);
+                Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_AddMigrationCommandPMC").Replace(">", "&gt;"), content);
+                Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_ApplyMigrationsCommandPMC").Replace(">", "&gt;"), content);
+            }
+        }
+
+        class NoMigrationsMiddleware
+        {
+            public NoMigrationsMiddleware(RequestDelegate next)
+            { }
+
+            public virtual Task Invoke(HttpContext context)
+            {
+                var db = context.RequestServices.GetService<BloggingContext>();
+                db.Blogs.Add(new Blog());
+                db.SaveChanges();
+                throw new Exception("SaveChanges should have thrown");
+            }
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public void No_exception_on_diagnostic_event_received_when_null_state()
+        {
+            using (var database = SqlServerTestStore.CreateScratch())
+            {
+                using (var server = SetupTestServer<BloggingContext, NoMigrationsMiddleware>(database))
+                {
+                    using (var db = server.Host.Services.GetService<BloggingContext>())
+                    {
+                        db.Blogs.Add(new Blog());
+
+                        try
+                        {
+                            db.SaveChanges();
+                        }
+                        catch (SqlException)
+                        {
+                        }
+                    }
+                }
+            }
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Error_page_displayed_pending_migrations()
+        {
+            using (var database = SqlServerTestStore.CreateScratch())
+            {
+                TestServer server = SetupTestServer<BloggingContextWithMigrations, PendingMigrationsMiddleware>(database);
+                HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
+
+                Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
+
+                var content = await response.Content.ReadAsStringAsync();
+                Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingMigrationsTitle", typeof(BloggingContextWithMigrations).Name), content);
+                Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_ApplyMigrationsCommandPMC").Replace(">", "&gt;"), content);
+                Assert.Contains("<li>111111111111111_MigrationOne</li>", content);
+                Assert.Contains("<li>222222222222222_MigrationTwo</li>", content);
+
+                Assert.DoesNotContain(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_AddMigrationCommandPMC").Replace(">", "&gt;"), content);
+            }
+        }
+
+        class PendingMigrationsMiddleware
+        {
+            public PendingMigrationsMiddleware(RequestDelegate next)
+            { }
+
+            public virtual Task Invoke(HttpContext context)
+            {
+                var db = context.RequestServices.GetService<BloggingContextWithMigrations>();
+                db.Blogs.Add(new Blog());
+                db.SaveChanges();
+                throw new Exception("SaveChanges should have thrown");
+            }
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Error_page_displayed_pending_model_changes()
+        {
+            using (var database = SqlServerTestStore.CreateScratch())
+            {
+                TestServer server = SetupTestServer<BloggingContextWithPendingModelChanges, PendingModelChangesMiddleware>(database);
+                HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
+
+                Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
+
+                var content = await response.Content.ReadAsStringAsync();
+                Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingChangesTitle", typeof(BloggingContextWithPendingModelChanges).Name), content);
+                Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_AddMigrationCommandCLI").Replace(">", "&gt;"), content);
+                Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_AddMigrationCommandPMC").Replace(">", "&gt;"), content);
+                Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_ApplyMigrationsCommandCLI").Replace(">", "&gt;"), content);
+                Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_ApplyMigrationsCommandPMC").Replace(">", "&gt;"), content);
+            }
+        }
+
+        class PendingModelChangesMiddleware
+        {
+            public PendingModelChangesMiddleware(RequestDelegate next)
+            { }
+
+            public virtual Task Invoke(HttpContext context)
+            {
+                var db = context.RequestServices.GetService<BloggingContextWithPendingModelChanges>();
+                db.Database.Migrate();
+
+                db.Blogs.Add(new Blog());
+                db.SaveChanges();
+                throw new Exception("SaveChanges should have thrown");
+            }
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Error_page_then_apply_migrations()
+        {
+            using (var database = SqlServerTestStore.CreateScratch())
+            {
+                TestServer server = SetupTestServer<BloggingContextWithMigrations, ApplyMigrationsMiddleware>(database);
+                var client = server.CreateClient();
+
+                var expectedMigrationsEndpoint = "/ApplyDatabaseMigrations";
+                var expectedContextType = typeof(BloggingContextWithMigrations).AssemblyQualifiedName;
+
+                // Step One: Initial request with database failure
+                HttpResponseMessage response = await client.GetAsync("http://localhost/");
+                Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
+                var content = await response.Content.ReadAsStringAsync();
+
+                // Ensure the url we're going to test is what the page is using in it's JavaScript
+                var javaScriptEncoder = JavaScriptEncoder.Default;
+                Assert.Contains("req.open(\"POST\", \"" + JavaScriptEncode(expectedMigrationsEndpoint) + "\", true);", content);
+                Assert.Contains("var formBody = \"context=" + JavaScriptEncode(UrlEncode(expectedContextType)) + "\";", content);
+
+                // Step Two: Request to migrations endpoint
+                var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
+                {
+                    new KeyValuePair<string, string>("context", expectedContextType)
+                });
+
+                response = await client.PostAsync("http://localhost" + expectedMigrationsEndpoint, formData);
+                content = await response.Content.ReadAsStringAsync();
+                Console.WriteLine(content);
+                Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
+
+                // Step Three: Successful request after migrations applied
+                response = await client.GetAsync("http://localhost/");
+                content = await response.Content.ReadAsStringAsync();
+                Assert.Equal("Saved a Blog", content);
+            }
+        }
+
+        class ApplyMigrationsMiddleware
+        {
+            public ApplyMigrationsMiddleware(RequestDelegate next)
+            { }
+
+            public virtual async Task Invoke(HttpContext context)
+            {
+                var db = context.RequestServices.GetService<BloggingContextWithMigrations>();
+                db.Blogs.Add(new Blog());
+                db.SaveChanges();
+                await context.Response.WriteAsync("Saved a Blog");
+            }
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Customize_migrations_end_point()
+        {
+            var migrationsEndpoint = "/MyCustomEndPoints/ApplyMyMigrationsHere";
+
+            using (var database = SqlServerTestStore.CreateScratch())
+            {
+                var builder = new WebHostBuilder()
+                    .Configure(app =>
+                    {
+                        app.UseDatabaseErrorPage(new DatabaseErrorPageOptions
+                        {
+                            MigrationsEndPointPath = new PathString(migrationsEndpoint)
+                        });
+
+                        app.UseMiddleware<PendingMigrationsMiddleware>();
+                    })
+                    .ConfigureServices(services =>
+                    {
+                        services.AddDbContext<BloggingContextWithMigrations>(optionsBuilder =>
+                        {
+                            optionsBuilder.UseSqlServer(database.ConnectionString);
+                        });
+                    });
+                var server = new TestServer(builder);
+
+                HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
+
+                Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
+
+                var content = await response.Content.ReadAsStringAsync();
+                Assert.Contains("req.open(\"POST\", \"" + JavaScriptEncode(migrationsEndpoint) + "\", true);", content);
+            }
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Pass_thru_when_context_not_in_services()
+        {
+            var logProvider = new TestLoggerProvider();
+
+            var builder = new WebHostBuilder()
+                .Configure(app =>
+                {
+                    app.UseDatabaseErrorPage();
+                    app.UseMiddleware<ContextNotRegisteredInServicesMiddleware>();
+#pragma warning disable CS0618 // Type or member is obsolete
+                    app.ApplicationServices.GetService<ILoggerFactory>().AddProvider(logProvider);
+#pragma warning restore CS0618 // Type or member is obsolete
+                });
+            var server = new TestServer(builder);
+
+            var ex = await Assert.ThrowsAsync<SqlException>(async () =>
+            {
+                try
+                {
+                    await server.CreateClient().GetAsync("http://localhost/");
+                }
+                catch (InvalidOperationException exception) when (exception.InnerException != null)
+                {
+                    throw exception.InnerException;
+                }
+            });
+
+            Assert.Contains(logProvider.Logger.Messages.ToList(), m =>
+                m.StartsWith(StringsHelpers.GetResourceString("FormatDatabaseErrorPageMiddleware_ContextNotRegistered", typeof(BloggingContext))));
+        }
+
+        class ContextNotRegisteredInServicesMiddleware
+        {
+            public ContextNotRegisteredInServicesMiddleware(RequestDelegate next)
+            { }
+
+            public virtual Task Invoke(HttpContext context)
+            {
+                using (var database = SqlServerTestStore.CreateScratch())
+                {
+                    var optionsBuilder = new DbContextOptionsBuilder()
+                        .UseLoggerFactory(context.RequestServices.GetService<ILoggerFactory>());
+                    if (!PlatformHelper.IsMono)
+                    {
+                        optionsBuilder.UseSqlServer(database.ConnectionString, b => b.CommandTimeout(600).EnableRetryOnFailure());
+                    }
+                    else
+                    {
+                        optionsBuilder.UseInMemoryDatabase("Scratch");
+                    }
+
+                    var db = new BloggingContext(optionsBuilder.Options);
+                    db.Blogs.Add(new Blog());
+                    db.SaveChanges();
+                    throw new Exception("SaveChanges should have thrown");
+                }
+            }
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Pass_thru_when_exception_in_logic()
+        {
+            using (var database = SqlServerTestStore.CreateScratch())
+            {
+                var logProvider = new TestLoggerProvider();
+
+                var server = SetupTestServer<BloggingContextWithSnapshotThatThrows, ExceptionInLogicMiddleware>(database, logProvider);
+
+                var ex = await Assert.ThrowsAsync<SqlException>(async () =>
+                {
+                    try
+                    {
+                        await server.CreateClient().GetAsync("http://localhost/");
+                    }
+                    catch (InvalidOperationException exception) when (exception.InnerException != null)
+                    {
+                        throw exception.InnerException;
+                    }
+                });
+
+                Assert.Contains(logProvider.Logger.Messages.ToList(), m =>
+                    m.StartsWith(StringsHelpers.GetResourceString("FormatDatabaseErrorPageMiddleware_Exception")));
+            }
+        }
+
+        class ExceptionInLogicMiddleware
+        {
+            public ExceptionInLogicMiddleware(RequestDelegate next)
+            { }
+
+            public virtual Task Invoke(HttpContext context)
+            {
+                var db = context.RequestServices.GetService<BloggingContextWithSnapshotThatThrows>();
+                db.Blogs.Add(new Blog());
+                db.SaveChanges();
+                throw new Exception("SaveChanges should have thrown");
+            }
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Error_page_displayed_when_exception_wrapped()
+        {
+            using (var database = SqlServerTestStore.CreateScratch())
+            {
+                TestServer server = SetupTestServer<BloggingContext, WrappedExceptionMiddleware>(database);
+                HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
+
+                Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
+                var content = await response.Content.ReadAsStringAsync();
+                Assert.Contains("I wrapped your exception", content);
+                Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", typeof(BloggingContext).Name), content);
+            }
+        }
+
+        class WrappedExceptionMiddleware
+        {
+            public WrappedExceptionMiddleware(RequestDelegate next)
+            { }
+
+            public virtual Task Invoke(HttpContext context)
+            {
+                var db = context.RequestServices.GetService<BloggingContext>();
+                db.Blogs.Add(new Blog());
+                try
+                {
+                    db.SaveChanges();
+                    throw new Exception("SaveChanges should have thrown");
+                }
+                catch (Exception ex)
+                {
+                    throw new Exception("I wrapped your exception", ex);
+                }
+            }
+        }
+
+        private static TestServer SetupTestServer<TContext, TMiddleware>(SqlServerTestStore database, ILoggerProvider logProvider = null)
+            where TContext : DbContext
+        {
+            var builder = new WebHostBuilder()
+                .Configure(app =>
+                {
+                    app.UseDatabaseErrorPage();
+
+                    app.UseMiddleware<TMiddleware>();
+
+                    if (logProvider != null)
+                    {
+#pragma warning disable CS0618 // Type or member is obsolete
+                        app.ApplicationServices.GetService<ILoggerFactory>().AddProvider(logProvider);
+#pragma warning restore CS0618 // Type or member is obsolete
+                    }
+                })
+                .ConfigureServices(services =>
+                {
+                    services.AddDbContext<TContext>(optionsBuilder =>
+                    {
+                        if (!PlatformHelper.IsMono)
+                        {
+                            optionsBuilder.UseSqlServer(
+                                database.ConnectionString, 
+                                b => b.CommandTimeout(600).EnableRetryOnFailure());
+                        }
+                        else
+                        {
+                            optionsBuilder.UseInMemoryDatabase("Scratch");
+                        }
+                    });
+                });
+            return new TestServer(builder);
+        }
+
+        private static UrlEncoder _urlEncoder = UrlEncoder.Default;
+        private static string UrlEncode(string content)
+        {
+            return _urlEncoder.Encode(content);
+        }
+
+        private static JavaScriptEncoder _javaScriptEncoder = JavaScriptEncoder.Default;
+        private static string JavaScriptEncode(string content)
+        {
+            return _javaScriptEncoder.Encode(content);
+        }
+    }
+}

+ 16 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/Diagnostics.EFCore.FunctionalTests.csproj

@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
+    <!-- Mitigation for long path issues -->
+    <AssemblyName>Diagnostics.EFCore.FunctionalTests</AssemblyName>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Reference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" />
+    <Reference Include="Microsoft.AspNetCore.TestHost" />
+    <Reference Include="Microsoft.EntityFrameworkCore.InMemory" />
+    <Reference Include="Microsoft.EntityFrameworkCore.SqlServer" />
+  </ItemGroup>
+
+</Project>

+ 18 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/Helpers/PlatformHelper.cs

@@ -0,0 +1,18 @@
+// 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 Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.FunctionalTests.Helpers
+{
+    public class PlatformHelper
+    {
+        public static bool IsMono
+        {
+            get
+            {
+                return Type.GetType("Mono.Runtime") != null;
+            }
+        }
+    }
+}

+ 19 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/Helpers/StringHelpers.cs

@@ -0,0 +1,19 @@
+// 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.Linq;
+using System.Reflection;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.FunctionalTests.Helpers
+{
+    public class StringsHelpers
+    {
+        public static string GetResourceString(string stringName, params object[] parameters)
+        {
+            var strings = typeof(DatabaseErrorPageMiddleware).GetTypeInfo().Assembly.GetType("Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Strings").GetTypeInfo();
+            var method = strings.GetDeclaredMethods(stringName).Single();
+            return (string)method.Invoke(null, parameters);
+        }
+    }
+}

+ 61 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/Helpers/TestLoggerProvider.cs

@@ -0,0 +1,61 @@
+// 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 Microsoft.Extensions.Logging;
+using System.Collections.Generic;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.FunctionalTests.Helpers
+{
+    public class TestLoggerProvider : ILoggerProvider
+    {
+        private readonly TestLogger _logger = new TestLogger();
+
+        public TestLogger Logger
+        {
+            get { return _logger; }
+        }
+
+        public ILogger CreateLogger(string name)
+        {
+            return _logger;
+        }
+
+        public void Dispose()
+        {
+        }
+
+        public class TestLogger : ILogger
+        {
+            private List<string> _messages = new List<string>();
+
+            public IEnumerable<string> Messages
+            {
+                get { return _messages; }
+            }
+
+            public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
+            {
+                _messages.Add(formatter(state, exception));
+            }
+
+            public bool IsEnabled(LogLevel logLevel)
+            {
+                return true;
+            }
+
+            public IDisposable BeginScope<TState>(TState state)
+            {
+                return NullScope.Instance;
+            }
+
+            public class NullScope : IDisposable
+            {
+                public static NullScope Instance = new NullScope();
+
+                public void Dispose()
+                { }
+            }
+        }
+    }
+}

+ 224 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/MigrationsEndPointMiddlewareTest.cs

@@ -0,0 +1,224 @@
+// Copyright (c) Microsoft Open Technologies, Inc. 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;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.FunctionalTests.Helpers;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.TestHost;
+using Microsoft.AspNetCore.Testing.xunit;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage;
+using Microsoft.Extensions.DependencyInjection;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
+{
+    public class MigrationsEndPointMiddlewareTest
+    {
+        [Fact]
+        public async Task Non_migration_requests_pass_thru()
+        {
+            var builder = new WebHostBuilder().Configure(app => app
+                .UseMigrationsEndPoint()
+                .UseMiddleware<SuccessMiddleware>());
+            var server = new TestServer(builder);
+
+            HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
+
+            Assert.Equal("Request Handled", await response.Content.ReadAsStringAsync());
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+        }
+
+        class SuccessMiddleware
+        {
+            public SuccessMiddleware(RequestDelegate next)
+            { }
+
+            public virtual async Task Invoke(HttpContext context)
+            {
+                context.Response.StatusCode = (int)HttpStatusCode.OK;
+                await context.Response.WriteAsync("Request Handled");
+            }
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Migration_request_default_path()
+        {
+            await Migration_request(useCustomPath: false);
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Migration_request_custom_path()
+        {
+            await Migration_request(useCustomPath: true);
+        }
+
+        private async Task Migration_request(bool useCustomPath)
+        {
+            using (var database = SqlServerTestStore.CreateScratch())
+            {
+                var optionsBuilder = new DbContextOptionsBuilder();
+                optionsBuilder.UseSqlServer(database.ConnectionString);
+
+                var path = useCustomPath ? new PathString("/EndPoints/ApplyMyMigrations") : MigrationsEndPointOptions.DefaultPath;
+
+                var builder = new WebHostBuilder()
+                    .Configure(app =>
+                    {
+                        if (useCustomPath)
+                        {
+                            app.UseMigrationsEndPoint(new MigrationsEndPointOptions
+                            {
+                                Path = path
+                            });
+                        }
+                        else
+                        {
+                            app.UseMigrationsEndPoint();
+                        }
+                    })
+                    .ConfigureServices(services =>
+                    {
+                        services.AddDbContext<BloggingContextWithMigrations>(options =>
+                        {
+                            options.UseSqlServer(database.ConnectionString);
+                        });
+                    });
+                var server = new TestServer(builder);
+
+                using (var db = BloggingContextWithMigrations.CreateWithoutExternalServiceProvider(optionsBuilder.Options))
+                {
+                    var databaseCreator = db.GetService<IRelationalDatabaseCreator>();
+                    Assert.False(databaseCreator.Exists());
+
+                    var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
+                    {
+                        new KeyValuePair<string, string>("context", typeof(BloggingContextWithMigrations).AssemblyQualifiedName)
+                    });
+
+                    HttpResponseMessage response = await server.CreateClient()
+                        .PostAsync("http://localhost" + path, formData);
+
+                    Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
+
+                    Assert.True(databaseCreator.Exists());
+
+                    var historyRepository = db.GetService<IHistoryRepository>();
+                    var appliedMigrations = historyRepository.GetAppliedMigrations();
+                    Assert.Equal(2, appliedMigrations.Count);
+                    Assert.Equal("111111111111111_MigrationOne", appliedMigrations.ElementAt(0).MigrationId);
+                    Assert.Equal("222222222222222_MigrationTwo", appliedMigrations.ElementAt(1).MigrationId);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task Context_type_not_specified()
+        {
+            var builder = new WebHostBuilder()
+                .Configure(app =>
+                {
+                    app.UseMigrationsEndPoint();
+                });
+            var server = new TestServer(builder);
+
+            var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>());
+
+            var response = await server.CreateClient().PostAsync("http://localhost" + MigrationsEndPointOptions.DefaultPath, formData);
+            var content = await response.Content.ReadAsStringAsync();
+
+            Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
+            Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_NoContextType"), content);
+            Assert.True(content.Length > 512);
+        }
+
+        [Fact]
+        public async Task Invalid_context_type_specified()
+        {
+            var builder = new WebHostBuilder()
+                .Configure(app =>
+                {
+                    app.UseMigrationsEndPoint();
+                });
+            var server = new TestServer(builder);
+
+            var typeName = "You won't find this type ;)";
+            var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
+                {
+                    new KeyValuePair<string, string>("context", typeName)
+                });
+
+            var response = await server.CreateClient().PostAsync("http://localhost" + MigrationsEndPointOptions.DefaultPath, formData);
+            var content = await response.Content.ReadAsStringAsync();
+
+            Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
+            Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_InvalidContextType", typeName), content);
+            Assert.True(content.Length > 512);
+        }
+
+        [Fact]
+        public async Task Context_not_registered_in_services()
+        {
+            var builder = new WebHostBuilder()
+                .Configure(app => app.UseMigrationsEndPoint())
+                .ConfigureServices(services => services.AddEntityFrameworkSqlServer());
+            var server = new TestServer(builder);
+
+            var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
+                {
+                    new KeyValuePair<string, string>("context", typeof(BloggingContext).AssemblyQualifiedName)
+                });
+
+            var response = await server.CreateClient().PostAsync("http://localhost" + MigrationsEndPointOptions.DefaultPath, formData);
+            var content = await response.Content.ReadAsStringAsync();
+
+            Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
+            Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_ContextNotRegistered", typeof(BloggingContext)), content);
+            Assert.True(content.Length > 512);
+        }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task Exception_while_applying_migrations()
+        {
+            using (var database = SqlServerTestStore.CreateScratch())
+            {
+                var builder = new WebHostBuilder()
+                    .Configure(app => app.UseMigrationsEndPoint())
+                    .ConfigureServices(services =>
+                    {
+                        services.AddDbContext<BloggingContextWithSnapshotThatThrows>(optionsBuilder =>
+                        {
+                            optionsBuilder.UseSqlServer(database.ConnectionString);
+                        });
+                    });
+                var server = new TestServer(builder);
+
+                var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
+                    {
+                        new KeyValuePair<string, string>("context", typeof(BloggingContextWithSnapshotThatThrows).AssemblyQualifiedName)
+                    });
+
+                var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
+                    await server.CreateClient().PostAsync("http://localhost" + MigrationsEndPointOptions.DefaultPath, formData));
+
+                Assert.StartsWith(StringsHelpers.GetResourceString("FormatMigrationsEndPointMiddleware_Exception", typeof(BloggingContextWithSnapshotThatThrows)), ex.Message);
+                Assert.Equal("Welcome to the invalid migration!", ex.InnerException.Message);
+            }
+        }
+    }
+}

+ 60 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/SqlServerTestStore.cs

@@ -0,0 +1,60 @@
+// 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.Data.SqlClient;
+using System.Threading;
+using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.FunctionalTests.Helpers;
+using Microsoft.EntityFrameworkCore;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
+{
+    public class SqlServerTestStore : IDisposable
+    {
+        private static int _scratchCount;
+
+        public static SqlServerTestStore CreateScratch()
+        {
+            var name = "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.FunctionalTests.Scratch_" + Interlocked.Increment(ref _scratchCount);
+            var db = new SqlServerTestStore(name);
+            return db;
+        }
+
+        private readonly string _connectionString;
+
+        private SqlServerTestStore(string name)
+        {
+            _connectionString = new SqlConnectionStringBuilder
+            {
+                DataSource = @"(localdb)\MSSQLLocalDB",
+                InitialCatalog = name,
+                IntegratedSecurity = true,
+                ConnectTimeout = 600
+            }.ConnectionString;
+        }
+
+        public string ConnectionString
+        {
+            get { return _connectionString; }
+        }
+
+        private void EnsureDeleted()
+        {
+            if (!PlatformHelper.IsMono)
+            {
+                var optionsBuilder = new DbContextOptionsBuilder();
+                optionsBuilder.UseSqlServer(_connectionString, b => b.CommandTimeout(600).EnableRetryOnFailure());
+
+                using (var db = new DbContext(optionsBuilder.Options))
+                {
+                    db.Database.EnsureDeleted();
+                }
+            }
+        }
+
+        public virtual void Dispose()
+        {
+            EnsureDeleted();
+        }
+    }
+}

+ 13 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/TestModels/Blog.cs

@@ -0,0 +1,13 @@
+// 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 Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
+{
+	public class Blog
+    {
+        public int BlogId { get; set; }
+        public string Name { get; set; }
+    }
+}

+ 18 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/TestModels/BloggingContext.cs

@@ -0,0 +1,18 @@
+// 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 Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
+{
+    public class BloggingContext : DbContext
+    {
+        public BloggingContext(DbContextOptions options)
+            : base(options)
+        { }
+
+        public DbSet<Blog> Blogs { get; set; }
+    }
+}

+ 71 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/TestModels/BloggingContextWithMigrations.cs

@@ -0,0 +1,71 @@
+// 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 Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
+{
+    public class BloggingContextWithMigrations : BloggingContext
+    {
+        public BloggingContextWithMigrations(DbContextOptions options)
+            : base(options)
+        { }
+
+        // Providing a factory method so that the ctor is hidden from DI
+        public static BloggingContextWithMigrations CreateWithoutExternalServiceProvider(DbContextOptions options)
+        {
+            return new BloggingContextWithMigrations(options);
+        }
+
+        [DbContext(typeof(BloggingContextWithMigrations))]
+        public class BloggingContextWithMigrationsModelSnapshot : ModelSnapshot
+        {
+            protected override void BuildModel(ModelBuilder builder)
+            {
+                builder.Entity("Blogging.Models.Blog", b =>
+                {
+                    b.Property<int>("BlogId");
+                    b.Property<string>("Name");
+                    b.HasKey("BlogId");
+                });
+            }
+        }
+
+        [DbContext(typeof(BloggingContextWithMigrations))]
+        [Migration("111111111111111_MigrationOne")]
+        public class MigrationOne : Migration
+        {
+            public override IModel TargetModel => new BloggingContextWithMigrationsModelSnapshot().Model;
+
+            protected override void Up(MigrationBuilder migrationBuilder)
+            {
+                migrationBuilder.CreateTable("Blogs",
+                c => new
+                {
+                    BlogId = c.Column<int>().Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
+                    Name = c.Column<string>(nullable: true),
+                })
+                .PrimaryKey("PK_Blog", t => t.BlogId);
+            }
+
+            protected override void Down(MigrationBuilder migrationBuilder)
+            {
+                migrationBuilder.DropTable("Blogs");
+            }
+        }
+
+        [DbContext(typeof(BloggingContextWithMigrations))]
+        [Migration("222222222222222_MigrationTwo")]
+        public class MigrationTwo : Migration
+        {
+            public override IModel TargetModel => new BloggingContextWithMigrationsModelSnapshot().Model;
+
+            protected override void Up(MigrationBuilder migrationBuilder)
+            { }
+        }
+    }
+}

+ 33 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/TestModels/BloggingContextWithPendingModelChanges.cs

@@ -0,0 +1,33 @@
+// 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 Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
+{
+    public class BloggingContextWithPendingModelChanges : BloggingContext
+    {
+        public BloggingContextWithPendingModelChanges(DbContextOptions options)
+            : base(options)
+        { }
+
+        [DbContext(typeof(BloggingContextWithPendingModelChanges))]
+        public class BloggingModelSnapshot : ModelSnapshot
+        {
+            protected override void BuildModel(ModelBuilder modelBuilder)
+            {
+            }
+        }
+
+        [DbContext(typeof(BloggingContextWithPendingModelChanges))]
+        [Migration("111111111111111_MigrationOne")]
+        public partial class MigrationOne : Migration
+        {
+            protected override void Up(MigrationBuilder migrationBuilder)
+            { }
+        }
+    }
+}

+ 39 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/FunctionalTests/TestModels/BloggingContextWithSnapshotThatThrows.cs

@@ -0,0 +1,39 @@
+// 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 Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
+{
+    public class BloggingContextWithSnapshotThatThrows : BloggingContext
+    {
+        public BloggingContextWithSnapshotThatThrows(DbContextOptions options)
+            : base(options)
+        { }
+
+        [DbContext(typeof(BloggingContextWithSnapshotThatThrows))]
+        public class BloggingContextWithSnapshotThatThrowsModelSnapshot : ModelSnapshot
+        {
+            protected override void BuildModel(ModelBuilder modelBuilder)
+            {
+                throw new Exception("Welcome to the invalid snapshot!");
+            }
+        }
+
+        [DbContext(typeof(BloggingContextWithSnapshotThatThrows))]
+        [Migration("111111111111111_MigrationOne")]
+        public class MigrationOne : Migration
+        {
+            public override IModel TargetModel => new BloggingContextWithSnapshotThatThrowsModelSnapshot().Model;
+
+            protected override void Up(MigrationBuilder migrationBuilder)
+            {
+                throw new Exception("Welcome to the invalid migration!");
+            }
+        }
+    }
+}

+ 28 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/DatabaseErrorPageOptionsTest.cs

@@ -0,0 +1,28 @@
+// 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 Microsoft.AspNetCore.Builder;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
+{
+    public class DatabaseErrorPageOptionsTest
+    {
+        [Fact]
+        public void Empty_MigrationsEndPointPath_by_default()
+        {
+            var options = new DatabaseErrorPageOptions();
+
+            Assert.Equal(MigrationsEndPointOptions.DefaultPath, options.MigrationsEndPointPath);
+        }
+
+        [Fact]
+        public void MigrationsEndPointPath_is_respected()
+        {
+            var options = new DatabaseErrorPageOptions();
+            options.MigrationsEndPointPath = "/test";
+            
+            Assert.Equal("/test", options.MigrationsEndPointPath);
+        }
+    }
+}

+ 199 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/DatabaseErrorPageTest.cs

@@ -0,0 +1,199 @@
+// 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 Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests.Helpers;
+using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Views;
+using Microsoft.AspNetCore.Http;
+using Microsoft.EntityFrameworkCore;
+using Moq;
+using System;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
+{
+    public class DatabaseErrorPageTest
+    {
+        [Fact]
+        public async Task No_database_or_migrations_only_displays_scaffold_first_migration()
+        {
+            var options = new DatabaseErrorPageOptions();
+
+            var model = new DatabaseErrorPageModel(
+                contextType: typeof(BloggingContext),
+                exception: new Exception(),
+                databaseExists: false,
+                pendingModelChanges: false,
+                pendingMigrations: new string[] { },
+                options: options);
+
+            var content = await ExecutePage(options, model);
+
+            AssertHelpers.DisplaysScaffoldFirstMigration(typeof(BloggingContext), content);
+            AssertHelpers.NotDisplaysApplyMigrations(typeof(BloggingContext), content);
+            AssertHelpers.NotDisplaysScaffoldNextMigraion(typeof(BloggingContext), content);
+        }
+
+        [Fact]
+        public async Task No_database_with_migrations_only_displays_apply_migrations()
+        {
+            var options = new DatabaseErrorPageOptions();
+
+            var model = new DatabaseErrorPageModel(
+                contextType: typeof(BloggingContext),
+                exception: new Exception(),
+                databaseExists: false,
+                pendingModelChanges: false,
+                pendingMigrations: new[] { "111_MigrationOne" },
+                options: options);
+
+            var content = await ExecutePage(options, model);
+
+            AssertHelpers.NotDisplaysScaffoldFirstMigration(typeof(BloggingContext), content);
+            AssertHelpers.DisplaysApplyMigrations(typeof(BloggingContext), content);
+            AssertHelpers.NotDisplaysScaffoldNextMigraion(typeof(BloggingContext), content);
+        }
+
+        [Fact]
+        public async Task Existing_database_with_migrations_only_displays_apply_migrations()
+        {
+            var options = new DatabaseErrorPageOptions();
+
+            var model = new DatabaseErrorPageModel(
+                contextType: typeof(BloggingContext),
+                exception: new Exception(),
+                databaseExists: true,
+                pendingModelChanges: false,
+                pendingMigrations: new[] { "111_MigrationOne" },
+                options: options);
+
+            var content = await ExecutePage(options, model);
+
+            AssertHelpers.NotDisplaysScaffoldFirstMigration(typeof(BloggingContext), content);
+            AssertHelpers.DisplaysApplyMigrations(typeof(BloggingContext), content);
+            AssertHelpers.NotDisplaysScaffoldNextMigraion(typeof(BloggingContext), content);
+        }
+
+        [Fact]
+        public async Task Existing_database_with_migrations_and_pending_model_changes_only_displays_apply_migrations()
+        {
+            var options = new DatabaseErrorPageOptions();
+
+            var model = new DatabaseErrorPageModel(
+                contextType: typeof(BloggingContext),
+                exception: new Exception(),
+                databaseExists: true,
+                pendingModelChanges: true,
+                pendingMigrations: new[] { "111_MigrationOne" },
+                options: options);
+
+            var content = await ExecutePage(options, model);
+
+            AssertHelpers.NotDisplaysScaffoldFirstMigration(typeof(BloggingContext), content);
+            AssertHelpers.DisplaysApplyMigrations(typeof(BloggingContext), content);
+            AssertHelpers.NotDisplaysScaffoldNextMigraion(typeof(BloggingContext), content);
+        }
+
+        [Fact]
+        public async Task Pending_model_changes_only_displays_scaffold_next_migration()
+        {
+            var options = new DatabaseErrorPageOptions();
+
+            var model = new DatabaseErrorPageModel(
+                contextType: typeof(BloggingContext),
+                exception: new Exception(),
+                databaseExists: true,
+                pendingModelChanges: true,
+                pendingMigrations: new string[] { },
+                options: options);
+
+            var content = await ExecutePage(options, model);
+
+            AssertHelpers.NotDisplaysScaffoldFirstMigration(typeof(BloggingContext), content);
+            AssertHelpers.NotDisplaysApplyMigrations(typeof(BloggingContext), content);
+            AssertHelpers.DisplaysScaffoldNextMigraion(typeof(BloggingContext), content);
+        }
+
+        [Fact]
+        public async Task Exception_details_are_displayed()
+        {
+            var options = new DatabaseErrorPageOptions();
+
+            var model = new DatabaseErrorPageModel(
+                contextType: typeof(BloggingContext),
+                exception: new Exception("Something bad happened"),
+                databaseExists: false,
+                pendingModelChanges: false,
+                pendingMigrations: new string[] { },
+                options: options);
+
+            var content = await ExecutePage(options, model);
+
+            Assert.Contains("Something bad happened", content);
+        }
+
+        [Fact]
+        public async Task Inner_exception_details_are_displayed()
+        {
+            var options = new DatabaseErrorPageOptions();
+
+            var model = new DatabaseErrorPageModel(
+                contextType: typeof(BloggingContext),
+                exception: new Exception("Something bad happened", new Exception("Because something more badder happened")),
+                databaseExists: false,
+                pendingModelChanges: false,
+                pendingMigrations: new string[] { },
+                options: options);
+
+            var content = await ExecutePage(options, model);
+
+            Assert.Contains("Something bad happened", content);
+            Assert.Contains("Because something more badder happened", content);
+        }
+
+        [Fact]
+        public async Task MigrationsEndPointPath_is_respected()
+        {
+            var options = new DatabaseErrorPageOptions();
+            options.MigrationsEndPointPath = "/HitThisEndPoint";
+
+            var model = new DatabaseErrorPageModel(
+               contextType: typeof(BloggingContext),
+               exception: new Exception(),
+               databaseExists: true,
+               pendingModelChanges: false,
+               pendingMigrations: new[] { "111_MigrationOne" },
+               options: options);
+
+            var content = await ExecutePage(options, model);
+
+            Assert.Contains(options.MigrationsEndPointPath.Value, content);
+        }
+
+
+        private static async Task<string> ExecutePage(DatabaseErrorPageOptions options, DatabaseErrorPageModel model)
+        {
+            var page = new DatabaseErrorPage();
+            var context = new Mock<HttpContext>();
+            var response = new Mock<HttpResponse>();
+            var stream = new MemoryStream();
+
+            response.Setup(r => r.Body).Returns(stream);
+            context.Setup(c => c.Response).Returns(response.Object);
+
+            page.Model = model;
+
+            await page.ExecuteAsync(context.Object);
+            var content = Encoding.ASCII.GetString(stream.ToArray());
+            return content;
+        }
+
+        private class BloggingContext : DbContext
+        {
+
+        }
+    }
+}

+ 41 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/Helpers/AssertHelpers.cs

@@ -0,0 +1,41 @@
+// 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 Xunit;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests.Helpers
+{
+    public static class AssertHelpers
+    {
+        public static void DisplaysScaffoldFirstMigration(Type contextType, string content)
+        {
+            Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", contextType.Name), content);
+        }
+
+        public static void NotDisplaysScaffoldFirstMigration(Type contextType, string content)
+        {
+            Assert.DoesNotContain(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_NoDbOrMigrationsTitle", contextType.Name), content);
+        }
+
+        public static void DisplaysApplyMigrations(Type contextType, string content)
+        {
+            Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingMigrationsTitle", contextType.Name), content);
+        }
+
+        public static void NotDisplaysApplyMigrations(Type contextType, string content)
+        {
+            Assert.DoesNotContain(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingMigrationsTitle", contextType.Name), content);
+        }
+
+        public static void DisplaysScaffoldNextMigraion(Type contextType, string content)
+        {
+            Assert.Contains(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingChangesTitle", contextType.Name), content);
+        }
+
+        public static void NotDisplaysScaffoldNextMigraion(Type contextType, string content)
+        {
+            Assert.DoesNotContain(StringsHelpers.GetResourceString("FormatDatabaseErrorPage_PendingChangesTitle", contextType.Name), content);
+        }
+    }
+}

+ 19 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/Helpers/StringHelpers.cs

@@ -0,0 +1,19 @@
+// 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.Linq;
+using System.Reflection;
+
+namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests.Helpers
+{
+    public class StringsHelpers
+    {
+        public static string GetResourceString(string stringName, params object[] parameters)
+        {
+            var strings = typeof(DatabaseErrorPageMiddleware).GetTypeInfo().Assembly.GetType("Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Strings").GetTypeInfo();
+            var method = strings.GetDeclaredMethods(stringName).Single();
+            return (string)method.Invoke(null, parameters);
+        }
+    }
+}

+ 13 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests.csproj

@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Reference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" />
+    <Reference Include="Microsoft.EntityFrameworkCore.InMemory" />
+  </ItemGroup>
+
+
+</Project>

+ 21 - 0
src/Middleware/Diagnostics.EntityFrameworkCore/test/UnitTests/TestHelperExtensions.cs

@@ -0,0 +1,21 @@
+// 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 Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Microsoft.EntityFrameworkCore.Tests
+{
+    public static class TestHelperExtensions
+    {
+        public static IServiceCollection AddProviderServices(this IServiceCollection serviceCollection)
+        {
+            return serviceCollection.AddEntityFrameworkInMemoryDatabase();
+        }
+
+        public static DbContextOptions UseProviderOptions(this DbContextOptions options)
+        {
+            return options;
+        }
+    }
+}

+ 7 - 0
src/Middleware/Diagnostics/src/.csslintrc

@@ -0,0 +1,7 @@
+{
+  "unique-headings": false,
+  "ids": false,
+  "box-sizing": false,
+  "qualified-headings": false,
+  "display-property-grouping": false
+}

+ 3 - 0
src/Middleware/Diagnostics/src/.jshintrc

@@ -0,0 +1,3 @@
+{
+  
+}

+ 53 - 0
src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageExtensions.cs

@@ -0,0 +1,53 @@
+// 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 Microsoft.AspNetCore.Diagnostics;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.AspNetCore.Builder
+{
+    /// <summary>
+    /// <see cref="IApplicationBuilder"/> extension methods for the <see cref="DeveloperExceptionPageMiddleware"/>.
+    /// </summary>
+    public static class DeveloperExceptionPageExtensions
+    {
+        /// <summary>
+        /// Captures synchronous and asynchronous <see cref="Exception"/> instances from the pipeline and generates HTML error responses.
+        /// </summary>
+        /// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
+        /// <returns>A reference to the <paramref name="app"/> after the operation has completed.</returns>
+        public static IApplicationBuilder UseDeveloperExceptionPage(this IApplicationBuilder app)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            return app.UseMiddleware<DeveloperExceptionPageMiddleware>();
+        }
+
+        /// <summary>
+        /// Captures synchronous and asynchronous <see cref="Exception"/> instances from the pipeline and generates HTML error responses.
+        /// </summary>
+        /// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
+        /// <param name="options">A <see cref="DeveloperExceptionPageOptions"/> that specifies options for the middleware.</param>
+        /// <returns>A reference to the <paramref name="app"/> after the operation has completed.</returns>
+        public static IApplicationBuilder UseDeveloperExceptionPage(
+            this IApplicationBuilder app,
+            DeveloperExceptionPageOptions options)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+            
+            return app.UseMiddleware<DeveloperExceptionPageMiddleware>(Options.Create(options));
+        }
+    }
+}

+ 210 - 0
src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs

@@ -0,0 +1,210 @@
+// 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.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.Internal;
+using Microsoft.AspNetCore.Diagnostics.RazorViews;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.FileProviders;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.StackTrace.Sources;
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    /// <summary>
+    /// Captures synchronous and asynchronous exceptions from the pipeline and generates HTML error responses.
+    /// </summary>
+    public class DeveloperExceptionPageMiddleware
+    {
+        private readonly RequestDelegate _next;
+        private readonly DeveloperExceptionPageOptions _options;
+        private readonly ILogger _logger;
+        private readonly IFileProvider _fileProvider;
+        private readonly DiagnosticSource _diagnosticSource;
+        private readonly ExceptionDetailsProvider _exceptionDetailsProvider;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DeveloperExceptionPageMiddleware"/> class
+        /// </summary>
+        /// <param name="next"></param>
+        /// <param name="options"></param>
+        /// <param name="loggerFactory"></param>
+        /// <param name="hostingEnvironment"></param>
+        /// <param name="diagnosticSource"></param>
+        public DeveloperExceptionPageMiddleware(
+            RequestDelegate next,
+            IOptions<DeveloperExceptionPageOptions> options,
+            ILoggerFactory loggerFactory,
+            IHostingEnvironment hostingEnvironment,
+            DiagnosticSource diagnosticSource)
+        {
+            if (next == null)
+            {
+                throw new ArgumentNullException(nameof(next));
+            }
+
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            _next = next;
+            _options = options.Value;
+            _logger = loggerFactory.CreateLogger<DeveloperExceptionPageMiddleware>();
+            _fileProvider = _options.FileProvider ?? hostingEnvironment.ContentRootFileProvider;
+            _diagnosticSource = diagnosticSource;
+            _exceptionDetailsProvider = new ExceptionDetailsProvider(_fileProvider, _options.SourceCodeLineCount);
+        }
+
+        /// <summary>
+        /// Process an individual request.
+        /// </summary>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        public async Task Invoke(HttpContext context)
+        {
+            try
+            {
+                await _next(context);
+            }
+            catch (Exception ex)
+            {
+                _logger.UnhandledException(ex);
+
+                if (context.Response.HasStarted)
+                {
+                    _logger.ResponseStartedErrorPageMiddleware();
+                    throw;
+                }
+
+                try
+                {
+                    context.Response.Clear();
+                    context.Response.StatusCode = 500;
+
+                    await DisplayException(context, ex);
+
+                    if (_diagnosticSource.IsEnabled("Microsoft.AspNetCore.Diagnostics.UnhandledException"))
+                    {
+                        _diagnosticSource.Write("Microsoft.AspNetCore.Diagnostics.UnhandledException", new { httpContext = context, exception = ex });
+                    }
+
+                    return;
+                }
+                catch (Exception ex2)
+                {
+                    // If there's a Exception while generating the error page, re-throw the original exception.
+                    _logger.DisplayErrorPageException(ex2);
+                }
+                throw;
+            }
+        }
+
+        // Assumes the response headers have not been sent.  If they have, still attempt to write to the body.
+        private Task DisplayException(HttpContext context, Exception ex)
+        {
+            var compilationException = ex as ICompilationException;
+            if (compilationException != null)
+            {
+                return DisplayCompilationException(context, compilationException);
+            }
+
+            return DisplayRuntimeException(context, ex);
+        }
+
+        private Task DisplayCompilationException(
+            HttpContext context,
+            ICompilationException compilationException)
+        {
+            var model = new CompilationErrorPageModel
+            {
+                Options = _options,
+            };
+
+            var errorPage = new CompilationErrorPage
+            {
+                Model = model
+            };
+
+            if (compilationException.CompilationFailures == null)
+            {
+                return errorPage.ExecuteAsync(context);
+            }
+
+            foreach (var compilationFailure in compilationException.CompilationFailures)
+            {
+                if (compilationFailure == null)
+                {
+                    continue;
+                }
+
+                var stackFrames = new List<StackFrameSourceCodeInfo>();
+                var exceptionDetails = new ExceptionDetails
+                {
+                    StackFrames = stackFrames,
+                    ErrorMessage = compilationFailure.FailureSummary,
+                };
+                model.ErrorDetails.Add(exceptionDetails);
+                model.CompiledContent.Add(compilationFailure.CompiledContent);
+
+                if (compilationFailure.Messages == null)
+                {
+                    continue;
+                }
+
+                var sourceLines = compilationFailure
+                        .SourceFileContent?
+                        .Split(new[] { Environment.NewLine }, StringSplitOptions.None);
+
+                foreach (var item in compilationFailure.Messages)
+                {
+                    if (item == null)
+                    {
+                        continue;
+                    }
+
+                    var frame = new StackFrameSourceCodeInfo
+                    {
+                        File = compilationFailure.SourceFilePath,
+                        Line = item.StartLine,
+                        Function = string.Empty
+                    };
+
+                    if (sourceLines != null)
+                    {
+                        _exceptionDetailsProvider.ReadFrameContent(frame, sourceLines, item.StartLine, item.EndLine);
+                    }
+
+                    frame.ErrorDetails = item.Message;
+
+                    stackFrames.Add(frame);
+                }
+            }
+
+            return errorPage.ExecuteAsync(context);
+        }
+
+        private Task DisplayRuntimeException(HttpContext context, Exception ex)
+        {
+            var request = context.Request;
+
+            var model = new ErrorPageModel
+            {
+                Options = _options,
+                ErrorDetails = _exceptionDetailsProvider.GetDetails(ex),
+                Query = request.Query,
+                Cookies = request.Cookies,
+                Headers = request.Headers
+            };
+
+            var errorPage = new ErrorPage(model);
+            return errorPage.ExecuteAsync(context);
+        }
+    }
+}

+ 37 - 0
src/Middleware/Diagnostics/src/DeveloperExceptionPage/DeveloperExceptionPageOptions.cs

@@ -0,0 +1,37 @@
+// 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 Microsoft.AspNetCore.Diagnostics;
+using Microsoft.Extensions.FileProviders;
+
+namespace Microsoft.AspNetCore.Builder
+{
+    /// <summary>
+    /// Options for the <see cref="DeveloperExceptionPageMiddleware"/>.
+    /// </summary>
+    public class DeveloperExceptionPageOptions
+    {
+        /// <summary>
+        /// Create an instance with the default options settings.
+        /// </summary>
+        public DeveloperExceptionPageOptions()
+        {
+            SourceCodeLineCount = 6;
+        }
+
+        /// <summary>
+        /// Determines how many lines of code to include before and after the line of code
+        /// present in an exception's stack frame. Only applies when symbols are available and
+        /// source code referenced by the exception stack trace is present on the server.
+        /// </summary>
+        public int SourceCodeLineCount { get; set; }
+
+        /// <summary>
+        /// Provides files containing source code used to display contextual information of an exception.
+        /// </summary>
+        /// <remarks>
+        /// If <c>null</c> <see cref="DeveloperExceptionPageMiddleware" /> will use a <see cref="PhysicalFileProvider"/>.
+        /// </remarks>
+        public IFileProvider FileProvider { get; set; }
+    }
+}

+ 30 - 0
src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/CompilationErrorModel.cs

@@ -0,0 +1,30 @@
+// 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.Collections.Generic;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.StackTrace.Sources;
+
+namespace Microsoft.AspNetCore.Diagnostics.RazorViews
+{
+    /// <summary>
+    /// Holds data to be displayed on the compilation error page.
+    /// </summary>
+    internal 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<ExceptionDetails> ErrorDetails { get; } = new List<ExceptionDetails>();
+
+        /// <summary>
+        /// Gets the generated content that produced the corresponding <see cref="ErrorDetails"/>.
+        /// </summary>
+        public IList<string> CompiledContent { get; } = new List<string>();
+    }
+}

+ 751 - 0
src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/CompilationErrorPage.Designer.cs

@@ -0,0 +1,751 @@
+// <auto-generated/>
+#pragma warning disable 1591
+namespace Microsoft.AspNetCore.Diagnostics.RazorViews
+{
+    #line hidden
+#line 1 "CompilationErrorPage.cshtml"
+using System;
+
+#line default
+#line hidden
+    using System.Threading.Tasks;
+#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
+    internal class CompilationErrorPage : Microsoft.Extensions.RazorViews.BaseView
+    {
+        #pragma warning disable 1998
+        public async override global::System.Threading.Tasks.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;
+    background-color: #fff;
+}
+
+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;
+    }
+
+    #h");
+            WriteLiteral(@"eader .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;
+    bo");
+            WriteLiteral(@"rder-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;
+");
+            WriteLiteral(@"}
+
+.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;
+}
+
+        </style>
+    </head>
+    <body>
+        <h1>");
+#line 222 "CompilationErrorPage.cshtml"
+       Write(Resources.ErrorPageHtml_CompilationException);
+
+#line default
+#line hidden
+            WriteLiteral("</h1>\r\n");
+#line 223 "CompilationErrorPage.cshtml"
+          
+            var exceptionDetailId = "";
+        
+
+#line default
+#line hidden
+            WriteLiteral("        ");
+#line 226 "CompilationErrorPage.cshtml"
+         for (var i = 0; i < Model.ErrorDetails.Count; i++)
+        {
+            var errorDetail = Model.ErrorDetails[i];
+            exceptionDetailId = "exceptionDetail" + i;
+
+
+#line default
+#line hidden
+            WriteLiteral("            <div id=\"stackpage\" class=\"page\">\r\n");
+#line 232 "CompilationErrorPage.cshtml"
+                  
+                    var stackFrameCount = 0;
+                    var frameId = "";
+                    var fileName = errorDetail.StackFrames.FirstOrDefault()?.File;
+                    if (!string.IsNullOrEmpty(fileName))
+                    {
+
+#line default
+#line hidden
+            WriteLiteral("                        <div class=\"titleerror\">");
+#line 238 "CompilationErrorPage.cshtml"
+                                           Write(fileName);
+
+#line default
+#line hidden
+            WriteLiteral("</div>\r\n");
+#line 239 "CompilationErrorPage.cshtml"
+                    }
+                
+
+#line default
+#line hidden
+            WriteLiteral("                ");
+#line 241 "CompilationErrorPage.cshtml"
+                 if (!string.IsNullOrEmpty(errorDetail.ErrorMessage))
+                {
+
+#line default
+#line hidden
+            WriteLiteral("                    <div class=\"details\">");
+#line 243 "CompilationErrorPage.cshtml"
+                                    Write(errorDetail.ErrorMessage);
+
+#line default
+#line hidden
+            WriteLiteral("</div>\r\n");
+#line 244 "CompilationErrorPage.cshtml"
+                }
+
+#line default
+#line hidden
+            WriteLiteral("                <br />\r\n                <ul>\r\n");
+#line 247 "CompilationErrorPage.cshtml"
+                 foreach (var frame in errorDetail.StackFrames)
+                {
+                    stackFrameCount++;
+                    frameId = "frame" + stackFrameCount;
+
+
+#line default
+#line hidden
+            WriteLiteral("                    <li class=\"frame\"");
+            BeginWriteAttribute("id", " id=\"", 5268, "\"", 5281, 1);
+#line 252 "CompilationErrorPage.cshtml"
+WriteAttributeValue("", 5273, frameId, 5273, 8, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(">\r\n");
+#line 253 "CompilationErrorPage.cshtml"
+                         if (!string.IsNullOrEmpty(frame.ErrorDetails))
+                        {
+
+#line default
+#line hidden
+            WriteLiteral("                            <h3>");
+#line 255 "CompilationErrorPage.cshtml"
+                           Write(frame.ErrorDetails);
+
+#line default
+#line hidden
+            WriteLiteral("</h3>\r\n");
+#line 256 "CompilationErrorPage.cshtml"
+                        }
+
+#line default
+#line hidden
+            WriteLiteral("\r\n");
+#line 258 "CompilationErrorPage.cshtml"
+                         if (frame.Line != 0 && frame.ContextCode.Any())
+                        {
+
+#line default
+#line hidden
+            WriteLiteral("                            <button class=\"expandCollapseButton\" data-frameId=\"");
+#line 260 "CompilationErrorPage.cshtml"
+                                                                          Write(frameId);
+
+#line default
+#line hidden
+            WriteLiteral("\">+</button>\r\n                            <div class=\"source\">\r\n");
+#line 262 "CompilationErrorPage.cshtml"
+                                 if (frame.PreContextCode.Any())
+                                {
+
+#line default
+#line hidden
+            WriteLiteral("                                    <ol");
+            BeginWriteAttribute("start", " start=\"", 5864, "\"", 5893, 1);
+#line 264 "CompilationErrorPage.cshtml"
+WriteAttributeValue("", 5872, frame.PreContextLine, 5872, 21, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(" class=\"collapsible\">\r\n");
+#line 265 "CompilationErrorPage.cshtml"
+                                         foreach (var line in frame.PreContextCode)
+                                        {
+
+#line default
+#line hidden
+            WriteLiteral("                                            <li><span>");
+#line 267 "CompilationErrorPage.cshtml"
+                                                 Write(line);
+
+#line default
+#line hidden
+            WriteLiteral("</span></li>\r\n");
+#line 268 "CompilationErrorPage.cshtml"
+                                        }
+
+#line default
+#line hidden
+            WriteLiteral("                                    </ol>\r\n");
+#line 270 "CompilationErrorPage.cshtml"
+                                }
+
+#line default
+#line hidden
+            WriteLiteral("                                <ol");
+            BeginWriteAttribute("start", " start=\"", 6274, "\"", 6293, 1);
+#line 271 "CompilationErrorPage.cshtml"
+WriteAttributeValue("", 6282, frame.Line, 6282, 11, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(" class=\"highlight\">\r\n");
+#line 272 "CompilationErrorPage.cshtml"
+                                     foreach (var line in frame.ContextCode)
+                                    {
+
+#line default
+#line hidden
+            WriteLiteral("                                        <li><span>");
+#line 274 "CompilationErrorPage.cshtml"
+                                             Write(line);
+
+#line default
+#line hidden
+            WriteLiteral("</span></li>\r\n");
+#line 275 "CompilationErrorPage.cshtml"
+                                    }
+
+#line default
+#line hidden
+            WriteLiteral("                                </ol>\r\n");
+#line 277 "CompilationErrorPage.cshtml"
+                                 if (frame.PostContextCode.Any())
+                                {
+
+#line default
+#line hidden
+            WriteLiteral("                                    <ol");
+            BeginWriteAttribute("start", " start=\'", 6720, "\'", 6745, 1);
+#line 279 "CompilationErrorPage.cshtml"
+WriteAttributeValue("", 6728, frame.Line + 1, 6728, 17, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(" class=\"collapsible\">\r\n");
+#line 280 "CompilationErrorPage.cshtml"
+                                         foreach (var line in frame.PostContextCode)
+                                        {
+
+#line default
+#line hidden
+            WriteLiteral("                                            <li><span>");
+#line 282 "CompilationErrorPage.cshtml"
+                                                 Write(line);
+
+#line default
+#line hidden
+            WriteLiteral("</span></li>\r\n");
+#line 283 "CompilationErrorPage.cshtml"
+                                        }
+
+#line default
+#line hidden
+            WriteLiteral("                                    </ol>\r\n");
+#line 285 "CompilationErrorPage.cshtml"
+                                }
+
+#line default
+#line hidden
+            WriteLiteral("                            </div>\r\n");
+#line 287 "CompilationErrorPage.cshtml"
+                        }
+
+#line default
+#line hidden
+            WriteLiteral("                    </li>\r\n");
+#line 289 "CompilationErrorPage.cshtml"
+                }
+
+#line default
+#line hidden
+            WriteLiteral("                </ul>\r\n                <br />\r\n            </div>\r\n");
+#line 293 "CompilationErrorPage.cshtml"
+             if (!string.IsNullOrEmpty(Model.CompiledContent[i]))
+            {
+
+#line default
+#line hidden
+            WriteLiteral("                <div class=\"rawExceptionBlock\">\r\n                    <div class=\"showRawExceptionContainer\">\r\n                        <button class=\"showRawException\" data-exceptionDetailId=\"");
+#line 297 "CompilationErrorPage.cshtml"
+                                                                            Write(exceptionDetailId);
+
+#line default
+#line hidden
+            WriteLiteral("\">Show compilation source</button>\r\n                    </div>\r\n                    <div");
+            BeginWriteAttribute("id", " id=\"", 7647, "\"", 7670, 1);
+#line 299 "CompilationErrorPage.cshtml"
+WriteAttributeValue("", 7652, exceptionDetailId, 7652, 18, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(" class=\"rawExceptionDetails\">\r\n                        <pre class=\"rawExceptionStackTrace\">");
+#line 300 "CompilationErrorPage.cshtml"
+                                                       Write(Model.CompiledContent[i]);
+
+#line default
+#line hidden
+            WriteLiteral("</pre>\r\n                    </div>\r\n                </div>\r\n");
+#line 303 "CompilationErrorPage.cshtml"
+            }
+
+#line default
+#line hidden
+#line 303 "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, e");
+            WriteLiteral(@"l).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(classNa");
+            WriteLiteral(@"me) < 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.o");
+            WriteLiteral(@"n(""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
+#line 8 "CompilationErrorPage.cshtml"
+ 
+    public CompilationErrorPageModel Model { get; set; }
+
+#line default
+#line hidden
+    }
+}
+#pragma warning restore 1591

+ 116 - 0
src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/CompilationErrorPage.cshtml

@@ -0,0 +1,116 @@
+@using System
+@using System.Globalization
+@using System.Linq
+@using System.Net
+@using Microsoft.AspNetCore.Diagnostics
+@using Microsoft.AspNetCore.Diagnostics.RazorViews
+@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>
+        @{
+            var exceptionDetailId = "";
+        }
+        @for (var i = 0; i < Model.ErrorDetails.Count; i++)
+        {
+            var errorDetail = Model.ErrorDetails[i];
+            exceptionDetailId = "exceptionDetail" + i;
+
+            <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>
+            @if (!string.IsNullOrEmpty(Model.CompiledContent[i]))
+            {
+                <div class="rawExceptionBlock">
+                    <div class="showRawExceptionContainer">
+                        <button class="showRawException" data-exceptionDetailId="@exceptionDetailId">Show compilation source</button>
+                    </div>
+                    <div id="@exceptionDetailId" class="rawExceptionDetails">
+                        <pre class="rawExceptionStackTrace">@Model.CompiledContent[i]</pre>
+                    </div>
+                </div>
+            }
+        }
+
+        <script>
+            //<!--
+            <%$ include: ErrorPage.js %>
+            //-->
+        </script>
+    </body>
+</html>

+ 1109 - 0
src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/ErrorPage.Designer.cs

@@ -0,0 +1,1109 @@
+// <auto-generated/>
+#pragma warning disable 1591
+namespace Microsoft.AspNetCore.Diagnostics.RazorViews
+{
+    #line hidden
+#line 1 "ErrorPage.cshtml"
+using System;
+
+#line default
+#line hidden
+    using System.Threading.Tasks;
+#line 2 "ErrorPage.cshtml"
+using System.Globalization;
+
+#line default
+#line hidden
+#line 3 "ErrorPage.cshtml"
+using System.Linq;
+
+#line default
+#line hidden
+#line 4 "ErrorPage.cshtml"
+using System.Net;
+
+#line default
+#line hidden
+#line 5 "ErrorPage.cshtml"
+using System.Reflection;
+
+#line default
+#line hidden
+#line 6 "ErrorPage.cshtml"
+using Microsoft.AspNetCore.Diagnostics.RazorViews;
+
+#line default
+#line hidden
+#line 7 "ErrorPage.cshtml"
+using Microsoft.AspNetCore.Diagnostics;
+
+#line default
+#line hidden
+    internal class ErrorPage : Microsoft.Extensions.RazorViews.BaseView
+    {
+        #pragma warning disable 1998
+        public async override global::System.Threading.Tasks.Task ExecuteAsync()
+        {
+#line 17 "ErrorPage.cshtml"
+  
+    // TODO: Response.ReasonPhrase = "Internal Server Error";
+    Response.ContentType = "text/html; charset=utf-8";
+    string location = string.Empty;
+
+#line default
+#line hidden
+            WriteLiteral("<!DOCTYPE html>\r\n<html");
+            BeginWriteAttribute("lang", " lang=\"", 536, "\"", 597, 1);
+#line 23 "ErrorPage.cshtml"
+WriteAttributeValue("", 543, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, 543, 54, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(" xmlns=\"http://www.w3.org/1999/xhtml\">\r\n    <head>\r\n        <meta charset=\"utf-8\" />\r\n        <title>");
+#line 26 "ErrorPage.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;
+    background-color: #fff;
+}
+
+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;
+    }
+
+    #h");
+            WriteLiteral(@"eader .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;
+    bo");
+            WriteLiteral(@"rder-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;
+");
+            WriteLiteral(@"}
+
+.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;
+}
+
+        </style>
+    </head>
+    <body>
+        <h1>");
+#line 228 "ErrorPage.cshtml"
+       Write(Resources.ErrorPageHtml_UnhandledException);
+
+#line default
+#line hidden
+            WriteLiteral("</h1>\r\n");
+#line 229 "ErrorPage.cshtml"
+         foreach (var errorDetail in Model.ErrorDetails)
+        {
+
+#line default
+#line hidden
+            WriteLiteral("            <div class=\"titleerror\">");
+#line 231 "ErrorPage.cshtml"
+                               Write(errorDetail.Error.GetType().Name);
+
+#line default
+#line hidden
+            WriteLiteral(": ");
+#line 231 "ErrorPage.cshtml"
+                                                                          Output.Write(HtmlEncodeAndReplaceLineBreaks(errorDetail.Error.Message)); 
+
+#line default
+#line hidden
+            WriteLiteral("</div>\r\n");
+#line 232 "ErrorPage.cshtml"
+            
+            var firstFrame = errorDetail.StackFrames.FirstOrDefault();
+            if (firstFrame != null)
+            {
+                location = firstFrame.Function;
+            }
+            if (!string.IsNullOrEmpty(location) && firstFrame != null && !string.IsNullOrEmpty(firstFrame.File))
+            {
+
+#line default
+#line hidden
+            WriteLiteral("                <p class=\"location\">");
+#line 240 "ErrorPage.cshtml"
+                               Write(location);
+
+#line default
+#line hidden
+            WriteLiteral(" in <code");
+            BeginWriteAttribute("title", " title=\"", 4950, "\"", 4974, 1);
+#line 240 "ErrorPage.cshtml"
+WriteAttributeValue("", 4958, firstFrame.File, 4958, 16, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(">");
+#line 240 "ErrorPage.cshtml"
+                                                                           Write(System.IO.Path.GetFileName(firstFrame.File));
+
+#line default
+#line hidden
+            WriteLiteral("</code>, line ");
+#line 240 "ErrorPage.cshtml"
+                                                                                                                                     Write(firstFrame.Line);
+
+#line default
+#line hidden
+            WriteLiteral("</p>\r\n");
+#line 241 "ErrorPage.cshtml"
+            }
+            else if (!string.IsNullOrEmpty(location))
+            {
+
+#line default
+#line hidden
+            WriteLiteral("                <p class=\"location\">");
+#line 244 "ErrorPage.cshtml"
+                               Write(location);
+
+#line default
+#line hidden
+            WriteLiteral("</p>\r\n");
+#line 245 "ErrorPage.cshtml"
+            }
+            else
+            {
+
+#line default
+#line hidden
+            WriteLiteral("                <p class=\"location\">");
+#line 248 "ErrorPage.cshtml"
+                               Write(Resources.ErrorPageHtml_UnknownLocation);
+
+#line default
+#line hidden
+            WriteLiteral("</p>\r\n");
+#line 249 "ErrorPage.cshtml"
+            }
+
+            var reflectionTypeLoadException = errorDetail.Error as ReflectionTypeLoadException;
+            if (reflectionTypeLoadException != null)
+            {
+                if (reflectionTypeLoadException.LoaderExceptions.Length > 0)
+                {
+
+#line default
+#line hidden
+            WriteLiteral("                    <h3>Loader Exceptions:</h3>\r\n                    <ul>\r\n");
+#line 258 "ErrorPage.cshtml"
+                         foreach (var ex in reflectionTypeLoadException.LoaderExceptions)
+                        {
+
+#line default
+#line hidden
+            WriteLiteral("                            <li>");
+#line 260 "ErrorPage.cshtml"
+                           Write(ex.Message);
+
+#line default
+#line hidden
+            WriteLiteral("</li>\r\n");
+#line 261 "ErrorPage.cshtml"
+                        }
+
+#line default
+#line hidden
+            WriteLiteral("                    </ul>\r\n");
+#line 263 "ErrorPage.cshtml"
+                }
+            }
+        }
+
+#line default
+#line hidden
+            WriteLiteral("        <ul id=\"header\">\r\n            <li id=\"stack\" tabindex=\"1\" class=\"selected\">\r\n                ");
+#line 268 "ErrorPage.cshtml"
+           Write(Resources.ErrorPageHtml_StackButton);
+
+#line default
+#line hidden
+            WriteLiteral("\r\n            </li>\r\n            <li id=\"query\" tabindex=\"2\">\r\n                ");
+#line 271 "ErrorPage.cshtml"
+           Write(Resources.ErrorPageHtml_QueryButton);
+
+#line default
+#line hidden
+            WriteLiteral("\r\n            </li>\r\n            <li id=\"cookies\" tabindex=\"3\">\r\n                ");
+#line 274 "ErrorPage.cshtml"
+           Write(Resources.ErrorPageHtml_CookiesButton);
+
+#line default
+#line hidden
+            WriteLiteral("\r\n            </li>\r\n            <li id=\"headers\" tabindex=\"4\">\r\n                ");
+#line 277 "ErrorPage.cshtml"
+           Write(Resources.ErrorPageHtml_HeadersButton);
+
+#line default
+#line hidden
+            WriteLiteral("\r\n            </li>\r\n        </ul>\r\n\r\n        <div id=\"stackpage\" class=\"page\">\r\n            <ul>\r\n");
+#line 283 "ErrorPage.cshtml"
+                  
+                    var exceptionCount = 0;
+                    var stackFrameCount = 0;
+                    var exceptionDetailId = "";
+                    var frameId = "";
+                
+
+#line default
+#line hidden
+            WriteLiteral("                ");
+#line 289 "ErrorPage.cshtml"
+                 foreach (var errorDetail in Model.ErrorDetails)
+                {
+                    exceptionCount++;
+                    exceptionDetailId = "exceptionDetail" + exceptionCount;
+
+
+#line default
+#line hidden
+            WriteLiteral("                    <li>\r\n                        <h2 class=\"stackerror\">");
+#line 295 "ErrorPage.cshtml"
+                                          Write(errorDetail.Error.GetType().Name);
+
+#line default
+#line hidden
+            WriteLiteral(": ");
+#line 295 "ErrorPage.cshtml"
+                                                                             Write(errorDetail.Error.Message);
+
+#line default
+#line hidden
+            WriteLiteral("</h2>\r\n                        <ul>\r\n");
+#line 297 "ErrorPage.cshtml"
+                         foreach (var frame in errorDetail.StackFrames)
+                        {
+                            stackFrameCount++;
+                            frameId = "frame" + stackFrameCount;
+
+
+#line default
+#line hidden
+            WriteLiteral("                            <li class=\"frame\"");
+            BeginWriteAttribute("id", " id=\"", 7386, "\"", 7399, 1);
+#line 302 "ErrorPage.cshtml"
+WriteAttributeValue("", 7391, frameId, 7391, 8, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(">\r\n");
+#line 303 "ErrorPage.cshtml"
+                                 if (string.IsNullOrEmpty(frame.File))
+                                {
+
+#line default
+#line hidden
+            WriteLiteral("                                    <h3>");
+#line 305 "ErrorPage.cshtml"
+                                   Write(frame.Function);
+
+#line default
+#line hidden
+            WriteLiteral("</h3>\r\n");
+#line 306 "ErrorPage.cshtml"
+                                }
+                                else
+                                {
+
+#line default
+#line hidden
+            WriteLiteral("                                    <h3>");
+#line 309 "ErrorPage.cshtml"
+                                   Write(frame.Function);
+
+#line default
+#line hidden
+            WriteLiteral(" in <code");
+            BeginWriteAttribute("title", " title=\"", 7744, "\"", 7763, 1);
+#line 309 "ErrorPage.cshtml"
+WriteAttributeValue("", 7752, frame.File, 7752, 11, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(">");
+#line 309 "ErrorPage.cshtml"
+                                                                                Write(System.IO.Path.GetFileName(frame.File));
+
+#line default
+#line hidden
+            WriteLiteral("</code></h3>\r\n");
+#line 310 "ErrorPage.cshtml"
+                                }
+
+#line default
+#line hidden
+            WriteLiteral("\r\n");
+#line 312 "ErrorPage.cshtml"
+                                 if (frame.Line != 0 && frame.ContextCode.Any())
+                                {
+
+#line default
+#line hidden
+            WriteLiteral("                                    <button class=\"expandCollapseButton\" data-frameId=\"");
+#line 314 "ErrorPage.cshtml"
+                                                                                  Write(frameId);
+
+#line default
+#line hidden
+            WriteLiteral("\">+</button>\r\n                                    <div class=\"source\">\r\n");
+#line 316 "ErrorPage.cshtml"
+                                         if (frame.PreContextCode.Any())
+                                        {
+
+#line default
+#line hidden
+            WriteLiteral("                                            <ol");
+            BeginWriteAttribute("start", " start=\"", 8303, "\"", 8332, 1);
+#line 318 "ErrorPage.cshtml"
+WriteAttributeValue("", 8311, frame.PreContextLine, 8311, 21, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(" class=\"collapsible\">\r\n");
+#line 319 "ErrorPage.cshtml"
+                                                 foreach (var line in frame.PreContextCode)
+                                                {
+
+#line default
+#line hidden
+            WriteLiteral("                                                    <li><span>");
+#line 321 "ErrorPage.cshtml"
+                                                         Write(line);
+
+#line default
+#line hidden
+            WriteLiteral("</span></li>\r\n");
+#line 322 "ErrorPage.cshtml"
+                                                }
+
+#line default
+#line hidden
+            WriteLiteral("                                            </ol>\r\n");
+#line 324 "ErrorPage.cshtml"
+                                        }
+
+#line default
+#line hidden
+            WriteLiteral("\r\n                                        <ol");
+            BeginWriteAttribute("start", " start=\"", 8771, "\"", 8790, 1);
+#line 326 "ErrorPage.cshtml"
+WriteAttributeValue("", 8779, frame.Line, 8779, 11, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(" class=\"highlight\">\r\n");
+#line 327 "ErrorPage.cshtml"
+                                             foreach (var line in frame.ContextCode)
+                                            {
+
+#line default
+#line hidden
+            WriteLiteral("                                                <li><span>");
+#line 329 "ErrorPage.cshtml"
+                                                     Write(line);
+
+#line default
+#line hidden
+            WriteLiteral("</span></li>\r\n");
+#line 330 "ErrorPage.cshtml"
+                                            }
+
+#line default
+#line hidden
+            WriteLiteral("                                        </ol>\r\n\r\n");
+#line 333 "ErrorPage.cshtml"
+                                         if (frame.PostContextCode.Any())
+                                        {
+
+#line default
+#line hidden
+            WriteLiteral("                                            <ol");
+            BeginWriteAttribute("start", " start=\'", 9283, "\'", 9308, 1);
+#line 335 "ErrorPage.cshtml"
+WriteAttributeValue("", 9291, frame.Line + 1, 9291, 17, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(" class=\"collapsible\">\r\n");
+#line 336 "ErrorPage.cshtml"
+                                                 foreach (var line in frame.PostContextCode)
+                                                {
+
+#line default
+#line hidden
+            WriteLiteral("                                                    <li><span>");
+#line 338 "ErrorPage.cshtml"
+                                                         Write(line);
+
+#line default
+#line hidden
+            WriteLiteral("</span></li>\r\n");
+#line 339 "ErrorPage.cshtml"
+                                                }
+
+#line default
+#line hidden
+            WriteLiteral("                                            </ol>\r\n");
+#line 341 "ErrorPage.cshtml"
+                                        }
+
+#line default
+#line hidden
+            WriteLiteral("                                    </div>\r\n");
+#line 343 "ErrorPage.cshtml"
+                                }
+
+#line default
+#line hidden
+            WriteLiteral("                            </li>\r\n");
+#line 345 "ErrorPage.cshtml"
+                        }
+
+#line default
+#line hidden
+            WriteLiteral(@"                        </ul>
+                    </li>
+                    <li>
+                        <br/>
+                        <div class=""rawExceptionBlock"">
+                            <div class=""showRawExceptionContainer"">
+                                <button class=""showRawException"" data-exceptionDetailId=""");
+#line 352 "ErrorPage.cshtml"
+                                                                                    Write(exceptionDetailId);
+
+#line default
+#line hidden
+            WriteLiteral("\">Show raw exception details</button>\r\n                            </div>\r\n                            <div");
+            BeginWriteAttribute("id", " id=\"", 10299, "\"", 10322, 1);
+#line 354 "ErrorPage.cshtml"
+WriteAttributeValue("", 10304, exceptionDetailId, 10304, 18, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            WriteLiteral(" class=\"rawExceptionDetails\">\r\n                                <pre class=\"rawExceptionStackTrace\">");
+#line 355 "ErrorPage.cshtml"
+                                                               Write(errorDetail.Error.ToString());
+
+#line default
+#line hidden
+            WriteLiteral("</pre>\r\n                            </div>\r\n                        </div>\r\n                    </li>\r\n");
+#line 359 "ErrorPage.cshtml"
+                }
+
+#line default
+#line hidden
+            WriteLiteral("            </ul>\r\n        </div>\r\n\r\n        <div id=\"querypage\" class=\"page\">\r\n");
+#line 364 "ErrorPage.cshtml"
+             if (Model.Query.Any())
+            {
+
+#line default
+#line hidden
+            WriteLiteral("                <table>\r\n                    <thead>\r\n                        <tr>\r\n                            <th>");
+#line 369 "ErrorPage.cshtml"
+                           Write(Resources.ErrorPageHtml_VariableColumn);
+
+#line default
+#line hidden
+            WriteLiteral("</th>\r\n                            <th>");
+#line 370 "ErrorPage.cshtml"
+                           Write(Resources.ErrorPageHtml_ValueColumn);
+
+#line default
+#line hidden
+            WriteLiteral("</th>\r\n                        </tr>\r\n                    </thead>\r\n                    <tbody>\r\n");
+#line 374 "ErrorPage.cshtml"
+                         foreach (var kv in Model.Query.OrderBy(kv => kv.Key))
+                        {
+                            foreach (var v in kv.Value)
+                            {
+
+#line default
+#line hidden
+            WriteLiteral("                                <tr>\r\n                                    <td>");
+#line 379 "ErrorPage.cshtml"
+                                   Write(kv.Key);
+
+#line default
+#line hidden
+            WriteLiteral("</td>\r\n                                    <td>");
+#line 380 "ErrorPage.cshtml"
+                                   Write(v);
+
+#line default
+#line hidden
+            WriteLiteral("</td>\r\n                                </tr>\r\n");
+#line 382 "ErrorPage.cshtml"
+                            }
+                        }
+
+#line default
+#line hidden
+            WriteLiteral("                    </tbody>\r\n                </table>\r\n");
+#line 386 "ErrorPage.cshtml"
+            }
+            else
+            {
+
+#line default
+#line hidden
+            WriteLiteral("                <p>");
+#line 389 "ErrorPage.cshtml"
+              Write(Resources.ErrorPageHtml_NoQueryStringData);
+
+#line default
+#line hidden
+            WriteLiteral("</p>\r\n");
+#line 390 "ErrorPage.cshtml"
+            }
+
+#line default
+#line hidden
+            WriteLiteral("        </div>\r\n\r\n        <div id=\"cookiespage\" class=\"page\">\r\n");
+#line 394 "ErrorPage.cshtml"
+             if (Model.Cookies.Any())
+            {
+
+#line default
+#line hidden
+            WriteLiteral("                <table>\r\n                    <thead>\r\n                        <tr>\r\n                            <th>");
+#line 399 "ErrorPage.cshtml"
+                           Write(Resources.ErrorPageHtml_VariableColumn);
+
+#line default
+#line hidden
+            WriteLiteral("</th>\r\n                            <th>");
+#line 400 "ErrorPage.cshtml"
+                           Write(Resources.ErrorPageHtml_ValueColumn);
+
+#line default
+#line hidden
+            WriteLiteral("</th>\r\n                        </tr>\r\n                    </thead>\r\n                    <tbody>\r\n");
+#line 404 "ErrorPage.cshtml"
+                         foreach (var kv in Model.Cookies.OrderBy(kv => kv.Key))
+                        {
+
+#line default
+#line hidden
+            WriteLiteral("                            <tr>\r\n                                <td>");
+#line 407 "ErrorPage.cshtml"
+                               Write(kv.Key);
+
+#line default
+#line hidden
+            WriteLiteral("</td>\r\n                                <td>");
+#line 408 "ErrorPage.cshtml"
+                               Write(kv.Value);
+
+#line default
+#line hidden
+            WriteLiteral("</td>\r\n                            </tr>\r\n");
+#line 410 "ErrorPage.cshtml"
+                        }
+
+#line default
+#line hidden
+            WriteLiteral("                    </tbody>\r\n                </table>\r\n");
+#line 413 "ErrorPage.cshtml"
+            }
+            else
+            {
+
+#line default
+#line hidden
+            WriteLiteral("                <p>");
+#line 416 "ErrorPage.cshtml"
+              Write(Resources.ErrorPageHtml_NoCookieData);
+
+#line default
+#line hidden
+            WriteLiteral("</p>\r\n");
+#line 417 "ErrorPage.cshtml"
+            }
+
+#line default
+#line hidden
+            WriteLiteral("        </div>\r\n        <div id=\"headerspage\" class=\"page\">\r\n");
+#line 420 "ErrorPage.cshtml"
+             if (Model.Headers.Any())
+            {
+
+#line default
+#line hidden
+            WriteLiteral("                <table>\r\n                    <thead>\r\n                        <tr>\r\n                            <th>");
+#line 425 "ErrorPage.cshtml"
+                           Write(Resources.ErrorPageHtml_VariableColumn);
+
+#line default
+#line hidden
+            WriteLiteral("</th>\r\n                            <th>");
+#line 426 "ErrorPage.cshtml"
+                           Write(Resources.ErrorPageHtml_ValueColumn);
+
+#line default
+#line hidden
+            WriteLiteral("</th>\r\n                        </tr>\r\n                    </thead>\r\n                    <tbody>\r\n");
+#line 430 "ErrorPage.cshtml"
+                         foreach (var kv in Model.Headers.OrderBy(kv => kv.Key))
+                        {
+                            foreach (var v in kv.Value)
+                            {
+
+#line default
+#line hidden
+            WriteLiteral("                                <tr>\r\n                                    <td>");
+#line 435 "ErrorPage.cshtml"
+                                   Write(kv.Key);
+
+#line default
+#line hidden
+            WriteLiteral("</td>\r\n                                    <td>");
+#line 436 "ErrorPage.cshtml"
+                                   Write(v);
+
+#line default
+#line hidden
+            WriteLiteral("</td>\r\n                                </tr>\r\n");
+#line 438 "ErrorPage.cshtml"
+                            }
+                        }
+
+#line default
+#line hidden
+            WriteLiteral("                    </tbody>\r\n                </table>\r\n");
+#line 442 "ErrorPage.cshtml"
+            }
+            else
+            {
+
+#line default
+#line hidden
+            WriteLiteral("                <p>");
+#line 445 "ErrorPage.cshtml"
+              Write(Resources.ErrorPageHtml_NoHeaderData);
+
+#line default
+#line hidden
+            WriteLiteral("</p>\r\n");
+#line 446 "ErrorPage.cshtml"
+            }
+
+#line default
+#line hidden
+            WriteLiteral(@"        </div>
+        <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(");
+            WriteLiteral(@"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.i");
+            WriteLiteral(@"ndexOf(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;
+          ");
+            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) {
+           ");
+            WriteLiteral(@" 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");
+            WriteLiteral(@".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);
+            //-->
+        </script>
+    </body>
+</html>
+");
+        }
+        #pragma warning restore 1998
+#line 9 "ErrorPage.cshtml"
+ 
+    public ErrorPage(ErrorPageModel model)
+    {
+        Model = model;
+    }
+
+    public ErrorPageModel Model { get; set; }
+
+#line default
+#line hidden
+    }
+}
+#pragma warning restore 1591

+ 258 - 0
src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/ErrorPage.cshtml

@@ -0,0 +1,258 @@
+@using System
+@using System.Globalization
+@using System.Linq
+@using System.Net
+@using System.Reflection
+@using Microsoft.AspNetCore.Diagnostics.RazorViews
+@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 = errorDetail.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>

+ 196 - 0
src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/ErrorPage.css

@@ -0,0 +1,196 @@
+body {
+    font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif;
+    font-size: .813em;
+    color: #222;
+    background-color: #fff;
+}
+
+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;
+}

+ 192 - 0
src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/ErrorPage.js

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

+ 42 - 0
src/Middleware/Diagnostics/src/DeveloperExceptionPage/Views/ErrorPageModel.cs

@@ -0,0 +1,42 @@
+// 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.Collections.Generic;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+using Microsoft.Extensions.StackTrace.Sources;
+
+namespace Microsoft.AspNetCore.Diagnostics.RazorViews
+{
+    /// <summary>
+    /// Holds data to be displayed on the error page.
+    /// </summary>
+    internal 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<ExceptionDetails> 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; }
+    }
+}

+ 98 - 0
src/Middleware/Diagnostics/src/ExceptionHandler/ExceptionHandlerExtensions.cs

@@ -0,0 +1,98 @@
+// 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 Microsoft.AspNetCore.Diagnostics;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.AspNetCore.Builder
+{
+    public static class ExceptionHandlerExtensions
+    {
+        /// <summary>
+        /// Adds a middleware to the pipeline that will catch exceptions, log them, and re-execute the request in an alternate pipeline.
+        /// The request will not be re-executed if the response has already started.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            return app.UseMiddleware<ExceptionHandlerMiddleware>();
+        }
+
+        /// <summary>
+        /// Adds a middleware to the pipeline that will catch exceptions, log them, reset the request path, and re-execute the request.
+        /// The request will not be re-executed if the response has already started.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="errorHandlingPath"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app, string errorHandlingPath)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            return app.UseExceptionHandler(new ExceptionHandlerOptions
+            {
+                ExceptionHandlingPath = new PathString(errorHandlingPath)
+            });
+        }
+
+        /// <summary>
+        /// Adds a middleware to the pipeline that will catch exceptions, log them, and re-execute the request in an alternate pipeline.
+        /// The request will not be re-executed if the response has already started.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="configure"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app, Action<IApplicationBuilder> configure)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+            if (configure == null)
+            {
+                throw new ArgumentNullException(nameof(configure));
+            }
+
+            var subAppBuilder = app.New();
+            configure(subAppBuilder);
+            var exceptionHandlerPipeline = subAppBuilder.Build();
+
+            return app.UseExceptionHandler(new ExceptionHandlerOptions
+            {
+                ExceptionHandler = exceptionHandlerPipeline
+            });
+        }
+
+        /// <summary>
+        /// Adds a middleware to the pipeline that will catch exceptions, log them, and re-execute the request in an alternate pipeline.
+        /// The request will not be re-executed if the response has already started.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="options"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseExceptionHandler(this IApplicationBuilder app, ExceptionHandlerOptions options)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            return app.UseMiddleware<ExceptionHandlerMiddleware>(Options.Create(options));
+        }
+    }
+}

+ 14 - 0
src/Middleware/Diagnostics/src/ExceptionHandler/ExceptionHandlerFeature.cs

@@ -0,0 +1,14 @@
+// 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 Microsoft.AspNetCore.Diagnostics
+{
+    public class ExceptionHandlerFeature : IExceptionHandlerPathFeature
+    {
+        public Exception Error { get; set; }
+
+        public string Path { get; set; }
+    }
+}

+ 115 - 0
src/Middleware/Diagnostics/src/ExceptionHandler/ExceptionHandlerMiddleware.cs

@@ -0,0 +1,115 @@
+// 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.Diagnostics;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.Internal;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Microsoft.Net.Http.Headers;
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    public class ExceptionHandlerMiddleware
+    {
+        private readonly RequestDelegate _next;
+        private readonly ExceptionHandlerOptions _options;
+        private readonly ILogger _logger;
+        private readonly Func<object, Task> _clearCacheHeadersDelegate;
+        private readonly DiagnosticSource _diagnosticSource;
+
+        public ExceptionHandlerMiddleware(
+            RequestDelegate next,
+            ILoggerFactory loggerFactory,
+            IOptions<ExceptionHandlerOptions> options,
+            DiagnosticSource diagnosticSource)
+        {
+            _next = next;
+            _options = options.Value;
+            _logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();
+            _clearCacheHeadersDelegate = ClearCacheHeaders;
+            _diagnosticSource = diagnosticSource;
+            if (_options.ExceptionHandler == null)
+            {
+                if (_options.ExceptionHandlingPath == null)
+                {
+                    throw new InvalidOperationException(Resources.FormatExceptionHandlerOptions_NotConfiguredCorrectly());
+                }
+                else
+                {
+                    _options.ExceptionHandler = _next;
+                }
+            }
+        }
+
+        public async Task Invoke(HttpContext context)
+        {
+            try
+            {
+                await _next(context);
+            }
+            catch (Exception ex)
+            {
+                _logger.UnhandledException(ex);
+                // We can't do anything if the response has already started, just abort.
+                if (context.Response.HasStarted)
+                {
+                    _logger.ResponseStartedErrorHandler();
+                    throw;
+                }
+
+                PathString originalPath = context.Request.Path;
+                if (_options.ExceptionHandlingPath.HasValue)
+                {
+                    context.Request.Path = _options.ExceptionHandlingPath;
+                }
+                try
+                {
+                    context.Response.Clear();
+                    var exceptionHandlerFeature = new ExceptionHandlerFeature()
+                    {
+                        Error = ex,
+                        Path = originalPath.Value,
+                    };
+                    context.Features.Set<IExceptionHandlerFeature>(exceptionHandlerFeature);
+                    context.Features.Set<IExceptionHandlerPathFeature>(exceptionHandlerFeature);
+                    context.Response.StatusCode = 500;
+                    context.Response.OnStarting(_clearCacheHeadersDelegate, context.Response);
+
+                    await _options.ExceptionHandler(context);
+
+                    if (_diagnosticSource.IsEnabled("Microsoft.AspNetCore.Diagnostics.HandledException"))
+                    {
+                        _diagnosticSource.Write("Microsoft.AspNetCore.Diagnostics.HandledException", new { httpContext = context, exception = ex });
+                    }
+
+                    // TODO: Optional re-throw? We'll re-throw the original exception by default if the error handler throws.
+                    return;
+                }
+                catch (Exception ex2)
+                {
+                    // Suppress secondary exceptions, re-throw the original.
+                    _logger.ErrorHandlerException(ex2);
+                }
+                finally
+                {
+                    context.Request.Path = originalPath;
+                }
+                throw; // Re-throw the original if we couldn't handle it
+            }
+        }
+
+        private Task ClearCacheHeaders(object state)
+        {
+            var response = (HttpResponse)state;
+            response.Headers[HeaderNames.CacheControl] = "no-cache";
+            response.Headers[HeaderNames.Pragma] = "no-cache";
+            response.Headers[HeaderNames.Expires] = "-1";
+            response.Headers.Remove(HeaderNames.ETag);
+            return Task.CompletedTask;
+        }
+    }
+}

+ 14 - 0
src/Middleware/Diagnostics/src/ExceptionHandler/ExceptionHandlerOptions.cs

@@ -0,0 +1,14 @@
+// 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 Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.Builder
+{
+    public class ExceptionHandlerOptions
+    {
+        public PathString ExceptionHandlingPath { get; set; }
+
+        public RequestDelegate ExceptionHandler { get; set; }
+    }
+}

+ 54 - 0
src/Middleware/Diagnostics/src/Internal/DiagnosticsLoggerExtensions.cs

@@ -0,0 +1,54 @@
+// 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 Microsoft.Extensions.Logging;
+
+namespace Microsoft.AspNetCore.Diagnostics.Internal
+{
+    internal static class DiagnosticsLoggerExtensions
+    {
+        // ExceptionHandlerMiddleware & DeveloperExceptionPageMiddleware
+        private static readonly Action<ILogger, Exception> _unhandledException =
+            LoggerMessage.Define(LogLevel.Error, new EventId(1, "UnhandledException"), "An unhandled exception has occurred while executing the request.");
+
+        // ExceptionHandlerMiddleware
+        private static readonly Action<ILogger, Exception> _responseStartedErrorHandler =
+            LoggerMessage.Define(LogLevel.Warning, new EventId(2, "ResponseStarted"), "The response has already started, the error handler will not be executed.");
+
+        private static readonly Action<ILogger, Exception> _errorHandlerException =
+            LoggerMessage.Define(LogLevel.Error, new EventId(3, "Exception"), "An exception was thrown attempting to execute the error handler.");
+
+        // DeveloperExceptionPageMiddleware
+        private static readonly Action<ILogger, Exception> _responseStartedErrorPageMiddleware =
+            LoggerMessage.Define(LogLevel.Warning, new EventId(2, "ResponseStarted"), "The response has already started, the error page middleware will not be executed.");
+
+        private static readonly Action<ILogger, Exception> _displayErrorPageException =
+            LoggerMessage.Define(LogLevel.Error, new EventId(3, "DisplayErrorPageException"), "An exception was thrown attempting to display the error page.");
+
+        public static void UnhandledException(this ILogger logger, Exception exception)
+        {
+            _unhandledException(logger, exception);
+        }
+
+        public static void ResponseStartedErrorHandler(this ILogger logger)
+        {
+            _responseStartedErrorHandler(logger, null);
+        }
+
+        public static void ErrorHandlerException(this ILogger logger, Exception exception)
+        {
+            _errorHandlerException(logger, exception);
+        }
+
+        public static void ResponseStartedErrorPageMiddleware(this ILogger logger)
+        {
+            _responseStartedErrorPageMiddleware(logger, null);
+        }
+
+        public static void DisplayErrorPageException(this ILogger logger, Exception exception)
+        {
+            _displayErrorPageException(logger, exception);
+        }
+    }
+}

+ 30 - 0
src/Middleware/Diagnostics/src/Microsoft.AspNetCore.Diagnostics.csproj

@@ -0,0 +1,30 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <Description>ASP.NET Core middleware for exception handling, exception display pages, and diagnostics information. Includes developer exception page middleware, exception handler middleware, runtime info middleware, status code page middleware, and welcome page middleware</Description>
+    <TargetFramework>netstandard2.0</TargetFramework>
+    <NoWarn>$(NoWarn);CS1591</NoWarn>
+    <GenerateDocumentationFile>true</GenerateDocumentationFile>
+    <PackageTags>aspnetcore;diagnostics</PackageTags>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Compile Include="$(SharedSourceRoot)Diagnostics\*.cs" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Reference Include="Microsoft.AspNetCore.Diagnostics.Abstractions" />
+    <Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
+    <Reference Include="Microsoft.AspNetCore.Http.Extensions" />
+    <Reference Include="Microsoft.AspNetCore.WebUtilities" />
+    <Reference Include="Microsoft.Extensions.FileProviders.Physical" />
+    <Reference Include="Microsoft.Extensions.Logging.Abstractions" />
+    <Reference Include="Microsoft.Extensions.Options" />
+    <Reference Include="Microsoft.Extensions.RazorViews.Sources" PrivateAssets="All" />
+    <Reference Include="Microsoft.Extensions.StackTrace.Sources" PrivateAssets="All" />
+    <Reference Include="Microsoft.Extensions.TypeNameHelper.Sources" PrivateAssets="All" />
+    <Reference Include="System.Diagnostics.DiagnosticSource" />
+    <Reference Include="System.Reflection.Metadata" />
+  </ItemGroup>
+
+</Project>

+ 9 - 0
src/Middleware/Diagnostics/src/Properties/AssemblyInfo.cs

@@ -0,0 +1,9 @@
+// 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.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Diagnostics.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

+ 618 - 0
src/Middleware/Diagnostics/src/Properties/Resources.Designer.cs

@@ -0,0 +1,618 @@
+// <auto-generated />
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    using System.Globalization;
+    using System.Reflection;
+    using System.Resources;
+
+    internal static class Resources
+    {
+        private static readonly ResourceManager _resourceManager
+            = new ResourceManager("Microsoft.AspNetCore.Diagnostics.Resources", typeof(Resources).GetTypeInfo().Assembly);
+
+        /// <summary>
+        /// You are seeing this page because DiagnosticsPageMiddleware was added to your web application.
+        /// </summary>
+        internal static string DiagnosticsPageHtml_Information
+        {
+            get => GetString("DiagnosticsPageHtml_Information");
+        }
+
+        /// <summary>
+        /// You are seeing this page because DiagnosticsPageMiddleware was added to your web application.
+        /// </summary>
+        internal static string FormatDiagnosticsPageHtml_Information()
+            => GetString("DiagnosticsPageHtml_Information");
+
+        /// <summary>
+        /// Test Error Message
+        /// </summary>
+        internal static string DiagnosticsPageHtml_TestErrorMessage
+        {
+            get => GetString("DiagnosticsPageHtml_TestErrorMessage");
+        }
+
+        /// <summary>
+        /// Test Error Message
+        /// </summary>
+        internal static string FormatDiagnosticsPageHtml_TestErrorMessage()
+            => GetString("DiagnosticsPageHtml_TestErrorMessage");
+
+        /// <summary>
+        /// Test Error Page
+        /// </summary>
+        internal static string DiagnosticsPageHtml_TestErrorSection
+        {
+            get => GetString("DiagnosticsPageHtml_TestErrorSection");
+        }
+
+        /// <summary>
+        /// Test Error Page
+        /// </summary>
+        internal static string FormatDiagnosticsPageHtml_TestErrorSection()
+            => GetString("DiagnosticsPageHtml_TestErrorSection");
+
+        /// <summary>
+        /// Diagnostics Page
+        /// </summary>
+        internal static string DiagnosticsPageHtml_Title
+        {
+            get => GetString("DiagnosticsPageHtml_Title");
+        }
+
+        /// <summary>
+        /// Diagnostics Page
+        /// </summary>
+        internal static string FormatDiagnosticsPageHtml_Title()
+            => GetString("DiagnosticsPageHtml_Title");
+
+        /// <summary>
+        /// Cookies
+        /// </summary>
+        internal static string ErrorPageHtml_CookiesButton
+        {
+            get => GetString("ErrorPageHtml_CookiesButton");
+        }
+
+        /// <summary>
+        /// Cookies
+        /// </summary>
+        internal static string FormatErrorPageHtml_CookiesButton()
+            => GetString("ErrorPageHtml_CookiesButton");
+
+        /// <summary>
+        /// Headers
+        /// </summary>
+        internal static string ErrorPageHtml_HeadersButton
+        {
+            get => GetString("ErrorPageHtml_HeadersButton");
+        }
+
+        /// <summary>
+        /// Headers
+        /// </summary>
+        internal static string FormatErrorPageHtml_HeadersButton()
+            => GetString("ErrorPageHtml_HeadersButton");
+
+        /// <summary>
+        /// No cookie data.
+        /// </summary>
+        internal static string ErrorPageHtml_NoCookieData
+        {
+            get => GetString("ErrorPageHtml_NoCookieData");
+        }
+
+        /// <summary>
+        /// No cookie data.
+        /// </summary>
+        internal static string FormatErrorPageHtml_NoCookieData()
+            => GetString("ErrorPageHtml_NoCookieData");
+
+        /// <summary>
+        /// No header data.
+        /// </summary>
+        internal static string ErrorPageHtml_NoHeaderData
+        {
+            get => GetString("ErrorPageHtml_NoHeaderData");
+        }
+
+        /// <summary>
+        /// No header data.
+        /// </summary>
+        internal static string FormatErrorPageHtml_NoHeaderData()
+            => GetString("ErrorPageHtml_NoHeaderData");
+
+        /// <summary>
+        /// No QueryString data.
+        /// </summary>
+        internal static string ErrorPageHtml_NoQueryStringData
+        {
+            get => GetString("ErrorPageHtml_NoQueryStringData");
+        }
+
+        /// <summary>
+        /// No QueryString data.
+        /// </summary>
+        internal static string FormatErrorPageHtml_NoQueryStringData()
+            => GetString("ErrorPageHtml_NoQueryStringData");
+
+        /// <summary>
+        /// Query
+        /// </summary>
+        internal static string ErrorPageHtml_QueryButton
+        {
+            get => GetString("ErrorPageHtml_QueryButton");
+        }
+
+        /// <summary>
+        /// Query
+        /// </summary>
+        internal static string FormatErrorPageHtml_QueryButton()
+            => GetString("ErrorPageHtml_QueryButton");
+
+        /// <summary>
+        /// Stack
+        /// </summary>
+        internal static string ErrorPageHtml_StackButton
+        {
+            get => GetString("ErrorPageHtml_StackButton");
+        }
+
+        /// <summary>
+        /// Stack
+        /// </summary>
+        internal static string FormatErrorPageHtml_StackButton()
+            => GetString("ErrorPageHtml_StackButton");
+
+        /// <summary>
+        /// Internal Server Error
+        /// </summary>
+        internal static string ErrorPageHtml_Title
+        {
+            get => GetString("ErrorPageHtml_Title");
+        }
+
+        /// <summary>
+        /// Internal Server Error
+        /// </summary>
+        internal static string FormatErrorPageHtml_Title()
+            => GetString("ErrorPageHtml_Title");
+
+        /// <summary>
+        /// An unhandled exception occurred while processing the request.
+        /// </summary>
+        internal static string ErrorPageHtml_UnhandledException
+        {
+            get => GetString("ErrorPageHtml_UnhandledException");
+        }
+
+        /// <summary>
+        /// An unhandled exception occurred while processing the request.
+        /// </summary>
+        internal static string FormatErrorPageHtml_UnhandledException()
+            => GetString("ErrorPageHtml_UnhandledException");
+
+        /// <summary>
+        /// Unknown location
+        /// </summary>
+        internal static string ErrorPageHtml_UnknownLocation
+        {
+            get => GetString("ErrorPageHtml_UnknownLocation");
+        }
+
+        /// <summary>
+        /// Unknown location
+        /// </summary>
+        internal static string FormatErrorPageHtml_UnknownLocation()
+            => GetString("ErrorPageHtml_UnknownLocation");
+
+        /// <summary>
+        /// Value
+        /// </summary>
+        internal static string ErrorPageHtml_ValueColumn
+        {
+            get => GetString("ErrorPageHtml_ValueColumn");
+        }
+
+        /// <summary>
+        /// Value
+        /// </summary>
+        internal static string FormatErrorPageHtml_ValueColumn()
+            => GetString("ErrorPageHtml_ValueColumn");
+
+        /// <summary>
+        /// Variable
+        /// </summary>
+        internal static string ErrorPageHtml_VariableColumn
+        {
+            get => GetString("ErrorPageHtml_VariableColumn");
+        }
+
+        /// <summary>
+        /// Variable
+        /// </summary>
+        internal static string FormatErrorPageHtml_VariableColumn()
+            => GetString("ErrorPageHtml_VariableColumn");
+
+        /// <summary>
+        /// The path must start with a '/'.
+        /// </summary>
+        internal static string Exception_PathMustStartWithSlash
+        {
+            get => GetString("Exception_PathMustStartWithSlash");
+        }
+
+        /// <summary>
+        /// The path must start with a '/'.
+        /// </summary>
+        internal static string FormatException_PathMustStartWithSlash()
+            => GetString("Exception_PathMustStartWithSlash");
+
+        /// <summary>
+        /// Name
+        /// </summary>
+        internal static string RuntimeInfoPage_PackageNameColumnName
+        {
+            get => GetString("RuntimeInfoPage_PackageNameColumnName");
+        }
+
+        /// <summary>
+        /// Name
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_PackageNameColumnName()
+            => GetString("RuntimeInfoPage_PackageNameColumnName");
+
+        /// <summary>
+        /// Path
+        /// </summary>
+        internal static string RuntimeInfoPage_PackagePathColumnName
+        {
+            get => GetString("RuntimeInfoPage_PackagePathColumnName");
+        }
+
+        /// <summary>
+        /// Path
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_PackagePathColumnName()
+            => GetString("RuntimeInfoPage_PackagePathColumnName");
+
+        /// <summary>
+        /// Packages:
+        /// </summary>
+        internal static string RuntimeInfoPage_Packages
+        {
+            get => GetString("RuntimeInfoPage_Packages");
+        }
+
+        /// <summary>
+        /// Packages:
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_Packages()
+            => GetString("RuntimeInfoPage_Packages");
+
+        /// <summary>
+        /// Could not retrieve the list of loaded packages.
+        /// </summary>
+        internal static string RuntimeInfoPage_PackagesFail
+        {
+            get => GetString("RuntimeInfoPage_PackagesFail");
+        }
+
+        /// <summary>
+        /// Could not retrieve the list of loaded packages.
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_PackagesFail()
+            => GetString("RuntimeInfoPage_PackagesFail");
+
+        /// <summary>
+        /// Version
+        /// </summary>
+        internal static string RuntimeInfoPage_PackageVersionColumnName
+        {
+            get => GetString("RuntimeInfoPage_PackageVersionColumnName");
+        }
+
+        /// <summary>
+        /// Version
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_PackageVersionColumnName()
+            => GetString("RuntimeInfoPage_PackageVersionColumnName");
+
+        /// <summary>
+        /// Runtime Version:
+        /// </summary>
+        internal static string RuntimeInfoPage_RuntimeVersion
+        {
+            get => GetString("RuntimeInfoPage_RuntimeVersion");
+        }
+
+        /// <summary>
+        /// Runtime Version:
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_RuntimeVersion()
+            => GetString("RuntimeInfoPage_RuntimeVersion");
+
+        /// <summary>
+        /// Could not determine the runtime version.
+        /// </summary>
+        internal static string RuntimeInfoPage_RuntimeVersionFail
+        {
+            get => GetString("RuntimeInfoPage_RuntimeVersionFail");
+        }
+
+        /// <summary>
+        /// Could not determine the runtime version.
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_RuntimeVersionFail()
+            => GetString("RuntimeInfoPage_RuntimeVersionFail");
+
+        /// <summary>
+        /// Runtime Information
+        /// </summary>
+        internal static string RuntimeInfoPage_Title
+        {
+            get => GetString("RuntimeInfoPage_Title");
+        }
+
+        /// <summary>
+        /// Runtime Information
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_Title()
+            => GetString("RuntimeInfoPage_Title");
+
+        /// <summary>
+        /// Welcome
+        /// </summary>
+        internal static string WelcomeHeader
+        {
+            get => GetString("WelcomeHeader");
+        }
+
+        /// <summary>
+        /// Welcome
+        /// </summary>
+        internal static string FormatWelcomeHeader()
+            => GetString("WelcomeHeader");
+
+        /// <summary>
+        /// Learn more about the Microsoft ASP.NET Core components
+        /// </summary>
+        internal static string WelcomeLearnMicrosoftAspNet
+        {
+            get => GetString("WelcomeLearnMicrosoftAspNet");
+        }
+
+        /// <summary>
+        /// Learn more about the Microsoft ASP.NET Core components
+        /// </summary>
+        internal static string FormatWelcomeLearnMicrosoftAspNet()
+            => GetString("WelcomeLearnMicrosoftAspNet");
+
+        /// <summary>
+        /// Browser
+        /// </summary>
+        internal static string WelcomePageImageText_Browser
+        {
+            get => GetString("WelcomePageImageText_Browser");
+        }
+
+        /// <summary>
+        /// Browser
+        /// </summary>
+        internal static string FormatWelcomePageImageText_Browser()
+            => GetString("WelcomePageImageText_Browser");
+
+        /// <summary>
+        /// Learn More
+        /// </summary>
+        internal static string WelcomePageImageText_LearnMore
+        {
+            get => GetString("WelcomePageImageText_LearnMore");
+        }
+
+        /// <summary>
+        /// Learn More
+        /// </summary>
+        internal static string FormatWelcomePageImageText_LearnMore()
+            => GetString("WelcomePageImageText_LearnMore");
+
+        /// <summary>
+        /// Light Bulb
+        /// </summary>
+        internal static string WelcomePageImageText_LightBulb
+        {
+            get => GetString("WelcomePageImageText_LightBulb");
+        }
+
+        /// <summary>
+        /// Light Bulb
+        /// </summary>
+        internal static string FormatWelcomePageImageText_LightBulb()
+            => GetString("WelcomePageImageText_LightBulb");
+
+        /// <summary>
+        /// Skyline
+        /// </summary>
+        internal static string WelcomePageImageText_Skyline
+        {
+            get => GetString("WelcomePageImageText_Skyline");
+        }
+
+        /// <summary>
+        /// Skyline
+        /// </summary>
+        internal static string FormatWelcomePageImageText_Skyline()
+            => GetString("WelcomePageImageText_Skyline");
+
+        /// <summary>
+        /// Your ASP.NET Core application has been successfully started
+        /// </summary>
+        internal static string WelcomeStarted
+        {
+            get => GetString("WelcomeStarted");
+        }
+
+        /// <summary>
+        /// Your ASP.NET Core application has been successfully started
+        /// </summary>
+        internal static string FormatWelcomeStarted()
+            => GetString("WelcomeStarted");
+
+        /// <summary>
+        /// Your ASP.NET Core application has been successfully started.
+        /// </summary>
+        internal static string WelcomeTitle
+        {
+            get => GetString("WelcomeTitle");
+        }
+
+        /// <summary>
+        /// Your ASP.NET Core application has been successfully started.
+        /// </summary>
+        internal static string FormatWelcomeTitle()
+            => GetString("WelcomeTitle");
+
+        /// <summary>
+        /// An error occurred during the compilation of a resource required to process this request. Please review the following specific error details and modify your source code appropriately.
+        /// </summary>
+        internal static string ErrorPageHtml_CompilationException
+        {
+            get => GetString("ErrorPageHtml_CompilationException");
+        }
+
+        /// <summary>
+        /// An error occurred during the compilation of a resource required to process this request. Please review the following specific error details and modify your source code appropriately.
+        /// </summary>
+        internal static string FormatErrorPageHtml_CompilationException()
+            => GetString("ErrorPageHtml_CompilationException");
+
+        /// <summary>
+        /// Operating System:
+        /// </summary>
+        internal static string RuntimeInfoPage_OperatingSystem
+        {
+            get => GetString("RuntimeInfoPage_OperatingSystem");
+        }
+
+        /// <summary>
+        /// Operating System:
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_OperatingSystem()
+            => GetString("RuntimeInfoPage_OperatingSystem");
+
+        /// <summary>
+        /// Runtime Architecture:
+        /// </summary>
+        internal static string RuntimeInfoPage_RuntimeArchitecture
+        {
+            get => GetString("RuntimeInfoPage_RuntimeArchitecture");
+        }
+
+        /// <summary>
+        /// Runtime Architecture:
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_RuntimeArchitecture()
+            => GetString("RuntimeInfoPage_RuntimeArchitecture");
+
+        /// <summary>
+        /// Runtime Type:
+        /// </summary>
+        internal static string RuntimeInfoPage_RuntimeType
+        {
+            get => GetString("RuntimeInfoPage_RuntimeType");
+        }
+
+        /// <summary>
+        /// Runtime Type:
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_RuntimeType()
+            => GetString("RuntimeInfoPage_RuntimeType");
+
+        /// <summary>
+        /// Could not determine the operating system.
+        /// </summary>
+        internal static string RuntimeInfoPage_OperatingSystemFail
+        {
+            get => GetString("RuntimeInfoPage_OperatingSystemFail");
+        }
+
+        /// <summary>
+        /// Could not determine the operating system.
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_OperatingSystemFail()
+            => GetString("RuntimeInfoPage_OperatingSystemFail");
+
+        /// <summary>
+        /// Could not determine the runtime architecture.
+        /// </summary>
+        internal static string RuntimeInfoPage_RuntimeArchitectureFail
+        {
+            get => GetString("RuntimeInfoPage_RuntimeArchitectureFail");
+        }
+
+        /// <summary>
+        /// Could not determine the runtime architecture.
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_RuntimeArchitectureFail()
+            => GetString("RuntimeInfoPage_RuntimeArchitectureFail");
+
+        /// <summary>
+        /// Could not determine the runtime type.
+        /// </summary>
+        internal static string RuntimeInfoPage_RuntimeTypeFail
+        {
+            get => GetString("RuntimeInfoPage_RuntimeTypeFail");
+        }
+
+        /// <summary>
+        /// Could not determine the runtime type.
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_RuntimeTypeFail()
+            => GetString("RuntimeInfoPage_RuntimeTypeFail");
+
+        /// <summary>
+        /// Environment:
+        /// </summary>
+        internal static string RuntimeInfoPage_Environment
+        {
+            get => GetString("RuntimeInfoPage_Environment");
+        }
+
+        /// <summary>
+        /// Environment:
+        /// </summary>
+        internal static string FormatRuntimeInfoPage_Environment()
+            => GetString("RuntimeInfoPage_Environment");
+
+        /// <summary>
+        /// An error occurred when configuring the exception handler middleware. Either the 'ExceptionHandlingPath' or the 'ExceptionHandler' option must be set in 'UseExceptionHandler()'.
+        /// </summary>
+        internal static string ExceptionHandlerOptions_NotConfiguredCorrectly
+        {
+            get => GetString("ExceptionHandlerOptions_NotConfiguredCorrectly");
+        }
+
+        /// <summary>
+        /// An error occurred when configuring the exception handler middleware. Either the 'ExceptionHandlingPath' or the 'ExceptionHandler' option must be set in 'UseExceptionHandler()'.
+        /// </summary>
+        internal static string FormatExceptionHandlerOptions_NotConfiguredCorrectly()
+            => GetString("ExceptionHandlerOptions_NotConfiguredCorrectly");
+
+        private static string GetString(string name, params string[] formatterNames)
+        {
+            var value = _resourceManager.GetString(name);
+
+            System.Diagnostics.Debug.Assert(value != null);
+
+            if (formatterNames != null)
+            {
+                for (var i = 0; i < formatterNames.Length; i++)
+                {
+                    value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
+                }
+            }
+
+            return value;
+        }
+    }
+}

+ 253 - 0
src/Middleware/Diagnostics/src/Resources.resx

@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="DiagnosticsPageHtml_Information" xml:space="preserve">
+    <value>You are seeing this page because DiagnosticsPageMiddleware was added to your web application.</value>
+  </data>
+  <data name="DiagnosticsPageHtml_TestErrorMessage" xml:space="preserve">
+    <value>Test Error Message</value>
+  </data>
+  <data name="DiagnosticsPageHtml_TestErrorSection" xml:space="preserve">
+    <value>Test Error Page</value>
+  </data>
+  <data name="DiagnosticsPageHtml_Title" xml:space="preserve">
+    <value>Diagnostics Page</value>
+  </data>
+  <data name="ErrorPageHtml_CookiesButton" xml:space="preserve">
+    <value>Cookies</value>
+    <comment>as in http request cookies</comment>
+  </data>
+  <data name="ErrorPageHtml_HeadersButton" xml:space="preserve">
+    <value>Headers</value>
+    <comment>as in http request headers</comment>
+  </data>
+  <data name="ErrorPageHtml_NoCookieData" xml:space="preserve">
+    <value>No cookie data.</value>
+  </data>
+  <data name="ErrorPageHtml_NoHeaderData" xml:space="preserve">
+    <value>No header data.</value>
+  </data>
+  <data name="ErrorPageHtml_NoQueryStringData" xml:space="preserve">
+    <value>No QueryString data.</value>
+  </data>
+  <data name="ErrorPageHtml_QueryButton" xml:space="preserve">
+    <value>Query</value>
+    <comment>as in a request url query string</comment>
+  </data>
+  <data name="ErrorPageHtml_StackButton" xml:space="preserve">
+    <value>Stack</value>
+    <comment>as in an exception's call stack</comment>
+  </data>
+  <data name="ErrorPageHtml_Title" xml:space="preserve">
+    <value>Internal Server Error</value>
+  </data>
+  <data name="ErrorPageHtml_UnhandledException" xml:space="preserve">
+    <value>An unhandled exception occurred while processing the request.</value>
+  </data>
+  <data name="ErrorPageHtml_UnknownLocation" xml:space="preserve">
+    <value>Unknown location</value>
+    <comment>when a stack source code location is not known</comment>
+  </data>
+  <data name="ErrorPageHtml_ValueColumn" xml:space="preserve">
+    <value>Value</value>
+    <comment>as in dictionary value</comment>
+  </data>
+  <data name="ErrorPageHtml_VariableColumn" xml:space="preserve">
+    <value>Variable</value>
+    <comment>as in dictionary key</comment>
+  </data>
+  <data name="Exception_PathMustStartWithSlash" xml:space="preserve">
+    <value>The path must start with a '/'.</value>
+  </data>
+  <data name="RuntimeInfoPage_PackageNameColumnName" xml:space="preserve">
+    <value>Name</value>
+  </data>
+  <data name="RuntimeInfoPage_PackagePathColumnName" xml:space="preserve">
+    <value>Path</value>
+  </data>
+  <data name="RuntimeInfoPage_Packages" xml:space="preserve">
+    <value>Packages:</value>
+  </data>
+  <data name="RuntimeInfoPage_PackagesFail" xml:space="preserve">
+    <value>Could not retrieve the list of loaded packages.</value>
+  </data>
+  <data name="RuntimeInfoPage_PackageVersionColumnName" xml:space="preserve">
+    <value>Version</value>
+  </data>
+  <data name="RuntimeInfoPage_RuntimeVersion" xml:space="preserve">
+    <value>Runtime Version:</value>
+  </data>
+  <data name="RuntimeInfoPage_RuntimeVersionFail" xml:space="preserve">
+    <value>Could not determine the runtime version.</value>
+  </data>
+  <data name="RuntimeInfoPage_Title" xml:space="preserve">
+    <value>Runtime Information</value>
+  </data>
+  <data name="WelcomeHeader" xml:space="preserve">
+    <value>Welcome</value>
+  </data>
+  <data name="WelcomeLearnMicrosoftAspNet" xml:space="preserve">
+    <value>Learn more about the Microsoft ASP.NET Core components</value>
+  </data>
+  <data name="WelcomePageImageText_Browser" xml:space="preserve">
+    <value>Browser</value>
+  </data>
+  <data name="WelcomePageImageText_LearnMore" xml:space="preserve">
+    <value>Learn More</value>
+  </data>
+  <data name="WelcomePageImageText_LightBulb" xml:space="preserve">
+    <value>Light Bulb</value>
+  </data>
+  <data name="WelcomePageImageText_Skyline" xml:space="preserve">
+    <value>Skyline</value>
+  </data>
+  <data name="WelcomeStarted" xml:space="preserve">
+    <value>Your ASP.NET Core application has been successfully started</value>
+  </data>
+  <data name="WelcomeTitle" xml:space="preserve">
+    <value>Your ASP.NET Core application has been successfully started.</value>
+  </data>
+  <data name="ErrorPageHtml_CompilationException" xml:space="preserve">
+    <value>An error occurred during the compilation of a resource required to process this request. Please review the following specific error details and modify your source code appropriately.</value>
+  </data>
+  <data name="RuntimeInfoPage_OperatingSystem" xml:space="preserve">
+    <value>Operating System:</value>
+  </data>
+  <data name="RuntimeInfoPage_RuntimeArchitecture" xml:space="preserve">
+    <value>Runtime Architecture:</value>
+  </data>
+  <data name="RuntimeInfoPage_RuntimeType" xml:space="preserve">
+    <value>Runtime Type:</value>
+  </data>
+  <data name="RuntimeInfoPage_OperatingSystemFail" xml:space="preserve">
+    <value>Could not determine the operating system.</value>
+  </data>
+  <data name="RuntimeInfoPage_RuntimeArchitectureFail" xml:space="preserve">
+    <value>Could not determine the runtime architecture.</value>
+  </data>
+  <data name="RuntimeInfoPage_RuntimeTypeFail" xml:space="preserve">
+    <value>Could not determine the runtime type.</value>
+  </data>
+  <data name="RuntimeInfoPage_Environment" xml:space="preserve">
+    <value>Environment:</value>
+  </data>
+  <data name="ExceptionHandlerOptions_NotConfiguredCorrectly" xml:space="preserve">
+    <value>An error occurred when configuring the exception handler middleware. Either the 'ExceptionHandlingPath' or the 'ExceptionHandler' option must be set in 'UseExceptionHandler()'.</value>
+  </data>
+</root>

+ 24 - 0
src/Middleware/Diagnostics/src/StatusCodePage/StatusCodeContext.cs

@@ -0,0 +1,24 @@
+// 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 Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    public class StatusCodeContext
+    {
+        public StatusCodeContext(HttpContext context, StatusCodePagesOptions options, RequestDelegate next)
+        {
+            HttpContext = context;
+            Options = options;
+            Next = next;
+        }
+
+        public HttpContext HttpContext { get; private set; }
+
+        public StatusCodePagesOptions Options { get; private set; }
+
+        public RequestDelegate Next { get; private set; }
+    }
+}

+ 206 - 0
src/Middleware/Diagnostics/src/StatusCodePage/StatusCodePagesExtensions.cs

@@ -0,0 +1,206 @@
+// 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.Globalization;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Diagnostics;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.AspNetCore.Builder
+{
+    public static class StatusCodePagesExtensions
+    {
+        /// <summary>
+        /// Adds a StatusCodePages middleware with the given options that checks for responses with status codes 
+        /// between 400 and 599 that do not have a body.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="options"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, StatusCodePagesOptions options)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            return app.UseMiddleware<StatusCodePagesMiddleware>(Options.Create(options));
+        }
+
+        /// <summary>
+        /// Adds a StatusCodePages middleware with a default response handler that checks for responses with status codes 
+        /// between 400 and 599 that do not have a body.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            return app.UseMiddleware<StatusCodePagesMiddleware>();
+        }
+
+        /// <summary>
+        /// Adds a StatusCodePages middleware with the specified handler that checks for responses with status codes 
+        /// between 400 and 599 that do not have a body.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="handler"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, Func<StatusCodeContext, Task> handler)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+            if (handler == null)
+            {
+                throw new ArgumentNullException(nameof(handler));
+            }
+
+            return app.UseStatusCodePages(new StatusCodePagesOptions
+            {
+                HandleAsync = handler
+            });
+        }
+
+        /// <summary>
+        /// Adds a StatusCodePages middleware with the specified response body to send. This may include a '{0}' placeholder for the status code.
+        /// The middleware checks for responses with status codes between 400 and 599 that do not have a body.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="contentType"></param>
+        /// <param name="bodyFormat"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, string contentType, string bodyFormat)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            return app.UseStatusCodePages(context =>
+            {
+                var body = string.Format(CultureInfo.InvariantCulture, bodyFormat, context.HttpContext.Response.StatusCode);
+                context.HttpContext.Response.ContentType = contentType;
+                return context.HttpContext.Response.WriteAsync(body);
+            });
+        }
+
+        /// <summary>
+        /// Adds a StatusCodePages middleware to the pipeline. Specifies that responses should be handled by redirecting 
+        /// with the given location URL template. This may include a '{0}' placeholder for the status code. URLs starting 
+        /// with '~' will have PathBase prepended, where any other URL will be used as is.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="locationFormat"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseStatusCodePagesWithRedirects(this IApplicationBuilder app, string locationFormat)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            if (locationFormat.StartsWith("~"))
+            {
+                locationFormat = locationFormat.Substring(1);
+                return app.UseStatusCodePages(context =>
+                {
+                    var location = string.Format(CultureInfo.InvariantCulture, locationFormat, context.HttpContext.Response.StatusCode);
+                    context.HttpContext.Response.Redirect(context.HttpContext.Request.PathBase + location);
+                    return Task.CompletedTask;
+                });
+            }
+            else
+            {
+                return app.UseStatusCodePages(context =>
+                {
+                    var location = string.Format(CultureInfo.InvariantCulture, locationFormat, context.HttpContext.Response.StatusCode);
+                    context.HttpContext.Response.Redirect(location);
+                    return Task.CompletedTask;
+                });
+            }
+        }
+
+        /// <summary>
+        /// Adds a StatusCodePages middleware to the pipeline with the specified alternate middleware pipeline to execute 
+        /// to generate the response body.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="configuration"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, Action<IApplicationBuilder> configuration)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            var builder = app.New();
+            configuration(builder);
+            var tangent = builder.Build();
+            return app.UseStatusCodePages(context => tangent(context.HttpContext));
+        }
+
+        /// <summary>
+        /// Adds a StatusCodePages middleware to the pipeline. Specifies that the response body should be generated by 
+        /// re-executing the request pipeline using an alternate path. This path may contain a '{0}' placeholder of the status code.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="pathFormat"></param>
+        /// <param name="queryFormat"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseStatusCodePagesWithReExecute(
+            this IApplicationBuilder app,
+            string pathFormat,
+            string queryFormat = null)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            return app.UseStatusCodePages(async context =>
+            {
+                var newPath = new PathString(
+                    string.Format(CultureInfo.InvariantCulture, pathFormat, context.HttpContext.Response.StatusCode));
+                var formatedQueryString = queryFormat == null ? null :
+                    string.Format(CultureInfo.InvariantCulture, queryFormat, context.HttpContext.Response.StatusCode);
+                var newQueryString = queryFormat == null ? QueryString.Empty : new QueryString(formatedQueryString);
+
+                var originalPath = context.HttpContext.Request.Path;
+                var originalQueryString = context.HttpContext.Request.QueryString;
+                // Store the original paths so the app can check it.
+                context.HttpContext.Features.Set<IStatusCodeReExecuteFeature>(new StatusCodeReExecuteFeature()
+                {
+                    OriginalPathBase = context.HttpContext.Request.PathBase.Value,
+                    OriginalPath = originalPath.Value,
+                    OriginalQueryString = originalQueryString.HasValue ? originalQueryString.Value : null,
+                });
+
+                context.HttpContext.Request.Path = newPath;
+                context.HttpContext.Request.QueryString = newQueryString;
+                try
+                {
+                    await context.Next(context.HttpContext);
+                }
+                finally
+                {
+                    context.HttpContext.Request.QueryString = originalQueryString;
+                    context.HttpContext.Request.Path = originalPath;
+                    context.HttpContext.Features.Set<IStatusCodeReExecuteFeature>(null);
+                }
+            });
+        }
+    }
+}

+ 13 - 0
src/Middleware/Diagnostics/src/StatusCodePage/StatusCodePagesFeature.cs

@@ -0,0 +1,13 @@
+// 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.
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    /// <summary>
+    /// Represents the Status code pages feature.
+    /// </summary>
+    public class StatusCodePagesFeature : IStatusCodePagesFeature
+    {
+        public bool Enabled { get; set; } = true;
+    }
+}

+ 55 - 0
src/Middleware/Diagnostics/src/StatusCodePage/StatusCodePagesMiddleware.cs

@@ -0,0 +1,55 @@
+// 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.Http;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    public class StatusCodePagesMiddleware
+    {
+        private readonly RequestDelegate _next;
+        private readonly StatusCodePagesOptions _options;
+
+        public StatusCodePagesMiddleware(RequestDelegate next, IOptions<StatusCodePagesOptions> options)
+        {
+            _next = next;
+            _options = options.Value;
+            if (_options.HandleAsync == null)
+            {
+                throw new ArgumentException("Missing options.HandleAsync implementation.");
+            }
+        }
+
+        public async Task Invoke(HttpContext context)
+        {
+            var statusCodeFeature = new StatusCodePagesFeature();
+            context.Features.Set<IStatusCodePagesFeature>(statusCodeFeature);
+
+            await _next(context);
+
+            if (!statusCodeFeature.Enabled)
+            {
+                // Check if the feature is still available because other middleware (such as a web API written in MVC) could
+                // have disabled the feature to prevent HTML status code responses from showing up to an API client.
+                return;
+            }
+
+            // Do nothing if a response body has already been provided.
+            if (context.Response.HasStarted
+                || context.Response.StatusCode < 400
+                || context.Response.StatusCode >= 600
+                || context.Response.ContentLength.HasValue
+                || !string.IsNullOrEmpty(context.Response.ContentType))
+            {
+                return;
+            }
+
+            var statusCodeContext = new StatusCodeContext(context, _options, _next);
+            await _options.HandleAsync(statusCodeContext);
+        }
+    }
+}

+ 48 - 0
src/Middleware/Diagnostics/src/StatusCodePage/StatusCodePagesOptions.cs

@@ -0,0 +1,48 @@
+// 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.Globalization;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Diagnostics;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.WebUtilities;
+
+namespace Microsoft.AspNetCore.Builder
+{
+    /// <summary>
+    /// Options for StatusCodePagesMiddleware.
+    /// </summary>
+    public class StatusCodePagesOptions
+    {
+        public StatusCodePagesOptions()
+        {
+            HandleAsync = context =>
+            {
+                // TODO: Render with a pre-compiled html razor view.
+                var statusCode = context.HttpContext.Response.StatusCode;
+
+                var body = BuildResponseBody(statusCode);
+
+                context.HttpContext.Response.ContentType = "text/plain";
+                return context.HttpContext.Response.WriteAsync(body);
+            };
+        }
+
+        private string BuildResponseBody(int httpStatusCode)
+        {
+            // Note the 500 spaces are to work around an IE 'feature'
+            var internetExplorerWorkaround = new string(' ', 500);
+
+            var reasonPhrase = ReasonPhrases.GetReasonPhrase(httpStatusCode);
+
+            return string.Format(CultureInfo.InvariantCulture, "Status Code: {0}{1}{2}{3}",
+                                                                    httpStatusCode,
+                                                                    string.IsNullOrWhiteSpace(reasonPhrase) ? "" : "; ",
+                                                                    reasonPhrase,
+                                                                    internetExplorerWorkaround);
+        }
+
+        public Func<StatusCodeContext, Task> HandleAsync { get; set; }
+    }
+}

+ 14 - 0
src/Middleware/Diagnostics/src/StatusCodePage/StatusCodeReExecuteFeature.cs

@@ -0,0 +1,14 @@
+// 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.
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    public class StatusCodeReExecuteFeature : IStatusCodeReExecuteFeature
+    {
+        public string OriginalPath { get; set; }
+
+        public string OriginalPathBase { get; set; }
+
+        public string OriginalQueryString { get; set; }
+    }
+}

+ 373 - 0
src/Middleware/Diagnostics/src/WelcomePage/Views/Obsolete/WelcomePage.cs

@@ -0,0 +1,373 @@
+namespace Microsoft.AspNetCore.Diagnostics.Views
+{
+#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;
+    
+    [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
+        public WelcomePage()
+        {
+        }
+
+        #pragma warning disable 1998
+        public override async Task ExecuteAsync()
+        {
+#line 3 "WelcomePage.cshtml"
+  
+    Response.ContentType = "text/html";
+
+#line default
+#line hidden
+
+            WriteLiteral("<!DOCTYPE html>\r\n<html");
+            BeginWriteAttribute("lang", " lang=\"", 126, "\"", 208, 1);
+#line 7 "WelcomePage.cshtml"
+WriteAttributeValue("", 133, System.Globalization.CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, 133, 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=\"", 7503, "\"", 7571, 1);
+#line 169 "WelcomePage.cshtml"
+WriteAttributeValue("", 7530, Resources.WelcomePageImageText_LightBulb, 7530, 41, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            BeginWriteAttribute("title", " title=\"", 7572, "\"", 7621, 1);
+#line 169 "WelcomePage.cshtml"
+WriteAttributeValue("", 7580, Resources.WelcomePageImageText_LightBulb, 7580, 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=\"", 16709, "\"", 16776, 1);
+#line 172 "WelcomePage.cshtml"
+WriteAttributeValue("", 16737, Resources.WelcomePageImageText_Browser, 16737, 39, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            BeginWriteAttribute("title", " title=\"", 16777, "\"", 16824, 1);
+#line 172 "WelcomePage.cshtml"
+WriteAttributeValue("", 16785, Resources.WelcomePageImageText_Browser, 16785, 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=\"", 23246, "\"", 23314, 1);
+#line 176 "WelcomePage.cshtml"
+WriteAttributeValue("", 23273, Resources.WelcomePageImageText_LightBulb, 23273, 41, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            BeginWriteAttribute("title", " title=\"", 23315, "\"", 23364, 1);
+#line 176 "WelcomePage.cshtml"
+WriteAttributeValue("", 23323, Resources.WelcomePageImageText_LightBulb, 23323, 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=\"", 31214, "\"", 31283, 1);
+#line 179 "WelcomePage.cshtml"
+WriteAttributeValue("", 31242, Resources.WelcomePageImageText_LightBulb, 31242, 41, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            BeginWriteAttribute("title", " title=\"", 31284, "\"", 31333, 1);
+#line 179 "WelcomePage.cshtml"
+WriteAttributeValue("", 31292, Resources.WelcomePageImageText_LightBulb, 31292, 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=\"", 46181, "\"", 46247, 1);
+#line 182 "WelcomePage.cshtml"
+WriteAttributeValue("", 46208, Resources.WelcomePageImageText_Skyline, 46208, 39, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            BeginWriteAttribute("title", " title=\"", 46248, "\"", 46295, 1);
+#line 182 "WelcomePage.cshtml"
+WriteAttributeValue("", 46256, Resources.WelcomePageImageText_Skyline, 46256, 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=\"", 49127, "\"", 49191, 1);
+#line 191 "WelcomePage.cshtml"
+WriteAttributeValue("", 49150, Resources.WelcomePageImageText_LearnMore, 49150, 41, false);
+
+#line default
+#line hidden
+            EndWriteAttribute();
+            BeginWriteAttribute("title", " title=\"", 49192, "\"", 49241, 1);
+#line 191 "WelcomePage.cshtml"
+WriteAttributeValue("", 49200, Resources.WelcomePageImageText_LearnMore, 49200, 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
+    }
+}

File diff suppressed because it is too large
+ 167 - 0
src/Middleware/Diagnostics/src/WelcomePage/Views/Obsolete/WelcomePage.cshtml


+ 366 - 0
src/Middleware/Diagnostics/src/WelcomePage/Views/WelcomePage.Designer.cs

@@ -0,0 +1,366 @@
+// <auto-generated/>
+#pragma warning disable 1591
+namespace Microsoft.AspNetCore.Diagnostics.RazorViews
+{
+    #line hidden
+#line 1 "WelcomePage.cshtml"
+using System;
+
+#line default
+#line hidden
+    using System.Threading.Tasks;
+#line 2 "WelcomePage.cshtml"
+using Microsoft.AspNetCore.Diagnostics;
+
+#line default
+#line hidden
+    internal class WelcomePage : Microsoft.Extensions.RazorViews.BaseView
+    {
+        #pragma warning disable 1998
+        public async override global::System.Threading.Tasks.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>\r\n    <style type=\"text/css\">\r\n        ");
+            WriteLiteral(@"@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 {
+                    color: #fff;
+                    text-decorat");
+            WriteLiteral(@"ion: 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 {
+                        position: absolute;
+              ");
+            WriteLiteral(@"          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: absolute;
+                top: 40px;
+             ");
+            WriteLiteral(@"   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"">
+                <img src=""data:image/png;base64,iVBORw");
+            WriteLiteral(@"0KGgoAAAANSUhEUgAAARIAAAESCAYAAAAxN1ojAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAACKhJREFUeNrs3TFPG0kYgOE1kou4IIVTUITiXJAiFFxBk/8vGopQQBEKKFyci7jAhRsX3E4YB3I5Asva3p2Z55EspJNOOq/3Xn8zu7arCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADI1MAhILi/v9+v/wwb/murwWCwcPQQknJCMa7/jOLj3X/+bsKqfiye/F3Gx6KOzcorICSkGY0P9WM/hmK/4/+kZYxLeHwXFyGh3+EYx0cK1lGZh4ewCAm7D0fYyziIjxCOYQZPaxajMqujsvQqCwnbj8dB5k83TCtTURESNheQdTgOCz0EsxiUqbNBSGg+fUzqx8dqc1dVUreKU8qtKUVI+HNAQjSOCp4+mkwpN3VQ5g6FkPAYkHGMh4A0E0LyTVCEpPSAhPs7jqt0LtkKCkJiCVNEUC7dti8kuQdkvYl65GhsVdiUvXKTm5DkGJFwCfdz5SrMroSIXNcxuXEohCSXZcxJZR+kK2GZ89VyR0hSjsh6GTN0NDp3EycUyx0hMYVgOhGSMiJyECNiCumvMJl8cxiEpI8BCeEIm6ku6aYhXCo+t9QRkr4tZU6r7r9AiGZCRM4sdYSkDxEZx4hYyqTrwqeLhaTLiIRlzIkjkYVpHZMLh0FIdh2REBD7IXmZxenEvomQbD0gNlXzFvZLzsRESLYdkS+VTdUSYnLuC5SERERoyxUdIRERxERIRAQxERIRQUzKsucQiAgvCufC3/GcQEga+SwiPBHOhS9iIiRNphE3m/FcTE4dBiF5TUT8LAR/Mo5vNAjJsxEJH8BzkvCSw/iGg5D8FpGRsZUGTuIbD0LyMyLDylcB0NypzVchecoVGt5iaIoVkvU0Er5j1XqXtwqbr5+EpOyIrL/tHdo4Kn2/pPSJxLe9s7Fzqe");
+            WriteLiteral(@"T9kmJDEn+8yq47m7L+YXghKWxJ44e82bRJqUucUicSSxoscYSk1TRyYEnDlpc4EyHJOyLrL26GbTqKy2chyXUNG98xYBfLZyHJcBqxwcoujUvaeC1pIhERdu1YSPKaRsLnaNwGz67tl/J1A6VMJMfOaUzCQtJmGgnrVJd76cqohKmkhInEkgZTiZC0mkZGQoKpREi8E2AyFpJOp5GhaYQeyfq+kpwnkolzF1OJkLT10XlL30KS6yeDswxJ/ISvz9RgKhGSVg6cr/TUX0KSxjRik5U+G8WPbAiJaQQsb4QEnKNC8sKyRkiwvBESpcfyRkiEBIo7V3MLia8LIKXlTTb3OmUTkvg5Br9Vg6lESFr54LzEBC0kXhSEREi8KNDQMJfLwFmEpNQfbsaSXEi8GBCYSLwY0Np7IREScO5mFBJfYkSyctjj2/MigDdCE4lpBOewkHgRIP19khxC8s55SOKS/4yYiQS6Z7PVRAKYSKAHUv/MzZ6XEHoh6X2SpEOS4++DgJCoOBS5RLe0ASEREkBIACEBEBJASAAhAYQEQEgAIQGEBHi0EhIHH9q6E5KODAaDhfMPhASwtPECgOk6j5BY3oCQmEgoXvJvhiYS8GYoJLWl85DEzYVESMBEYmkDnbtL/QkkH5LBYLAyleDNUEi8EJRsGd8MhURIoOxzN5eQfHc+kqh5Dk/CRALdusvhSWQRkrjGFBNSPHdNJJY3YFmTW0jmzksSMxMSIQFTdG4hifskYkIqljl9w19u35A2c35ighYSIaEUWZ2rWYWkHhXDZ25cBqbvVvW5KiQ9N3WeYhoREi8SQiIkvVjeuHpDXy1zW9bkOpFY3mAaEZKNTCUhJL5dnj66FRJTCbQxj0tvIVF+eLObXJ9YtiGJ5XcFh77IcpO1hIkk63cAknOd85PLOiTxS2NcCqZrq3gBQEgS9s15TMey36/LPiSmErqeRkpYYu8V8mKaSuhsGsnhd2uExFRCd8KVmiLexPYKelFNJezadSlPtJiQxKnE3a7syi");
+            WriteLiteral(@"L3KzWlTiTrdwifwWEXLkt6skWFJN7t6tZ5tm2ayw9fCcnzMQl7Jb6OkW0JE+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+H3jdYGq0j8XAimTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHL0rwADANq3ok68n5URAAAAAElFTkSuQm");
+            WriteLiteral("CC\"");
+            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
+    }
+}
+#pragma warning restore 1591

File diff suppressed because it is too large
+ 167 - 0
src/Middleware/Diagnostics/src/WelcomePage/Views/WelcomePage.cshtml


+ 90 - 0
src/Middleware/Diagnostics/src/WelcomePage/WelcomePageExtensions.cs

@@ -0,0 +1,90 @@
+// 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 Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Diagnostics;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.AspNetCore.Builder
+{
+    /// <summary>
+    /// IApplicationBuilder extensions for the WelcomePageMiddleware.
+    /// </summary>
+    public static class WelcomePageExtensions
+    {
+        /// <summary>
+        /// Adds the WelcomePageMiddleware to the pipeline with the given options.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="options"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseWelcomePage(this IApplicationBuilder app, WelcomePageOptions options)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            return app.UseMiddleware<WelcomePageMiddleware>(Options.Create(options));
+        }
+
+        /// <summary>
+        /// Adds the WelcomePageMiddleware to the pipeline with the given path.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="path"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseWelcomePage(this IApplicationBuilder app, PathString path)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            return app.UseWelcomePage(new WelcomePageOptions
+            {
+                Path = path
+            });
+        }
+
+        /// <summary>
+        /// Adds the WelcomePageMiddleware to the pipeline with the given path.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <param name="path"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseWelcomePage(this IApplicationBuilder app, string path)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            return app.UseWelcomePage(new WelcomePageOptions
+            {
+                Path = new PathString(path)
+            });
+        }
+
+        /// <summary>
+        /// Adds the WelcomePageMiddleware to the pipeline.
+        /// </summary>
+        /// <param name="app"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseWelcomePage(this IApplicationBuilder app)
+        {
+            if (app == null)
+            {
+                throw new ArgumentNullException(nameof(app));
+            }
+
+            return app.UseMiddleware<WelcomePageMiddleware>();
+        }
+    }
+}

+ 60 - 0
src/Middleware/Diagnostics/src/WelcomePage/WelcomePageMiddleware.cs

@@ -0,0 +1,60 @@
+// 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.RazorViews;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.AspNetCore.Diagnostics
+{
+    /// <summary>
+    /// This middleware provides a default web page for new applications.
+    /// </summary>
+    public class WelcomePageMiddleware
+    {
+        private readonly RequestDelegate _next;
+        private readonly WelcomePageOptions _options;
+
+        /// <summary>
+        /// Creates a default web page for new applications.
+        /// </summary>
+        /// <param name="next"></param>
+        /// <param name="options"></param>
+        public WelcomePageMiddleware(RequestDelegate next, IOptions<WelcomePageOptions> options)
+        {
+            if (next == null)
+            {
+                throw new ArgumentNullException(nameof(next));
+            }
+
+            if (options == null)
+            {
+                throw new ArgumentNullException(nameof(options));
+            }
+
+            _next = next;
+            _options = options.Value;
+        }
+
+        /// <summary>
+        /// Process an individual request.
+        /// </summary>
+        /// <param name="context">The <see cref="HttpContext"/>.</param>
+        /// <returns></returns>
+        public Task Invoke(HttpContext context)
+        {
+            HttpRequest request = context.Request;
+            if (!_options.Path.HasValue || _options.Path == request.Path)
+            {
+                // Dynamically generated for LOC.
+                var welcomePage = new WelcomePage();
+                return welcomePage.ExecuteAsync(context);
+            }
+
+            return _next(context);
+        }
+    }
+}

+ 19 - 0
src/Middleware/Diagnostics/src/WelcomePage/WelcomePageOptions.cs

@@ -0,0 +1,19 @@
+// 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 Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.Builder
+{
+    /// <summary>
+    /// Options for the WelcomePageMiddleware.
+    /// </summary>
+    public class WelcomePageOptions
+    {
+        /// <summary>
+        /// Specifies which requests paths will be responded to. Exact matches only. Leave null to handle all requests.
+        /// </summary>
+        public PathString Path { get; set; }
+    }
+}

+ 32 - 0
src/Middleware/Diagnostics/src/_gruntfile.js

@@ -0,0 +1,32 @@
+
+module.exports = function (grunt) {
+
+    grunt.initConfig({
+        jshint: {
+            src: [
+                "**/*.js",
+                "!node_modules/**/*.js"
+            ],
+            options: {
+                // Options are documented at https://github.com/gruntjs/grunt-contrib-jshint#options
+                jshintrc: ".jshintrc"
+            }
+        },
+        csslint: {
+            src: [
+                "**/*.css",
+                "!node_modules/**/*.css"
+            ],
+            options: {
+                // Options are documented at https://github.com/gruntjs/grunt-contrib-csslint#options
+                csslintrc: ".csslintrc"
+            }
+        }
+    });
+
+    grunt.loadNpmTasks("grunt-contrib-jshint");
+    grunt.loadNpmTasks("grunt-contrib-csslint");
+
+
+    grunt.registerTask("default", ["jshint", "csslint"]);
+};

+ 1 - 0
src/Middleware/Diagnostics/src/_gruntfile.readme

@@ -0,0 +1 @@
+If js or css files changes, rename _gruntfile.js to gruntfile.js, _package.json to package.json, and run build.

+ 12 - 0
src/Middleware/Diagnostics/src/_package.json

@@ -0,0 +1,12 @@
+{
+  "name": "DiagnosticsPages",
+  "version": "0.0.0",
+  "description": "",
+  "private": true,
+  "devDependencies": {
+    "grunt": "~0.4.4",
+    "grunt-cli": "~0.1.13",
+    "grunt-contrib-csslint": "~0.2.0",
+    "grunt-contrib-jshint": "~0.10.0"
+  }
+}

+ 1543 - 0
src/Middleware/Diagnostics/src/baseline.netcore.json

@@ -0,0 +1,1543 @@
+{
+  "AssemblyIdentity": "Microsoft.AspNetCore.Diagnostics, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
+  "Types": [
+    {
+      "Name": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_Prefix",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Value",
+          "Parameters": [],
+          "ReturnType": "System.Object",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Literal",
+          "Parameters": [],
+          "ReturnType": "System.Boolean",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "FromTuple",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Tuple<System.String, System.Object, System.Boolean>"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue",
+          "Static": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "FromTuple",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Tuple<System.String, System.String, System.Boolean>"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue",
+          "Static": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "op_Implicit",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Tuple<System.String, System.Object, System.Boolean>"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue",
+          "Static": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "prefix",
+              "Type": "System.String"
+            },
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            },
+            {
+              "Name": "literal",
+              "Type": "System.Boolean"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "Abstract": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_Context",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.HttpContext",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Request",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.HttpRequest",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Response",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.HttpResponse",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Output",
+          "Parameters": [],
+          "ReturnType": "System.IO.StreamWriter",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_HtmlEncoder",
+          "Parameters": [],
+          "ReturnType": "System.Text.Encodings.Web.HtmlEncoder",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_HtmlEncoder",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Text.Encodings.Web.HtmlEncoder"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_UrlEncoder",
+          "Parameters": [],
+          "ReturnType": "System.Text.Encodings.Web.UrlEncoder",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_UrlEncoder",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Text.Encodings.Web.UrlEncoder"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_JavaScriptEncoder",
+          "Parameters": [],
+          "ReturnType": "System.Text.Encodings.Web.JavaScriptEncoder",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_JavaScriptEncoder",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Text.Encodings.Web.JavaScriptEncoder"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "ExecuteAsync",
+          "Parameters": [
+            {
+              "Name": "context",
+              "Type": "Microsoft.AspNetCore.Http.HttpContext"
+            }
+          ],
+          "ReturnType": "System.Threading.Tasks.Task",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "ExecuteAsync",
+          "Parameters": [],
+          "ReturnType": "System.Threading.Tasks.Task",
+          "Virtual": true,
+          "Abstract": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteLiteral",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteLiteral",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteAttributeValue",
+          "Parameters": [
+            {
+              "Name": "thingy",
+              "Type": "System.String"
+            },
+            {
+              "Name": "startPostion",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            },
+            {
+              "Name": "endValue",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "dealyo",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "yesno",
+              "Type": "System.Boolean"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "BeginWriteAttribute",
+          "Parameters": [
+            {
+              "Name": "name",
+              "Type": "System.String"
+            },
+            {
+              "Name": "begining",
+              "Type": "System.String"
+            },
+            {
+              "Name": "startPosition",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "ending",
+              "Type": "System.String"
+            },
+            {
+              "Name": "endPosition",
+              "Type": "System.Int32"
+            },
+            {
+              "Name": "thingy",
+              "Type": "System.Int32"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "EndWriteAttribute",
+          "Parameters": [],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteAttributeTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            },
+            {
+              "Name": "name",
+              "Type": "System.String"
+            },
+            {
+              "Name": "leader",
+              "Type": "System.String"
+            },
+            {
+              "Name": "trailer",
+              "Type": "System.String"
+            },
+            {
+              "Name": "values",
+              "Type": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue[]",
+              "IsParams": true
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "Write",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "Write",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "Write",
+          "Parameters": [
+            {
+              "Name": "result",
+              "Type": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.HelperResult"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            },
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            },
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteLiteralTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            },
+            {
+              "Name": "value",
+              "Type": "System.Object"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteLiteralTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            },
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "HtmlEncodeAndReplaceLineBreaks",
+          "Parameters": [
+            {
+              "Name": "input",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.String",
+          "Visibility": "Protected",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Protected",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.HelperResult",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_WriteAction",
+          "Parameters": [],
+          "ReturnType": "System.Action<System.IO.TextWriter>",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "WriteTo",
+          "Parameters": [
+            {
+              "Name": "writer",
+              "Type": "System.IO.TextWriter"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "action",
+              "Type": "System.Action<System.IO.TextWriter>"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "Invoke",
+          "Parameters": [
+            {
+              "Name": "context",
+              "Type": "Microsoft.AspNetCore.Http.HttpContext"
+            }
+          ],
+          "ReturnType": "System.Threading.Tasks.Task",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "next",
+              "Type": "Microsoft.AspNetCore.Http.RequestDelegate"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Builder.DeveloperExceptionPageOptions>"
+            },
+            {
+              "Name": "loggerFactory",
+              "Type": "Microsoft.Extensions.Logging.ILoggerFactory"
+            },
+            {
+              "Name": "hostingEnvironment",
+              "Type": "Microsoft.AspNetCore.Hosting.IHostingEnvironment"
+            },
+            {
+              "Name": "diagnosticSource",
+              "Type": "System.Diagnostics.DiagnosticSource"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.ExceptionHandlerFeature",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [
+        "Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature"
+      ],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_Error",
+          "Parameters": [],
+          "ReturnType": "System.Exception",
+          "Sealed": true,
+          "Virtual": true,
+          "ImplementedInterface": "Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_Error",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Exception"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Path",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Sealed": true,
+          "Virtual": true,
+          "ImplementedInterface": "Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_Path",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "Invoke",
+          "Parameters": [
+            {
+              "Name": "context",
+              "Type": "Microsoft.AspNetCore.Http.HttpContext"
+            }
+          ],
+          "ReturnType": "System.Threading.Tasks.Task",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "next",
+              "Type": "Microsoft.AspNetCore.Http.RequestDelegate"
+            },
+            {
+              "Name": "loggerFactory",
+              "Type": "Microsoft.Extensions.Logging.ILoggerFactory"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Builder.ExceptionHandlerOptions>"
+            },
+            {
+              "Name": "diagnosticSource",
+              "Type": "System.Diagnostics.DiagnosticSource"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.StatusCodeContext",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_HttpContext",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.HttpContext",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Options",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Builder.StatusCodePagesOptions",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_Next",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.RequestDelegate",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "context",
+              "Type": "Microsoft.AspNetCore.Http.HttpContext"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.AspNetCore.Builder.StatusCodePagesOptions"
+            },
+            {
+              "Name": "next",
+              "Type": "Microsoft.AspNetCore.Http.RequestDelegate"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.StatusCodePagesFeature",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [
+        "Microsoft.AspNetCore.Diagnostics.IStatusCodePagesFeature"
+      ],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_Enabled",
+          "Parameters": [],
+          "ReturnType": "System.Boolean",
+          "Sealed": true,
+          "Virtual": true,
+          "ImplementedInterface": "Microsoft.AspNetCore.Diagnostics.IStatusCodePagesFeature",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_Enabled",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Boolean"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Sealed": true,
+          "Virtual": true,
+          "ImplementedInterface": "Microsoft.AspNetCore.Diagnostics.IStatusCodePagesFeature",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "Invoke",
+          "Parameters": [
+            {
+              "Name": "context",
+              "Type": "Microsoft.AspNetCore.Http.HttpContext"
+            }
+          ],
+          "ReturnType": "System.Threading.Tasks.Task",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "next",
+              "Type": "Microsoft.AspNetCore.Http.RequestDelegate"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Builder.StatusCodePagesOptions>"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.StatusCodeReExecuteFeature",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [
+        "Microsoft.AspNetCore.Diagnostics.IStatusCodeReExecuteFeature"
+      ],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_OriginalPath",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Sealed": true,
+          "Virtual": true,
+          "ImplementedInterface": "Microsoft.AspNetCore.Diagnostics.IStatusCodeReExecuteFeature",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_OriginalPath",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Sealed": true,
+          "Virtual": true,
+          "ImplementedInterface": "Microsoft.AspNetCore.Diagnostics.IStatusCodeReExecuteFeature",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_OriginalPathBase",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Sealed": true,
+          "Virtual": true,
+          "ImplementedInterface": "Microsoft.AspNetCore.Diagnostics.IStatusCodeReExecuteFeature",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_OriginalPathBase",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Sealed": true,
+          "Virtual": true,
+          "ImplementedInterface": "Microsoft.AspNetCore.Diagnostics.IStatusCodeReExecuteFeature",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_OriginalQueryString",
+          "Parameters": [],
+          "ReturnType": "System.String",
+          "Sealed": true,
+          "Virtual": true,
+          "ImplementedInterface": "Microsoft.AspNetCore.Diagnostics.IStatusCodeReExecuteFeature",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_OriginalQueryString",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Sealed": true,
+          "Virtual": true,
+          "ImplementedInterface": "Microsoft.AspNetCore.Diagnostics.IStatusCodeReExecuteFeature",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.WelcomePageMiddleware",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "Invoke",
+          "Parameters": [
+            {
+              "Name": "context",
+              "Type": "Microsoft.AspNetCore.Http.HttpContext"
+            }
+          ],
+          "ReturnType": "System.Threading.Tasks.Task",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [
+            {
+              "Name": "next",
+              "Type": "Microsoft.AspNetCore.Http.RequestDelegate"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Builder.WelcomePageOptions>"
+            }
+          ],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Diagnostics.Views.WelcomePage",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "BaseType": "Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "ExecuteAsync",
+          "Parameters": [],
+          "ReturnType": "System.Threading.Tasks.Task",
+          "Virtual": true,
+          "Override": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.DeveloperExceptionPageExtensions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "Abstract": true,
+      "Static": true,
+      "Sealed": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "UseDeveloperExceptionPage",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseDeveloperExceptionPage",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.AspNetCore.Builder.DeveloperExceptionPageOptions"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.DeveloperExceptionPageOptions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_SourceCodeLineCount",
+          "Parameters": [],
+          "ReturnType": "System.Int32",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_SourceCodeLineCount",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Int32"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_FileProvider",
+          "Parameters": [],
+          "ReturnType": "Microsoft.Extensions.FileProviders.IFileProvider",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_FileProvider",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "Microsoft.Extensions.FileProviders.IFileProvider"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "Abstract": true,
+      "Static": true,
+      "Sealed": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "UseExceptionHandler",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseExceptionHandler",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "errorHandlingPath",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseExceptionHandler",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "configure",
+              "Type": "System.Action<Microsoft.AspNetCore.Builder.IApplicationBuilder>"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseExceptionHandler",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.AspNetCore.Builder.ExceptionHandlerOptions"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.ExceptionHandlerOptions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_ExceptionHandlingPath",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.PathString",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_ExceptionHandlingPath",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "Microsoft.AspNetCore.Http.PathString"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "get_ExceptionHandler",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.RequestDelegate",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_ExceptionHandler",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "Microsoft.AspNetCore.Http.RequestDelegate"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.StatusCodePagesExtensions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "Abstract": true,
+      "Static": true,
+      "Sealed": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "UseStatusCodePages",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.AspNetCore.Builder.StatusCodePagesOptions"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseStatusCodePages",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseStatusCodePages",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "handler",
+              "Type": "System.Func<Microsoft.AspNetCore.Diagnostics.StatusCodeContext, System.Threading.Tasks.Task>"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseStatusCodePages",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "contentType",
+              "Type": "System.String"
+            },
+            {
+              "Name": "bodyFormat",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseStatusCodePagesWithRedirects",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "locationFormat",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseStatusCodePages",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "configuration",
+              "Type": "System.Action<Microsoft.AspNetCore.Builder.IApplicationBuilder>"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseStatusCodePagesWithReExecute",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "pathFormat",
+              "Type": "System.String"
+            },
+            {
+              "Name": "queryFormat",
+              "Type": "System.String",
+              "DefaultValue": "null"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.StatusCodePagesOptions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_HandleAsync",
+          "Parameters": [],
+          "ReturnType": "System.Func<Microsoft.AspNetCore.Diagnostics.StatusCodeContext, System.Threading.Tasks.Task>",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_HandleAsync",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "System.Func<Microsoft.AspNetCore.Diagnostics.StatusCodeContext, System.Threading.Tasks.Task>"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.WelcomePageExtensions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "Abstract": true,
+      "Static": true,
+      "Sealed": true,
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "UseWelcomePage",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "options",
+              "Type": "Microsoft.AspNetCore.Builder.WelcomePageOptions"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseWelcomePage",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "path",
+              "Type": "Microsoft.AspNetCore.Http.PathString"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseWelcomePage",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            },
+            {
+              "Name": "path",
+              "Type": "System.String"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "UseWelcomePage",
+          "Parameters": [
+            {
+              "Name": "app",
+              "Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
+            }
+          ],
+          "ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
+          "Static": true,
+          "Extension": true,
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    },
+    {
+      "Name": "Microsoft.AspNetCore.Builder.WelcomePageOptions",
+      "Visibility": "Public",
+      "Kind": "Class",
+      "ImplementedInterfaces": [],
+      "Members": [
+        {
+          "Kind": "Method",
+          "Name": "get_Path",
+          "Parameters": [],
+          "ReturnType": "Microsoft.AspNetCore.Http.PathString",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Method",
+          "Name": "set_Path",
+          "Parameters": [
+            {
+              "Name": "value",
+              "Type": "Microsoft.AspNetCore.Http.PathString"
+            }
+          ],
+          "ReturnType": "System.Void",
+          "Visibility": "Public",
+          "GenericParameter": []
+        },
+        {
+          "Kind": "Constructor",
+          "Name": ".ctor",
+          "Parameters": [],
+          "Visibility": "Public",
+          "GenericParameter": []
+        }
+      ],
+      "GenericParameters": []
+    }
+  ]
+}

+ 38 - 0
src/Middleware/Diagnostics/test/FunctionalTests/DatabaseErrorPageSampleTest.cs

@@ -0,0 +1,38 @@
+// 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.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Testing.xunit;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Diagnostics.FunctionalTests
+{
+    public class DatabaseErrorPageSampleTest : IClassFixture<TestFixture<DatabaseErrorPageSample.Startup>>
+    {
+        public DatabaseErrorPageSampleTest(TestFixture<DatabaseErrorPageSample.Startup> fixture)
+        {
+            Client = fixture.Client;
+        }
+
+        public HttpClient Client { get; }
+
+        [ConditionalFact]
+        [OSSkipCondition(OperatingSystems.Linux)]
+        [OSSkipCondition(OperatingSystems.MacOSX)]
+        public async Task DatabaseErrorPage_ShowsError()
+        {
+            // Arrange
+            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/");
+
+            // Act
+            var response = await Client.SendAsync(request);
+
+            // Assert
+            var body = await response.Content.ReadAsStringAsync();
+            Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
+            Assert.Contains("In Visual Studio, use the Package Manager Console to scaffold a new migration and apply it to the database:", body);
+        }
+    }
+}

+ 36 - 0
src/Middleware/Diagnostics/test/FunctionalTests/DeveloperExceptionPageSampleTest.cs

@@ -0,0 +1,36 @@
+// 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.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Diagnostics.FunctionalTests
+{
+    public class DeveloperExceptionPageSampleTest : IClassFixture<TestFixture<DeveloperExceptionPageSample.Startup>>
+    {
+        public DeveloperExceptionPageSampleTest(TestFixture<DeveloperExceptionPageSample.Startup> fixture)
+        {
+            Client = fixture.Client;
+        }
+
+        public HttpClient Client { get; }
+
+
+        [Fact]
+        public async Task DeveloperExceptionPage_ShowsError()
+        {
+            // Arrange
+            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/");
+
+            // Act
+            var response = await Client.SendAsync(request);
+
+            // Assert
+            var body = await response.Content.ReadAsStringAsync();
+            Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
+            Assert.Contains("Exception: Demonstration exception.", body);
+        }
+    }
+}

+ 25 - 0
src/Middleware/Diagnostics/test/FunctionalTests/Diagnostics.FunctionalTests.csproj

@@ -0,0 +1,25 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
+    <SignAssembly>false</SignAssembly>
+    <PublicSign>false</PublicSign>
+    <!-- Mitigation for long path issues -->
+    <AssemblyName>Diagnostics.FunctionalTests</AssemblyName>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\testassets\DatabaseErrorPageSample\DatabaseErrorPageSample.csproj" />
+    <ProjectReference Include="..\testassets\DeveloperExceptionPageSample\DeveloperExceptionPageSample.csproj" />
+    <ProjectReference Include="..\testassets\ExceptionHandlerSample\ExceptionHandlerSample.csproj" />
+    <ProjectReference Include="..\testassets\StatusCodePagesSample\StatusCodePagesSample.csproj" />
+    <ProjectReference Include="..\testassets\WelcomePageSample\WelcomePageSample.csproj" />
+    <ProjectReference Include="..\..\..\MiddlewareAnalysis\samples\MiddlewareAnalysisSample\MiddlewareAnalysisSample.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
+    <Reference Include="Microsoft.AspNetCore.TestHost" />
+  </ItemGroup>
+
+</Project>

+ 35 - 0
src/Middleware/Diagnostics/test/FunctionalTests/ExceptionHandlerSampleTest.cs

@@ -0,0 +1,35 @@
+// 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.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Diagnostics.FunctionalTests
+{
+    public class ExceptionHandlerSampleTest : IClassFixture<TestFixture<ExceptionHandlerSample.Startup>>
+    {
+        public ExceptionHandlerSampleTest(TestFixture<ExceptionHandlerSample.Startup> fixture)
+        {
+            Client = fixture.Client;
+        }
+
+        public HttpClient Client { get; }
+
+        [Fact]
+        public async Task ExceptionHandlerPage_ShowsError()
+        {
+            // Arrange
+            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/throw");
+
+            // Act
+            var response = await Client.SendAsync(request);
+
+            // Assert
+            var body = await response.Content.ReadAsStringAsync();
+            Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
+            Assert.Contains("we encountered an un-expected issue with your application.", body);
+        }
+    }
+}

+ 34 - 0
src/Middleware/Diagnostics/test/FunctionalTests/MiddlewareAnalysisSampleTest.cs

@@ -0,0 +1,34 @@
+// 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.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Diagnostics.FunctionalTests
+{
+    public class MiddlewareAnalysisSampleTest : IClassFixture<TestFixture<MiddlewareAnaysisSample.Startup>>
+    {
+        public MiddlewareAnalysisSampleTest(TestFixture<MiddlewareAnaysisSample.Startup> fixture)
+        {
+            Client = fixture.Client;
+        }
+
+        public HttpClient Client { get; }
+
+        [Fact]
+        public async Task MiddlewareAnalysisPage_ShowsAnalysis()
+        {
+            // Arrange
+            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/");
+
+            // Act
+            var response = await Client.SendAsync(request);
+
+            // Assert
+            var body = await response.Content.ReadAsStringAsync();
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+        }
+    }
+}

+ 76 - 0
src/Middleware/Diagnostics/test/FunctionalTests/StatusCodeSampleTest.cs

@@ -0,0 +1,76 @@
+// 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.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.WebUtilities;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Diagnostics.FunctionalTests
+{
+    public class StatusCodeSampleTest : IClassFixture<TestFixture<StatusCodePagesSample.Startup>>
+    {
+        public StatusCodeSampleTest(TestFixture<StatusCodePagesSample.Startup> fixture)
+        {
+            Client = fixture.Client;
+        }
+
+        public HttpClient Client { get; }
+
+        [Fact]
+        public async Task StatusCodePage_ShowsError()
+        {
+            // Arrange
+            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/errors/417");
+
+            // Act
+            var response = await Client.SendAsync(request);
+
+            // Assert
+            var body = await response.Content.ReadAsStringAsync();
+            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+            Assert.Contains("Status Code: 417", body);
+        }
+
+        [Fact]
+        public async Task StatusCodePageOptions_ExcludesSemicolon_WhenReasonPhrase_IsUnknown()
+        {
+            //Arrange
+            var httpStatusCode = 541;
+            var request = new HttpRequestMessage(HttpMethod.Get, $"http://localhost/?statuscode={httpStatusCode}");
+
+            //Act
+            var response = await Client.SendAsync(request);
+
+            var statusCode = response.StatusCode;
+
+            var responseBody = await response.Content.ReadAsStringAsync();
+
+            //Assert
+            Assert.Equal((HttpStatusCode)httpStatusCode, response.StatusCode);
+            Assert.DoesNotContain(";", responseBody);
+        }   
+
+        [Fact]
+        public async Task StatusCodePageOptions_IncludesSemicolon__AndReasonPhrase_WhenReasonPhrase_IsKnown()
+        {
+            //Arrange    
+            var httpStatusCode = 400;
+            var request = new HttpRequestMessage(HttpMethod.Get, $"http://localhost/?statuscode={httpStatusCode}");
+
+            //Act
+            var response = await Client.SendAsync(request);
+
+            var statusCode = response.StatusCode;
+            var statusCodeReasonPhrase = ReasonPhrases.GetReasonPhrase(httpStatusCode);
+
+            var responseBody = await response.Content.ReadAsStringAsync();
+
+            //Assert
+            Assert.Equal((HttpStatusCode)httpStatusCode, response.StatusCode);
+            Assert.Contains(";", responseBody);
+            Assert.Contains(statusCodeReasonPhrase, responseBody);
+        }
+    }
+}

+ 41 - 0
src/Middleware/Diagnostics/test/FunctionalTests/TestFixture.cs

@@ -0,0 +1,41 @@
+// 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.Net.Http;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.TestHost;
+using Microsoft.AspNetCore.Testing;
+
+namespace Microsoft.AspNetCore.Diagnostics.FunctionalTests
+{
+    public class TestFixture<TStartup> : IDisposable
+    {
+        private readonly TestServer _server;
+
+        public TestFixture()
+        {
+            // RequestLocalizationOptions saves the current culture when constructed, potentially changing response
+            // localization i.e. RequestLocalizationMiddleware behavior. Ensure the saved culture
+            // (DefaultRequestCulture) is consistent regardless of system configuration or personal preferences.
+            using (new CultureReplacer())
+            {
+                var builder = new WebHostBuilder()
+                    .UseStartup(typeof(TStartup));
+
+                _server = new TestServer(builder);
+            }
+
+            Client = _server.CreateClient();
+            Client.BaseAddress = new Uri("http://localhost");
+        }
+
+        public HttpClient Client { get; }
+
+        public void Dispose()
+        {
+            Client.Dispose();
+            _server.Dispose();
+        }
+    }
+}

Some files were not shown because too many files changed in this diff