From b04d09fcca6a25c402fb2599a1265f2b7428ae58 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Thu, 14 Mar 2019 10:49:37 -0700 Subject: [PATCH 01/23] Display startup errors --- .../CommonLib/ServerErrorHandler.h | 18 +++++++------ .../StartupExceptionApplication.h | 22 +++++++++------- .../InProcessRequestHandler/dllmain.cpp | 3 ++- .../inprocessapplication.h | 1 - .../managedexports.cpp | 8 ++++++ .../IIS/samples/NativeIISSample/Startup.cs | 25 +++++++++++++------ src/Servers/IIS/IIS/src/NativeMethods.cs | 18 +++++++++---- 7 files changed, 64 insertions(+), 31 deletions(-) diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h index eb493ce722c4..00cc039b9b19 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h @@ -2,6 +2,7 @@ // Licensed under the MIT License. See License.txt in the project root for license information. #pragma once +#include #include "requesthandler.h" #include "file_utility.h" #include "Environment.h" @@ -9,25 +10,27 @@ class ServerErrorHandler : public REQUEST_HANDLER { public: - ServerErrorHandler(IHttpContext &pContext, USHORT statusCode, USHORT subStatusCode, std::string statusText, HRESULT hr, HINSTANCE moduleInstance, bool disableStartupPage, int page) noexcept + : ServerErrorHandler(pContext, statusCode, subStatusCode, statusText, hr, GetHtml(moduleInstance, page), disableStartupPage) + { + + } + + ServerErrorHandler(IHttpContext &pContext, USHORT statusCode, USHORT subStatusCode, std::string statusText, HRESULT hr, std::string errorPageContent, bool disableStartupPage) noexcept : REQUEST_HANDLER(pContext), m_pContext(pContext), m_HR(hr), m_disableStartupPage(disableStartupPage), - m_page(page), - m_moduleInstance(moduleInstance), m_statusCode(statusCode), m_subStatusCode(subStatusCode), - m_statusText(std::move(statusText)) + m_statusText(std::move(statusText)), + m_content(std::move(errorPageContent)) { } REQUEST_NOTIFICATION_STATUS ExecuteRequestHandler() override { - static std::string s_html500Page = GetHtml(m_moduleInstance, m_page); - - WriteStaticResponse(m_pContext, s_html500Page, m_HR, m_disableStartupPage); + WriteStaticResponse(m_pContext, m_content, m_HR, m_disableStartupPage); return RQ_NOTIFICATION_FINISH_REQUEST; } @@ -99,4 +102,5 @@ class ServerErrorHandler : public REQUEST_HANDLER USHORT m_statusCode; USHORT m_subStatusCode; std::string m_statusText; + std::string m_content; }; diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h index 72b26d857c42..77dd7912b091 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h @@ -15,10 +15,12 @@ class StartupExceptionApplication : public InProcessApplicationBase IHttpApplication& pApplication, HINSTANCE moduleInstance, BOOL disableLogs, - HRESULT hr) + HRESULT hr, + std::wstring errorPageContent) : m_disableLogs(disableLogs), m_HR(hr), m_moduleInstance(moduleInstance), + m_errorPageContent(errorPageContent), InProcessApplicationBase(pServer, pApplication) { } @@ -27,18 +29,20 @@ class StartupExceptionApplication : public InProcessApplicationBase HRESULT CreateHandler(IHttpContext *pHttpContext, IREQUEST_HANDLER ** pRequestHandler) { - *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, m_moduleInstance, m_disableLogs, IN_PROCESS_RH_STATIC_HTML); - return S_OK; - } + if (m_errorPageContent.length() > 0) + { + *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, to_multi_byte_string(m_errorPageContent, CP_UTF8), m_disableLogs); + } + else + { + *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, m_moduleInstance, m_disableLogs, IN_PROCESS_RH_STATIC_HTML); + } - std::string& - GetStaticHtml500Content() - { - return html500Page; + return S_OK; } private: - std::string html500Page; + std::wstring m_errorPageContent; BOOL m_disableLogs; HRESULT m_HR; HINSTANCE m_moduleInstance; diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp index 948a08950d2e..4b17ce16af68 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp @@ -28,6 +28,7 @@ HINSTANCE g_hWinHttpModule; HINSTANCE g_hAspNetCoreModule; HANDLE g_hEventLog = NULL; bool g_fInProcessApplicationCreated = false; +std::wstring g_errorPageContent; HINSTANCE g_hServerModule; HRESULT @@ -128,7 +129,7 @@ CreateApplication( std::unique_ptr options; THROW_IF_FAILED(InProcessOptions::Create(*pServer, pSite, *pHttpApplication, options)); // Set the currently running application to a fake application that returns startup exceptions. - auto pErrorApplication = std::make_unique(*pServer, *pHttpApplication, g_hServerModule, options->QueryDisableStartUpErrorPage(), hr); + auto pErrorApplication = std::make_unique(*pServer, *pHttpApplication, g_hServerModule, options->QueryDisableStartUpErrorPage(), hr, g_errorPageContent); RETURN_IF_FAILED(pErrorApplication->StartMonitoringAppOffline()); *ppApplication = pErrorApplication.release(); diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h index 349b2e293225..4b769822192a 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.h @@ -58,7 +58,6 @@ class IN_PROCESS_APPLICATION : public InProcessApplicationBase HRESULT LoadManagedApplication(); - void QueueStop(); diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp index 93c9d6a97bc6..6b700f876a19 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp @@ -6,6 +6,7 @@ #include "requesthandler_config.h" extern bool g_fInProcessApplicationCreated; +extern std::wstring g_errorPageContent; // // Initialization export @@ -504,4 +505,11 @@ set_main_handler(_In_ hostfxr_main_fn main) IN_PROCESS_APPLICATION::SetMainCallback(main); } +EXTERN_C __MIDL_DECLSPEC_DLLEXPORT +VOID +http_set_startup_error_page_content(_In_ LPCWSTR errorPageContent) +{ + g_errorPageContent = std::wstring(errorPageContent); +} + // End of export diff --git a/src/Servers/IIS/IIS/samples/NativeIISSample/Startup.cs b/src/Servers/IIS/IIS/samples/NativeIISSample/Startup.cs index 216dcea3b89d..4207abfba1a2 100644 --- a/src/Servers/IIS/IIS/samples/NativeIISSample/Startup.cs +++ b/src/Servers/IIS/IIS/samples/NativeIISSample/Startup.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Text.Encodings.Web; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -117,14 +118,22 @@ public void Configure(IApplicationBuilder app) public static void Main(string[] args) { - var host = new WebHostBuilder() - .UseKestrel() - .UseIIS() - .UseIISIntegration() - .UseStartup() - .Build(); - - host.Run(); + AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) => { + Console.WriteLine("1"); + NativeMethods.HttpSetStartupErrorPageContent("
" + HtmlEncoder.Default.Encode(eventArgs.Exception.ToString()) + "
"); + }; + + Console.WriteLine("0"); + throw new InvalidOperationException("ex!"); + + //var host = new WebHostBuilder() + // .UseKestrel() + // .UseIIS() + // .UseIISIntegration() + // .UseStartup() + // .Build(); + + //host.Run(); } } } diff --git a/src/Servers/IIS/IIS/src/NativeMethods.cs b/src/Servers/IIS/IIS/src/NativeMethods.cs index 415604ccc152..d4e7c0f3502e 100644 --- a/src/Servers/IIS/IIS/src/NativeMethods.cs +++ b/src/Servers/IIS/IIS/src/NativeMethods.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Server.IIS { - internal static class NativeMethods + public static class NativeMethods { internal const int HR_OK = 0; internal const int ERROR_NOT_FOUND = unchecked((int)0x80070490); @@ -147,6 +147,9 @@ private static extern unsafe int http_websockets_write_bytes( [DllImport(AspNetCoreModuleDll)] private static extern int http_get_authentication_information(IntPtr pInProcessHandler, [MarshalAs(UnmanagedType.BStr)] out string authType, out IntPtr token); + [DllImport(AspNetCoreModuleDll)] + private static extern int http_set_startup_error_page_content([MarshalAs(UnmanagedType.LPWStr)]string content); + public static void HttpPostCompletion(IntPtr pInProcessHandler, int cbBytes) { Validate(http_post_completion(pInProcessHandler, cbBytes)); @@ -169,7 +172,7 @@ public static void HttpRegisterCallbacks(IntPtr pInProcessApplication, Validate(register_callbacks(pInProcessApplication, requestCallback, shutdownCallback, disconnectCallback, asyncCallback, requestsDrainedHandler, pvRequestContext, pvShutdownContext)); } - public static unsafe int HttpWriteResponseBytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected) + internal static unsafe int HttpWriteResponseBytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected) { return http_write_response_bytes(pInProcessHandler, pDataChunks, nChunks, out fCompletionExpected); } @@ -179,7 +182,7 @@ public static int HttpFlushResponseBytes(IntPtr pInProcessHandler, bool fMoreDat return http_flush_response_bytes(pInProcessHandler, fMoreData, out fCompletionExpected); } - public static unsafe HttpApiTypes.HTTP_REQUEST_V2* HttpGetRawRequest(IntPtr pInProcessHandler) + internal static unsafe HttpApiTypes.HTTP_REQUEST_V2* HttpGetRawRequest(IntPtr pInProcessHandler) { return http_get_raw_request(pInProcessHandler); } @@ -219,7 +222,7 @@ public static void HttpSetManagedContext(IntPtr pInProcessHandler, IntPtr pvMana Validate(http_set_managed_context(pInProcessHandler, pvManagedContext)); } - public static IISConfigurationData HttpGetApplicationProperties() + internal static IISConfigurationData HttpGetApplicationProperties() { var iisConfigurationData = new IISConfigurationData(); Validate(http_get_application_properties(ref iisConfigurationData)); @@ -247,7 +250,7 @@ public static unsafe int HttpWebsocketsReadBytes( return http_websockets_read_bytes(pInProcessHandler, pvBuffer, cbBuffer, pfnCompletionCallback, pvCompletionContext, out dwBytesReceived, out fCompletionExpected); } - public static unsafe int HttpWebsocketsWriteBytes( + internal static unsafe int HttpWebsocketsWriteBytes( IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, @@ -297,6 +300,11 @@ public static void HttpGetAuthenticationInformation(IntPtr pInProcessHandler, ou Validate(http_get_authentication_information(pInProcessHandler, out authType, out token)); } + public static void HttpSetStartupErrorPageContent(string content) + { + http_set_startup_error_page_content(content); + } + private static void Validate(int hr) { if (hr != HR_OK) From 51ad137ee391c4c4cca5751128b1f677d0c7621d Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Fri, 22 Mar 2019 10:28:46 -0700 Subject: [PATCH 02/23] nit --- .../IIS/IIS/test/Common.FunctionalTests/MultiApplicationTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Servers/IIS/IIS/test/Common.FunctionalTests/MultiApplicationTests.cs b/src/Servers/IIS/IIS/test/Common.FunctionalTests/MultiApplicationTests.cs index 90bbcb4291f8..87d9c73dd0c3 100644 --- a/src/Servers/IIS/IIS/test/Common.FunctionalTests/MultiApplicationTests.cs +++ b/src/Servers/IIS/IIS/test/Common.FunctionalTests/MultiApplicationTests.cs @@ -10,7 +10,6 @@ using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Extensions.Logging; using Xunit; namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests From f9eda2be06156a29d8112abe7fd001b92c623941 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Fri, 22 Mar 2019 18:01:02 -0700 Subject: [PATCH 03/23] prototype work --- .../AspNetCore/ServerErrorApplication.h | 2 +- .../CommonLib/ServerErrorHandler.h | 50 ++- .../InProcessRequestHandler/HtmlResponses.rc | Bin 3112 -> 3304 bytes .../InProcessRequestHandler.vcxproj | 3 + .../InProcessRhExceptionPage.htm | 404 ++++++++++++++++++ .../StartupExceptionApplication.h | 4 +- .../inprocessapplication.cpp | 3 + .../InProcessRequestHandler/resource.h | 1 + .../forwardinghandler.cpp | 2 +- .../IIS/samples/NativeIISSample/Startup.cs | 6 - .../Microsoft.AspNetCore.Server.IIS.csproj | 4 +- src/Servers/IIS/IIS/src/StartupHook.cs | 239 +++++++++++ 12 files changed, 684 insertions(+), 34 deletions(-) create mode 100644 src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhExceptionPage.htm create mode 100644 src/Servers/IIS/IIS/src/StartupHook.cs diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h index b5b86aa20cdb..77aaff9332ab 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h @@ -27,7 +27,7 @@ class ServerErrorApplication : public PollingAppOfflineApplication HRESULT CreateHandler(IHttpContext *pHttpContext, IREQUEST_HANDLER ** pRequestHandler) override { - auto handler = std::make_unique(*pHttpContext, 500ui16, 0ui16, "Internal Server Error", m_HR, m_moduleInstance, m_disableStartupPage, m_page); + auto handler = std::make_unique(*pHttpContext, 500ui16, 0ui16, "Internal Server Error", m_HR, m_moduleInstance, m_disableStartupPage, m_page, ""); *pRequestHandler = handler.release(); return S_OK; } diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h index 00cc039b9b19..2de9649e8104 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h @@ -10,27 +10,25 @@ class ServerErrorHandler : public REQUEST_HANDLER { public: - ServerErrorHandler(IHttpContext &pContext, USHORT statusCode, USHORT subStatusCode, std::string statusText, HRESULT hr, HINSTANCE moduleInstance, bool disableStartupPage, int page) noexcept - : ServerErrorHandler(pContext, statusCode, subStatusCode, statusText, hr, GetHtml(moduleInstance, page), disableStartupPage) - { - - } - - ServerErrorHandler(IHttpContext &pContext, USHORT statusCode, USHORT subStatusCode, std::string statusText, HRESULT hr, std::string errorPageContent, bool disableStartupPage) noexcept + ServerErrorHandler(IHttpContext& pContext, USHORT statusCode, USHORT subStatusCode, std::string statusText, HRESULT hr, HINSTANCE module, bool disableStartupPage, int page, std::string errorPageContent) noexcept : REQUEST_HANDLER(pContext), - m_pContext(pContext), - m_HR(hr), - m_disableStartupPage(disableStartupPage), - m_statusCode(statusCode), - m_subStatusCode(subStatusCode), - m_statusText(std::move(statusText)), - m_content(std::move(errorPageContent)) + m_pContext(pContext), + m_HR(hr), + m_disableStartupPage(disableStartupPage), + m_statusCode(statusCode), + m_subStatusCode(subStatusCode), + m_statusText(std::move(statusText)), + m_ExceptionInfoContent(std::move(errorPageContent)), + m_page(page), + m_moduleInstance(module) { } REQUEST_NOTIFICATION_STATUS ExecuteRequestHandler() override { - WriteStaticResponse(m_pContext, m_content, m_HR, m_disableStartupPage); + static std::string s_html500Page = GetHtml(m_moduleInstance, m_page); + + WriteStaticResponse(m_pContext, s_html500Page, m_HR, m_disableStartupPage); return RQ_NOTIFICATION_FINISH_REQUEST; } @@ -59,7 +57,6 @@ class ServerErrorHandler : public REQUEST_HANDLER pResponse->WriteEntityChunkByReference(&dataChunk); } - static std::string GetHtml(HMODULE module, int page) { @@ -77,15 +74,22 @@ class ServerErrorHandler : public REQUEST_HANDLER THROW_LAST_ERROR_IF_NULL(pTempData = static_cast(LockResource(rcData))); data = std::string(pTempData, size); - auto additionalErrorLink = Environment::GetEnvironmentVariableValue(L"ANCM_ADDITIONAL_ERROR_PAGE_LINK"); - std::string additionalHtml; + if (page == 101) // TODO + { + auto additionalErrorLink = Environment::GetEnvironmentVariableValue(L"ANCM_ADDITIONAL_ERROR_PAGE_LINK"); + std::string additionalHtml; + + if (additionalErrorLink.has_value()) + { + additionalHtml = format(" %S and ", additionalErrorLink->c_str(), additionalErrorLink->c_str()); + } - if (additionalErrorLink.has_value()) + return format(data, additionalHtml.c_str()); + } + else { - additionalHtml = format(" %S and ", additionalErrorLink->c_str(), additionalErrorLink->c_str()); + return format(data, m_ExceptionInfoContent.c_str()); } - - return format(data, additionalHtml.c_str()); } catch (...) { @@ -102,5 +106,5 @@ class ServerErrorHandler : public REQUEST_HANDLER USHORT m_statusCode; USHORT m_subStatusCode; std::string m_statusText; - std::string m_content; + std::string m_ExceptionInfoContent; }; diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/HtmlResponses.rc b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/HtmlResponses.rc index 25a99683c5e9730bdb8e0b66e6a68d3229964283..4d189a38c04d0b114bf5282fb9521ad98e84179b 100644 GIT binary patch delta 80 zcmZ1>@j`OLD~`zq95S-53=s^@46Y0T3?U4j4E_v$4Dmp=BZE6oEPir5hxp_M4i8CJ gh6;vchE#?Eh7yKMhJ1!RpqfO6bcWQ;w>f;70S9*yu>b%7 delta 12 TcmaDMxk6&YD~`>pIPI7LCO!oV diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRequestHandler.vcxproj b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRequestHandler.vcxproj index cf2b5d1f02a7..d4981f3ff254 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRequestHandler.vcxproj +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRequestHandler.vcxproj @@ -267,6 +267,9 @@ + + true + true diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhExceptionPage.htm b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhExceptionPage.htm new file mode 100644 index 000000000000..b1766b2dc65b --- /dev/null +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhExceptionPage.htm @@ -0,0 +1,404 @@ + + + + + + Internal Server Error + + + + %s + + + diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h index 77dd7912b091..f72c135657d7 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h @@ -31,11 +31,11 @@ class StartupExceptionApplication : public InProcessApplicationBase { if (m_errorPageContent.length() > 0) { - *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, to_multi_byte_string(m_errorPageContent, CP_UTF8), m_disableLogs); + *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, m_moduleInstance, m_disableLogs, IN_PROCESS_RH_EXCEPTION_PAGE_HTML, to_multi_byte_string(m_errorPageContent, CP_UTF8)); } else { - *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, m_moduleInstance, m_disableLogs, IN_PROCESS_RH_STATIC_HTML); + *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, m_moduleInstance, m_disableLogs, IN_PROCESS_RH_STATIC_HTML, ""); } return S_OK; diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp index 696211420a3a..cb21c5add048 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp @@ -462,6 +462,9 @@ IN_PROCESS_APPLICATION::SetEnvironmentVariablesOnWorkerProcess() SetEnvironmentVariable(variable.first.c_str(), variable.second.c_str()); } + auto startupHookDll = Environment::GetCurrentDirectoryValue() + std::wstring(L"\\Microsoft.AspNetCore.Server.IIS.dll"); + SetEnvironmentVariable(L"DOTNET_STARTUP_HOOKS", startupHookDll.c_str()); + return S_OK; } diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/resource.h b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/resource.h index 61f67c283334..fc834f6670bb 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/resource.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/resource.h @@ -3,6 +3,7 @@ // Used by HtmlResponses.rc // #define IN_PROCESS_RH_STATIC_HTML 101 +#define IN_PROCESS_RH_EXCEPTION_PAGE_HTML 103 // Next default values for new objects // diff --git a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp index 551d10c9f992..fba507132c5c 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp @@ -302,7 +302,7 @@ FORWARDING_HANDLER::ExecuteRequestHandler() } else if (fFailedToStartKestrel && !m_pApplication->QueryConfig()->QueryDisableStartUpErrorPage()) { - ServerErrorHandler handler(*m_pW3Context, 502, 5, "Bad Gateway", hr, g_hOutOfProcessRHModule, m_pApplication->QueryConfig()->QueryDisableStartUpErrorPage(), OUT_OF_PROCESS_RH_STATIC_HTML); + ServerErrorHandler handler(*m_pW3Context, 502, 5, "Bad Gateway", hr, g_hOutOfProcessRHModule, m_pApplication->QueryConfig()->QueryDisableStartUpErrorPage(), OUT_OF_PROCESS_RH_STATIC_HTML, ""); handler.ExecuteRequestHandler(); } else diff --git a/src/Servers/IIS/IIS/samples/NativeIISSample/Startup.cs b/src/Servers/IIS/IIS/samples/NativeIISSample/Startup.cs index 4207abfba1a2..98610450d932 100644 --- a/src/Servers/IIS/IIS/samples/NativeIISSample/Startup.cs +++ b/src/Servers/IIS/IIS/samples/NativeIISSample/Startup.cs @@ -118,12 +118,6 @@ public void Configure(IApplicationBuilder app) public static void Main(string[] args) { - AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) => { - Console.WriteLine("1"); - NativeMethods.HttpSetStartupErrorPageContent("
" + HtmlEncoder.Default.Encode(eventArgs.Exception.ToString()) + "
"); - }; - - Console.WriteLine("0"); throw new InvalidOperationException("ex!"); //var host = new WebHostBuilder() diff --git a/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj b/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj index 293ab4c80715..8fe44d645fbf 100644 --- a/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj +++ b/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.0 @@ -32,8 +32,10 @@ + +
diff --git a/src/Servers/IIS/IIS/src/StartupHook.cs b/src/Servers/IIS/IIS/src/StartupHook.cs new file mode 100644 index 000000000000..47df52b0eff2 --- /dev/null +++ b/src/Servers/IIS/IIS/src/StartupHook.cs @@ -0,0 +1,239 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.Encodings.Web; +using Microsoft.AspNetCore.Server.IIS; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Primitives; +using Microsoft.Extensions.StackTrace.Sources; + +internal class StartupHook +{ + public static void Initialize() + { + Console.WriteLine("test"); + AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) => + { + var builder = new StringBuilder(); + var exception = eventArgs.Exception; + // Pinvoke for content root. + var exceptionDetailProvider = new ExceptionDetailsProvider( + new PhysicalFileProvider(), // TODO get content root here + sourceCodeLineCount: 6); + + var details = exceptionDetailProvider.GetDetails(exception); + var detail = details.First(); + + builder.Append("

An error occurred while starting the application.


"); + builder.Append($"
{HtmlEncoder.Default.Encode(exception.GetType().ToString())}: {HtmlEncodeAndReplaceLineBreaks(exception.Message)}"); + + var firstFrame = detail.StackFrames.FirstOrDefault(); + var location = string.Empty; + if (firstFrame != null) + { + location = firstFrame.Function; + } + + if (!string.IsNullOrEmpty(location) && firstFrame != null && !string.IsNullOrEmpty(firstFrame.File)) + { + builder.Append($"

{HtmlEncoder.Default.Encode(location)} in {HtmlEncoder.Default.Encode(Path.GetFileName(firstFrame.File))}, line {firstFrame.Line}

"); + } + else if (!string.IsNullOrEmpty(location)) + { + builder.Append($"

{HtmlEncoder.Default.Encode(location)}

"); + } + else + { + builder.Append($"

@Resources.ErrorPageHtml_UnknownLocation

"); + } + + var reflectionTypeLoadException = detail.Error as ReflectionTypeLoadException; + if (reflectionTypeLoadException != null) + { + if (reflectionTypeLoadException.LoaderExceptions.Length > 0) + { + builder.Append("

Loader Exceptions:


"); + builder.Append("
    "); + + foreach (var ex in reflectionTypeLoadException.LoaderExceptions) + { + builder.Append($"
  • {HtmlEncoder.Default.Encode(ex.Message)}
  • "); + } + builder.Append("
"); + } + } + + builder.Append("
"); + builder.Append("
    "); + + var exceptionCount = 0; + var stackFrameCount = 0; + var exceptionDetailId = ""; + var frameId = ""; + foreach (var errorDetail in details) + { + exceptionCount++; + exceptionDetailId = "exceptionDetail" + exceptionCount; + builder.Append("
  • "); + builder.Append($"

    {HtmlEncoder.Default.Encode(errorDetail.Error.GetType().Name)}: {HtmlEncoder.Default.Encode(errorDetail.Error.Message)}

    "); + builder.Append("
      "); + foreach (var frame in errorDetail.StackFrames) + { + stackFrameCount++; + frameId = "frame" + stackFrameCount; + builder.Append($"
    • "); + if (string.IsNullOrEmpty(frame.File)) + { + builder.Append($"

      {HtmlEncoder.Default.Encode(frame.Function)}

      "); + } + else + { + builder.Append($"

      {HtmlEncoder.Default.Encode(frame.Function)} in {HtmlEncoder.Default.Encode(Path.GetFileName(frame.File))}

      "); + } + + if (frame.Line != 0 && frame.ContextCode.Any()) + { + builder.Append($""); + builder.Append($"
      "); + if (frame.PreContextCode.Any()) + { + builder.Append($"
        "); + foreach (var line in frame.PreContextCode) + { + builder.Append($"
      1. {HtmlEncoder.Default.Encode(line)}
      2. "); + } + builder.Append("
      "); + } + builder.Append($"
        "); + foreach(var line in frame.ContextCode) + { + builder.Append($"
      1. {HtmlEncoder.Default.Encode(line)}
      2. "); + } + builder.Append("
      "); + + if (frame.PostContextCode.Any()) + { + builder.Append($"
        "); + foreach (var line in frame.PostContextCode) + { + builder.Append($"
      1. {HtmlEncoder.Default.Encode(line)}
      2. "); + } + builder.Append("
      "); + } + builder.Append($"
      "); + } + + builder.Append($"
    • "); + } + builder.Append($"
    "); + builder.Append($"
  • "); + builder.Append($"
  • "); + builder.Append("
    "); + builder.Append($"
    "); + builder.Append($"
    "); + builder.Append($""); + builder.Append($"
    "); + builder.Append($"
    "); + builder.Append($"
    {HtmlEncoder.Default.Encode(errorDetail.Error.ToString())}
    "); + builder.Append($"
    "); + builder.Append($"
    "); + builder.Append($"
  • "); + } + builder.Append("
"); + builder.Append($"
"); + + + builder.Append("
"); + builder.Append("
"); + NativeMethods.HttpSetStartupErrorPageContent(builder.ToString()); + }; + } + + private static string HtmlEncodeAndReplaceLineBreaks(string input) + { + if (string.IsNullOrEmpty(input)) + { + return string.Empty; + } + + // This is horrible, but I don't want to call linq + var list = new List(); + var arr = input.Split(new[] { "\r\n" }, StringSplitOptions.None); + foreach (var a in arr) + { + var anotherStringArr = a.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + list.AddRange(anotherStringArr); + } + + return string.Join("
" + Environment.NewLine, list); + } + + public class PhysicalFileProvider : IFileProvider + { + public IDirectoryContents GetDirectoryContents(string subpath) + { + throw new NotImplementedException(); + } + + public IFileInfo GetFileInfo(string contentRoot) + { + var fileInfo = new FileInfo(contentRoot); + return new PhysicalFileInfo(fileInfo); + } + + + public IChangeToken Watch(string filter) + { + throw new NotImplementedException(); + } + + private class PhysicalFileInfo : IFileInfo + { + private readonly FileInfo _info; + + public PhysicalFileInfo(FileInfo info) + { + _info = info; + } + + /// + public bool Exists => _info.Exists; + + /// + public long Length => _info.Length; + + /// + public string PhysicalPath => _info.FullName; + + /// + public string Name => _info.Name; + + /// + public DateTimeOffset LastModified => _info.LastWriteTimeUtc; + + /// + /// Always false. + /// + public bool IsDirectory => false; + public Stream CreateReadStream() + { + // We are setting buffer size to 1 to prevent FileStream from allocating it's internal buffer + // 0 causes constructor to throw + var bufferSize = 1; + return new FileStream( + PhysicalPath, + FileMode.Open, + FileAccess.Read, + FileShare.ReadWrite, + bufferSize, + FileOptions.Asynchronous | FileOptions.SequentialScan); + } + } + } +} From 2054469e227ac91515b70cdb8e96b236a6efbe63 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Mon, 25 Mar 2019 08:58:08 -0700 Subject: [PATCH 04/23] small nits --- .../Microsoft.AspNetCore.Server.IIS.csproj | 1 + src/Servers/IIS/IIS/src/StartupHook.cs | 151 ++++++------------ 2 files changed, 53 insertions(+), 99 deletions(-) diff --git a/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj b/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj index 8fe44d645fbf..2853fe7b6b12 100644 --- a/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj +++ b/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj @@ -32,6 +32,7 @@ + diff --git a/src/Servers/IIS/IIS/src/StartupHook.cs b/src/Servers/IIS/IIS/src/StartupHook.cs index 47df52b0eff2..334ad05a7ecc 100644 --- a/src/Servers/IIS/IIS/src/StartupHook.cs +++ b/src/Servers/IIS/IIS/src/StartupHook.cs @@ -6,66 +6,70 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using System.Text; using System.Text.Encodings.Web; using Microsoft.AspNetCore.Server.IIS; using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.Primitives; using Microsoft.Extensions.StackTrace.Sources; internal class StartupHook { public static void Initialize() { - Console.WriteLine("test"); + // TODO make this unhandled exception AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) => { var builder = new StringBuilder(); var exception = eventArgs.Exception; + // Pinvoke for content root. + var iisConfigData = NativeMethods.HttpGetApplicationProperties(); + var contentRoot = iisConfigData.pwzFullApplicationPath.TrimEnd(Path.DirectorySeparatorChar); + var exceptionDetailProvider = new ExceptionDetailsProvider( - new PhysicalFileProvider(), // TODO get content root here + new PhysicalFileProvider(contentRoot), sourceCodeLineCount: 6); var details = exceptionDetailProvider.GetDetails(exception); - var detail = details.First(); builder.Append("

An error occurred while starting the application.


"); - builder.Append($"
{HtmlEncoder.Default.Encode(exception.GetType().ToString())}: {HtmlEncodeAndReplaceLineBreaks(exception.Message)}"); - - var firstFrame = detail.StackFrames.FirstOrDefault(); - var location = string.Empty; - if (firstFrame != null) - { - location = firstFrame.Function; - } - - if (!string.IsNullOrEmpty(location) && firstFrame != null && !string.IsNullOrEmpty(firstFrame.File)) - { - builder.Append($"

{HtmlEncoder.Default.Encode(location)} in {HtmlEncoder.Default.Encode(Path.GetFileName(firstFrame.File))}, line {firstFrame.Line}

"); - } - else if (!string.IsNullOrEmpty(location)) - { - builder.Append($"

{HtmlEncoder.Default.Encode(location)}

"); - } - else + foreach (var detail in details) { - builder.Append($"

@Resources.ErrorPageHtml_UnknownLocation

"); - } + var firstFrame = detail.StackFrames.FirstOrDefault(); + var location = string.Empty; + if (firstFrame != null) + { + location = firstFrame.Function; + } - var reflectionTypeLoadException = detail.Error as ReflectionTypeLoadException; - if (reflectionTypeLoadException != null) - { - if (reflectionTypeLoadException.LoaderExceptions.Length > 0) + if (!string.IsNullOrEmpty(location) && firstFrame != null && !string.IsNullOrEmpty(firstFrame.File)) { - builder.Append("

Loader Exceptions:


"); - builder.Append("
    "); + builder.Append($"

    {HtmlEncoder.Default.Encode(location)} in {HtmlEncoder.Default.Encode(Path.GetFileName(firstFrame.File))}, line {firstFrame.Line}

    "); + } + else if (!string.IsNullOrEmpty(location)) + { + builder.Append($"

    {HtmlEncoder.Default.Encode(location)}

    "); + } + else + { + builder.Append($"

    @Resources.ErrorPageHtml_UnknownLocation

    "); + } - foreach (var ex in reflectionTypeLoadException.LoaderExceptions) + var reflectionTypeLoadException = detail.Error as ReflectionTypeLoadException; + if (reflectionTypeLoadException != null) + { + if (reflectionTypeLoadException.LoaderExceptions.Length > 0) { - builder.Append($"
  • {HtmlEncoder.Default.Encode(ex.Message)}
  • "); + builder.Append("

    Loader Exceptions:


    "); + builder.Append("
      "); + + foreach (var ex in reflectionTypeLoadException.LoaderExceptions) + { + builder.Append($"
    • {HtmlEncoder.Default.Encode(ex.Message)}
    • "); + } + builder.Append("
    "); } - builder.Append("
"); } } @@ -111,7 +115,7 @@ public static void Initialize() builder.Append(""); } builder.Append($"
    "); - foreach(var line in frame.ContextCode) + foreach (var line in frame.ContextCode) { builder.Append($"
  1. {HtmlEncoder.Default.Encode(line)}
  2. "); } @@ -145,12 +149,25 @@ public static void Initialize() builder.Append($"
"); builder.Append($""); } + builder.Append(""); builder.Append($"
"); - builder.Append("
"); + + var runtimeDisplayName = HtmlEncoder.Default.Encode(RuntimeInformation.FrameworkDescription); + var runtimeArchitecture = HtmlEncoder.Default.Encode(RuntimeInformation.ProcessArchitecture.ToString()); + var currentAssemblyVersion = HtmlEncoder.Default.Encode(RuntimeInformation.ProcessArchitecture.ToString()); + var systemRuntimeAssembly = typeof(System.ComponentModel.DefaultValueAttribute).GetTypeInfo().Assembly; + var clrVersion = HtmlEncoder.Default.Encode(new AssemblyName(systemRuntimeAssembly.FullName).Version.ToString()); + var operatingSystemDescription = HtmlEncoder.Default.Encode(RuntimeInformation.OSDescription); + + builder.Append($"{runtimeDisplayName} {runtimeArchitecture} v{clrVersion}    |   Microsoft.AspNetCore.Server.IIS version " + + $"{currentAssemblyVersion}    |    {operatingSystemDescription}    |    " + + $"Need help?"); + builder.Append("
"); + NativeMethods.HttpSetStartupErrorPageContent(builder.ToString()); }; } @@ -162,7 +179,6 @@ private static string HtmlEncodeAndReplaceLineBreaks(string input) return string.Empty; } - // This is horrible, but I don't want to call linq var list = new List(); var arr = input.Split(new[] { "\r\n" }, StringSplitOptions.None); foreach (var a in arr) @@ -173,67 +189,4 @@ private static string HtmlEncodeAndReplaceLineBreaks(string input) return string.Join("
" + Environment.NewLine, list); } - - public class PhysicalFileProvider : IFileProvider - { - public IDirectoryContents GetDirectoryContents(string subpath) - { - throw new NotImplementedException(); - } - - public IFileInfo GetFileInfo(string contentRoot) - { - var fileInfo = new FileInfo(contentRoot); - return new PhysicalFileInfo(fileInfo); - } - - - public IChangeToken Watch(string filter) - { - throw new NotImplementedException(); - } - - private class PhysicalFileInfo : IFileInfo - { - private readonly FileInfo _info; - - public PhysicalFileInfo(FileInfo info) - { - _info = info; - } - - /// - public bool Exists => _info.Exists; - - /// - public long Length => _info.Length; - - /// - public string PhysicalPath => _info.FullName; - - /// - public string Name => _info.Name; - - /// - public DateTimeOffset LastModified => _info.LastWriteTimeUtc; - - /// - /// Always false. - /// - public bool IsDirectory => false; - public Stream CreateReadStream() - { - // We are setting buffer size to 1 to prevent FileStream from allocating it's internal buffer - // 0 causes constructor to throw - var bufferSize = 1; - return new FileStream( - PhysicalPath, - FileMode.Open, - FileAccess.Read, - FileShare.ReadWrite, - bufferSize, - FileOptions.Asynchronous | FileOptions.SequentialScan); - } - } - } } From dbfb98cfc063a3c7a3c3710b96b2a3e5a1cee567 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Mon, 25 Mar 2019 10:50:48 -0700 Subject: [PATCH 05/23] make this feature good --- .../src/Microsoft.AspNetCore.Hosting.csproj | 1 + src/Hosting/Hosting/src/Resources.resx | 9 - .../AspNetCore/ServerErrorApplication.h | 2 +- .../CommonLib/ServerErrorHandler.h | 65 +- .../StartupExceptionApplication.h | 13 +- .../InProcessRequestHandler/dllmain.cpp | 5 +- .../managedexports.cpp | 9 +- .../forwardinghandler.cpp | 2 +- .../Microsoft.AspNetCore.Server.IIS.csproj | 2 + src/Servers/IIS/IIS/src/NativeMethods.cs | 9 +- src/Servers/IIS/IIS/src/StartupHook.cs | 235 +- .../ErrorPage}/ErrorPage.Designer.cs | 2109 +++++++++-------- .../ErrorPage}/ErrorPage.cshtml | 8 +- .../Views => Shared/ErrorPage}/ErrorPage.css | 0 .../Views => Shared/ErrorPage}/ErrorPage.js | 0 .../ErrorPage}/ErrorPageModel.cs | 2 +- .../StackTrace/StackFrame/StackTraceHelper.cs | 2 +- 17 files changed, 1214 insertions(+), 1259 deletions(-) rename src/{Hosting/Hosting/src/Startup/ExceptionPage/Views => Shared/ErrorPage}/ErrorPage.Designer.cs (95%) rename src/{Hosting/Hosting/src/Startup/ExceptionPage/Views => Shared/ErrorPage}/ErrorPage.cshtml (96%) rename src/{Hosting/Hosting/src/Startup/ExceptionPage/Views => Shared/ErrorPage}/ErrorPage.css (100%) rename src/{Hosting/Hosting/src/Startup/ExceptionPage/Views => Shared/ErrorPage}/ErrorPage.js (100%) rename src/{Hosting/Hosting/src/Startup/ExceptionPage/Views => Shared/ErrorPage}/ErrorPageModel.cs (93%) diff --git a/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj b/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj index 8405e5e0d36f..c1aac9be6143 100644 --- a/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj +++ b/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj @@ -12,6 +12,7 @@ + diff --git a/src/Hosting/Hosting/src/Resources.resx b/src/Hosting/Hosting/src/Resources.resx index 64d6fe523dae..22d1975ba094 100644 --- a/src/Hosting/Hosting/src/Resources.resx +++ b/src/Hosting/Hosting/src/Resources.resx @@ -117,15 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Internal Server Error - - - An error occurred while starting the application. - - - Unknown location - WebHostBuilder allows creation only of a single instance of WebHost diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h index 77aaff9332ab..fe42ca474462 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h @@ -27,7 +27,7 @@ class ServerErrorApplication : public PollingAppOfflineApplication HRESULT CreateHandler(IHttpContext *pHttpContext, IREQUEST_HANDLER ** pRequestHandler) override { - auto handler = std::make_unique(*pHttpContext, 500ui16, 0ui16, "Internal Server Error", m_HR, m_moduleInstance, m_disableStartupPage, m_page, ""); + auto handler = std::make_unique(*pHttpContext, 500ui16, 0ui16, "Internal Server Error", m_HR, m_moduleInstance, m_disableStartupPage, m_page, nullptr, 0); *pRequestHandler = handler.release(); return S_OK; } diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h index 2de9649e8104..0986cc13ae69 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h @@ -10,17 +10,18 @@ class ServerErrorHandler : public REQUEST_HANDLER { public: - ServerErrorHandler(IHttpContext& pContext, USHORT statusCode, USHORT subStatusCode, std::string statusText, HRESULT hr, HINSTANCE module, bool disableStartupPage, int page, std::string errorPageContent) noexcept + ServerErrorHandler(IHttpContext& pContext, USHORT statusCode, USHORT subStatusCode, std::string statusText, HRESULT hr, HINSTANCE module, bool disableStartupPage, int page, BYTE* content, int length) noexcept : REQUEST_HANDLER(pContext), - m_pContext(pContext), - m_HR(hr), - m_disableStartupPage(disableStartupPage), - m_statusCode(statusCode), - m_subStatusCode(subStatusCode), - m_statusText(std::move(statusText)), - m_ExceptionInfoContent(std::move(errorPageContent)), - m_page(page), - m_moduleInstance(module) + m_pContext(pContext), + m_HR(hr), + m_disableStartupPage(disableStartupPage), + m_statusCode(statusCode), + m_subStatusCode(subStatusCode), + m_statusText(std::move(statusText)), + m_ExceptionInfoContent(content), + m_length(length), + m_page(page), + m_moduleInstance(module) { } @@ -34,7 +35,7 @@ class ServerErrorHandler : public REQUEST_HANDLER } private: - void WriteStaticResponse(IHttpContext& pContext, std::string &page, HRESULT hr, bool disableStartupErrorPage) const + void WriteStaticResponse(IHttpContext& pContext, std::string& page, HRESULT hr, bool disableStartupErrorPage) const { if (disableStartupErrorPage) { @@ -42,6 +43,24 @@ class ServerErrorHandler : public REQUEST_HANDLER return; } + if (m_length > 0) + { + // TODO cleanup + HTTP_DATA_CHUNK dataChunk = {}; + IHttpResponse* pResponse = pContext.GetResponse(); + pResponse->SetStatus(m_statusCode, m_statusText.c_str(), m_subStatusCode, hr, nullptr, true); + pResponse->SetHeader("Content-Type", + "text/html", + (USHORT)strlen("text/html"), + FALSE + ); + dataChunk.DataChunkType = HttpDataChunkFromMemory; + dataChunk.FromMemory.pBuffer = m_ExceptionInfoContent; + dataChunk.FromMemory.BufferLength = static_cast(m_length); + pResponse->WriteEntityChunkByReference(&dataChunk); + return; + } + HTTP_DATA_CHUNK dataChunk = {}; IHttpResponse* pResponse = pContext.GetResponse(); pResponse->SetStatus(m_statusCode, m_statusText.c_str(), m_subStatusCode, hr, nullptr, true); @@ -74,22 +93,15 @@ class ServerErrorHandler : public REQUEST_HANDLER THROW_LAST_ERROR_IF_NULL(pTempData = static_cast(LockResource(rcData))); data = std::string(pTempData, size); - if (page == 101) // TODO - { - auto additionalErrorLink = Environment::GetEnvironmentVariableValue(L"ANCM_ADDITIONAL_ERROR_PAGE_LINK"); - std::string additionalHtml; - - if (additionalErrorLink.has_value()) - { - additionalHtml = format(" %S and ", additionalErrorLink->c_str(), additionalErrorLink->c_str()); - } + auto additionalErrorLink = Environment::GetEnvironmentVariableValue(L"ANCM_ADDITIONAL_ERROR_PAGE_LINK"); + std::string additionalHtml; - return format(data, additionalHtml.c_str()); - } - else + if (additionalErrorLink.has_value()) { - return format(data, m_ExceptionInfoContent.c_str()); + additionalHtml = format(" %S and ", additionalErrorLink->c_str(), additionalErrorLink->c_str()); } + + return format(data, additionalHtml.c_str()); } catch (...) { @@ -98,7 +110,7 @@ class ServerErrorHandler : public REQUEST_HANDLER } } - IHttpContext &m_pContext; + IHttpContext& m_pContext; HRESULT m_HR; bool m_disableStartupPage; int m_page; @@ -106,5 +118,6 @@ class ServerErrorHandler : public REQUEST_HANDLER USHORT m_statusCode; USHORT m_subStatusCode; std::string m_statusText; - std::string m_ExceptionInfoContent; + byte* m_ExceptionInfoContent; + int m_length; }; diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h index f72c135657d7..289d9e657297 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h @@ -16,11 +16,13 @@ class StartupExceptionApplication : public InProcessApplicationBase HINSTANCE moduleInstance, BOOL disableLogs, HRESULT hr, - std::wstring errorPageContent) + BYTE* errorPageContent, + int length) : m_disableLogs(disableLogs), m_HR(hr), m_moduleInstance(moduleInstance), m_errorPageContent(errorPageContent), + m_length(length), InProcessApplicationBase(pServer, pApplication) { } @@ -29,22 +31,23 @@ class StartupExceptionApplication : public InProcessApplicationBase HRESULT CreateHandler(IHttpContext *pHttpContext, IREQUEST_HANDLER ** pRequestHandler) { - if (m_errorPageContent.length() > 0) + if (m_length > 0) { - *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, m_moduleInstance, m_disableLogs, IN_PROCESS_RH_EXCEPTION_PAGE_HTML, to_multi_byte_string(m_errorPageContent, CP_UTF8)); + *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, m_moduleInstance, m_disableLogs, IN_PROCESS_RH_EXCEPTION_PAGE_HTML, m_errorPageContent, m_length); } else { - *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, m_moduleInstance, m_disableLogs, IN_PROCESS_RH_STATIC_HTML, ""); + *pRequestHandler = new ServerErrorHandler(*pHttpContext, 500, 30, "Internal Server Error", m_HR, m_moduleInstance, m_disableLogs, IN_PROCESS_RH_STATIC_HTML, nullptr, 0); } return S_OK; } private: - std::wstring m_errorPageContent; + BYTE* m_errorPageContent; BOOL m_disableLogs; HRESULT m_HR; HINSTANCE m_moduleInstance; + int m_length; }; diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp index 4b17ce16af68..4cb60dfc616b 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp @@ -28,7 +28,8 @@ HINSTANCE g_hWinHttpModule; HINSTANCE g_hAspNetCoreModule; HANDLE g_hEventLog = NULL; bool g_fInProcessApplicationCreated = false; -std::wstring g_errorPageContent; +BYTE* g_errorPageContent; +int g_errorPageLength; HINSTANCE g_hServerModule; HRESULT @@ -129,7 +130,7 @@ CreateApplication( std::unique_ptr options; THROW_IF_FAILED(InProcessOptions::Create(*pServer, pSite, *pHttpApplication, options)); // Set the currently running application to a fake application that returns startup exceptions. - auto pErrorApplication = std::make_unique(*pServer, *pHttpApplication, g_hServerModule, options->QueryDisableStartUpErrorPage(), hr, g_errorPageContent); + auto pErrorApplication = std::make_unique(*pServer, *pHttpApplication, g_hServerModule, options->QueryDisableStartUpErrorPage(), hr, g_errorPageContent, g_errorPageLength); RETURN_IF_FAILED(pErrorApplication->StartMonitoringAppOffline()); *ppApplication = pErrorApplication.release(); diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp index 6b700f876a19..86fbaf97ef9b 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp @@ -6,7 +6,8 @@ #include "requesthandler_config.h" extern bool g_fInProcessApplicationCreated; -extern std::wstring g_errorPageContent; +extern BYTE* g_errorPageContent; +extern int g_errorPageLength; // // Initialization export @@ -507,9 +508,11 @@ set_main_handler(_In_ hostfxr_main_fn main) EXTERN_C __MIDL_DECLSPEC_DLLEXPORT VOID -http_set_startup_error_page_content(_In_ LPCWSTR errorPageContent) +http_set_startup_error_page_content(_In_ byte* errorPageContent, int length) { - g_errorPageContent = std::wstring(errorPageContent); + g_errorPageContent = new BYTE[length]; + g_errorPageLength = length; + memcpy(g_errorPageContent, errorPageContent, length); } // End of export diff --git a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp index fba507132c5c..8e67c872ca82 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp @@ -302,7 +302,7 @@ FORWARDING_HANDLER::ExecuteRequestHandler() } else if (fFailedToStartKestrel && !m_pApplication->QueryConfig()->QueryDisableStartUpErrorPage()) { - ServerErrorHandler handler(*m_pW3Context, 502, 5, "Bad Gateway", hr, g_hOutOfProcessRHModule, m_pApplication->QueryConfig()->QueryDisableStartUpErrorPage(), OUT_OF_PROCESS_RH_STATIC_HTML, ""); + ServerErrorHandler handler(*m_pW3Context, 502, 5, "Bad Gateway", hr, g_hOutOfProcessRHModule, m_pApplication->QueryConfig()->QueryDisableStartUpErrorPage(), OUT_OF_PROCESS_RH_STATIC_HTML, nullptr, 0); handler.ExecuteRequestHandler(); } else diff --git a/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj b/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj index 2853fe7b6b12..faacc02ee7de 100644 --- a/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj +++ b/src/Servers/IIS/IIS/src/Microsoft.AspNetCore.Server.IIS.csproj @@ -37,6 +37,8 @@ + + diff --git a/src/Servers/IIS/IIS/src/NativeMethods.cs b/src/Servers/IIS/IIS/src/NativeMethods.cs index d4e7c0f3502e..dbc851506b98 100644 --- a/src/Servers/IIS/IIS/src/NativeMethods.cs +++ b/src/Servers/IIS/IIS/src/NativeMethods.cs @@ -148,7 +148,7 @@ private static extern unsafe int http_websockets_write_bytes( private static extern int http_get_authentication_information(IntPtr pInProcessHandler, [MarshalAs(UnmanagedType.BStr)] out string authType, out IntPtr token); [DllImport(AspNetCoreModuleDll)] - private static extern int http_set_startup_error_page_content([MarshalAs(UnmanagedType.LPWStr)]string content); + private static extern unsafe int http_set_startup_error_page_content(byte* content, int contentLength); public static void HttpPostCompletion(IntPtr pInProcessHandler, int cbBytes) { @@ -300,9 +300,12 @@ public static void HttpGetAuthenticationInformation(IntPtr pInProcessHandler, ou Validate(http_get_authentication_information(pInProcessHandler, out authType, out token)); } - public static void HttpSetStartupErrorPageContent(string content) + public static unsafe void HttpSetStartupErrorPageContent(byte[] content) { - http_set_startup_error_page_content(content); + fixed(byte* bytePtr = content) + { + http_set_startup_error_page_content(bytePtr, content.Length); + } } private static void Validate(int hr) diff --git a/src/Servers/IIS/IIS/src/StartupHook.cs b/src/Servers/IIS/IIS/src/StartupHook.cs index 334ad05a7ecc..99df5591c4be 100644 --- a/src/Servers/IIS/IIS/src/StartupHook.cs +++ b/src/Servers/IIS/IIS/src/StartupHook.cs @@ -4,11 +4,15 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; +using System.IO.Pipelines; using System.Reflection; using System.Runtime.InteropServices; -using System.Text; -using System.Text.Encodings.Web; +using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting.Views; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Server.IIS; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.StackTrace.Sources; @@ -20,173 +24,106 @@ public static void Initialize() // TODO make this unhandled exception AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) => { - var builder = new StringBuilder(); var exception = eventArgs.Exception; - // Pinvoke for content root. var iisConfigData = NativeMethods.HttpGetApplicationProperties(); var contentRoot = iisConfigData.pwzFullApplicationPath.TrimEnd(Path.DirectorySeparatorChar); + var model = new ErrorPageModel + { + RuntimeDisplayName = RuntimeInformation.FrameworkDescription + }; + var systemRuntimeAssembly = typeof(System.ComponentModel.DefaultValueAttribute).GetTypeInfo().Assembly; + var assemblyVersion = new AssemblyName(systemRuntimeAssembly.FullName).Version.ToString(); + var clrVersion = assemblyVersion; + model.RuntimeArchitecture = RuntimeInformation.ProcessArchitecture.ToString(); + var currentAssembly = typeof(ErrorPage).GetTypeInfo().Assembly; + model.CurrentAssemblyVesion = currentAssembly + .GetCustomAttribute() + .InformationalVersion; + model.ClrVersion = clrVersion; + model.OperatingSystemDescription = RuntimeInformation.OSDescription; + var exceptionDetailProvider = new ExceptionDetailsProvider( - new PhysicalFileProvider(contentRoot), - sourceCodeLineCount: 6); + new PhysicalFileProvider(contentRoot), + sourceCodeLineCount: 6); - var details = exceptionDetailProvider.GetDetails(exception); + model.ErrorDetails = exceptionDetailProvider.GetDetails(exception); - builder.Append("

An error occurred while starting the application.


"); - foreach (var detail in details) - { - var firstFrame = detail.StackFrames.FirstOrDefault(); - var location = string.Empty; - if (firstFrame != null) - { - location = firstFrame.Function; - } - - if (!string.IsNullOrEmpty(location) && firstFrame != null && !string.IsNullOrEmpty(firstFrame.File)) - { - builder.Append($"

{HtmlEncoder.Default.Encode(location)} in {HtmlEncoder.Default.Encode(Path.GetFileName(firstFrame.File))}, line {firstFrame.Line}

"); - } - else if (!string.IsNullOrEmpty(location)) - { - builder.Append($"

{HtmlEncoder.Default.Encode(location)}

"); - } - else - { - builder.Append($"

@Resources.ErrorPageHtml_UnknownLocation

"); - } - - var reflectionTypeLoadException = detail.Error as ReflectionTypeLoadException; - if (reflectionTypeLoadException != null) - { - if (reflectionTypeLoadException.LoaderExceptions.Length > 0) - { - builder.Append("

Loader Exceptions:


"); - builder.Append("
    "); - - foreach (var ex in reflectionTypeLoadException.LoaderExceptions) - { - builder.Append($"
  • {HtmlEncoder.Default.Encode(ex.Message)}
  • "); - } - builder.Append("
"); - } - } - } + var errorPage = new ErrorPage(model); + var context = new IntermediateHttpContext(); + errorPage.ExecuteAsync(context).GetAwaiter().GetResult(); + context.Response.Body.Position = 0; + var content = ((MemoryStream)context.Response.Body).ToArray(); - builder.Append("
"); - builder.Append("
    "); + NativeMethods.HttpSetStartupErrorPageContent(content); + }; + } - var exceptionCount = 0; - var stackFrameCount = 0; - var exceptionDetailId = ""; - var frameId = ""; - foreach (var errorDetail in details) - { - exceptionCount++; - exceptionDetailId = "exceptionDetail" + exceptionCount; - builder.Append("
  • "); - builder.Append($"

    {HtmlEncoder.Default.Encode(errorDetail.Error.GetType().Name)}: {HtmlEncoder.Default.Encode(errorDetail.Error.Message)}

    "); - builder.Append("
      "); - foreach (var frame in errorDetail.StackFrames) - { - stackFrameCount++; - frameId = "frame" + stackFrameCount; - builder.Append($"
    • "); - if (string.IsNullOrEmpty(frame.File)) - { - builder.Append($"

      {HtmlEncoder.Default.Encode(frame.Function)}

      "); - } - else - { - builder.Append($"

      {HtmlEncoder.Default.Encode(frame.Function)} in {HtmlEncoder.Default.Encode(Path.GetFileName(frame.File))}

      "); - } - - if (frame.Line != 0 && frame.ContextCode.Any()) - { - builder.Append($""); - builder.Append($"
      "); - if (frame.PreContextCode.Any()) - { - builder.Append($"
        "); - foreach (var line in frame.PreContextCode) - { - builder.Append($"
      1. {HtmlEncoder.Default.Encode(line)}
      2. "); - } - builder.Append("
      "); - } - builder.Append($"
        "); - foreach (var line in frame.ContextCode) - { - builder.Append($"
      1. {HtmlEncoder.Default.Encode(line)}
      2. "); - } - builder.Append("
      "); - - if (frame.PostContextCode.Any()) - { - builder.Append($"
        "); - foreach (var line in frame.PostContextCode) - { - builder.Append($"
      1. {HtmlEncoder.Default.Encode(line)}
      2. "); - } - builder.Append("
      "); - } - builder.Append($"
      "); - } - - builder.Append($"
    • "); - } - builder.Append($"
    "); - builder.Append($"
  • "); - builder.Append($"
  • "); - builder.Append("
    "); - builder.Append($"
    "); - builder.Append($"
    "); - builder.Append($""); - builder.Append($"
    "); - builder.Append($"
    "); - builder.Append($"
    {HtmlEncoder.Default.Encode(errorDetail.Error.ToString())}
    "); - builder.Append($"
    "); - builder.Append($"
    "); - builder.Append($"
  • "); - } + private class IntermediateHttpContext : HttpContext + { + public IntermediateHttpContext() + { + } - builder.Append("
"); - builder.Append($"
"); + public override IFeatureCollection Features => throw new NotImplementedException(); - builder.Append("
"); + public override HttpRequest Request => null; - var runtimeDisplayName = HtmlEncoder.Default.Encode(RuntimeInformation.FrameworkDescription); - var runtimeArchitecture = HtmlEncoder.Default.Encode(RuntimeInformation.ProcessArchitecture.ToString()); - var currentAssemblyVersion = HtmlEncoder.Default.Encode(RuntimeInformation.ProcessArchitecture.ToString()); - var systemRuntimeAssembly = typeof(System.ComponentModel.DefaultValueAttribute).GetTypeInfo().Assembly; - var clrVersion = HtmlEncoder.Default.Encode(new AssemblyName(systemRuntimeAssembly.FullName).Version.ToString()); - var operatingSystemDescription = HtmlEncoder.Default.Encode(RuntimeInformation.OSDescription); + public override HttpResponse Response { get; } = new IntermediateResponse(); - builder.Append($"{runtimeDisplayName} {runtimeArchitecture} v{clrVersion}    |   Microsoft.AspNetCore.Server.IIS version " + - $"{currentAssemblyVersion}    |    {operatingSystemDescription}    |    " + - $"Need help?"); + public override ConnectionInfo Connection => throw new NotImplementedException(); - builder.Append("
"); + public override WebSocketManager WebSockets => throw new NotImplementedException(); - NativeMethods.HttpSetStartupErrorPageContent(builder.ToString()); - }; - } + public override ClaimsPrincipal User { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public override IDictionary Items { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public override IServiceProvider RequestServices { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public override CancellationToken RequestAborted { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public override string TraceIdentifier { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public override ISession Session { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - private static string HtmlEncodeAndReplaceLineBreaks(string input) - { - if (string.IsNullOrEmpty(input)) + public override void Abort() { - return string.Empty; + throw new NotImplementedException(); } - var list = new List(); - var arr = input.Split(new[] { "\r\n" }, StringSplitOptions.None); - foreach (var a in arr) + private class IntermediateResponse : HttpResponse { - var anotherStringArr = a.Split(new[] { '\r', '\n' }, StringSplitOptions.None); - list.AddRange(anotherStringArr); - } + public override HttpContext HttpContext => throw new NotImplementedException(); - return string.Join("
" + Environment.NewLine, list); + public override int StatusCode { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + + public override IHeaderDictionary Headers => throw new NotImplementedException(); + + public override Stream Body { get; set; } = new MemoryStream(); + public override PipeWriter BodyWriter { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public override long? ContentLength { get; set; } + public override string ContentType { get; set; } + + public override IResponseCookies Cookies => throw new NotImplementedException(); + + public override bool HasStarted => throw new NotImplementedException(); + + public override void OnCompleted(Func callback, object state) + { + throw new NotImplementedException(); + } + + public override void OnStarting(Func callback, object state) + { + throw new NotImplementedException(); + } + + public override void Redirect(string location, bool permanent) + { + throw new NotImplementedException(); + } + + public override Task StartAsync(CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + } } } diff --git a/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.Designer.cs b/src/Shared/ErrorPage/ErrorPage.Designer.cs similarity index 95% rename from src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.Designer.cs rename to src/Shared/ErrorPage/ErrorPage.Designer.cs index 52a6db45d33d..9959fe9a81af 100644 --- a/src/Hosting/Hosting/src/Startup/ExceptionPage/Views/ErrorPage.Designer.cs +++ b/src/Shared/ErrorPage/ErrorPage.Designer.cs @@ -1,1055 +1,1056 @@ -namespace Microsoft.AspNetCore.Hosting.Views -{ -#line 1 "ErrorPage.cshtml" -using System - -#line default -#line hidden - ; -#line 2 "ErrorPage.cshtml" -using System.Globalization - -#line default -#line hidden - ; -#line 3 "ErrorPage.cshtml" -using System.Linq - -#line default -#line hidden - ; -#line 4 "ErrorPage.cshtml" -using System.Net - -#line default -#line hidden - ; -#line 5 "ErrorPage.cshtml" -using System.Reflection - -#line default -#line hidden - ; -#line 6 "ErrorPage.cshtml" -using Microsoft.AspNetCore.Hosting.Views - -#line default -#line hidden - ; - using System.Threading.Tasks; - - internal class ErrorPage : Microsoft.Extensions.RazorViews.BaseView - { -#line 9 "ErrorPage.cshtml" - - public ErrorPage(ErrorPageModel model) - { - Model = model; - } - - public ErrorPageModel Model { get; set; } - -#line default -#line hidden - #line hidden - public ErrorPage() - { - } - - #pragma warning disable 1998 - public override async Task ExecuteAsync() - { - WriteLiteral("\r\n"); -#line 17 "ErrorPage.cshtml" - - Response.ContentType = "text/html; charset=utf-8"; - var location = string.Empty; - -#line default -#line hidden - - WriteLiteral("\r\n