diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/AspNetCore.vcxproj b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/AspNetCore.vcxproj
index d53a438f03..db33b281cd 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/AspNetCore.vcxproj
+++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/AspNetCore.vcxproj
@@ -233,8 +233,6 @@
-
-
@@ -249,7 +247,6 @@
-
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp
index 8491edc5a4..cb4893196f 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp
+++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp
@@ -28,7 +28,10 @@ HandlerResolver::HandlerResolver(HMODULE hModule, const IHttpServer &pServer)
}
HRESULT
-HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication, const ShimOptions& pConfiguration, std::unique_ptr& pApplicationFactory)
+HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication,
+ const ShimOptions& pConfiguration,
+ std::unique_ptr& pApplicationFactory,
+ ErrorContext& errorContext)
{
HRESULT hr = S_OK;
PCWSTR pstrHandlerDllName = nullptr;
@@ -53,6 +56,7 @@ HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication
{
if (pConfiguration.QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_IN_PROCESS)
{
+ errorContext.generalErrorType = "ANCM In-Process Handler Load Failure";
std::unique_ptr options;
RETURN_IF_FAILED(HostFxrResolutionResult::Create(
@@ -66,12 +70,12 @@ HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication
auto redirectionOutput = std::make_shared();
- hr = FindNativeAssemblyFromHostfxr(*options, pstrHandlerDllName, handlerDllPath, pApplication, pConfiguration, redirectionOutput);
+ hr = FindNativeAssemblyFromHostfxr(*options, pstrHandlerDllName, handlerDllPath, pApplication, pConfiguration, redirectionOutput, errorContext);
+
+ auto output = redirectionOutput->GetOutput();
if (FAILED_LOG(hr))
{
- auto output = redirectionOutput->GetOutput();
-
EventLog::Error(
ASPNETCORE_EVENT_GENERAL_ERROR,
ASPNETCORE_EVENT_INPROCESS_RH_ERROR_MSG,
@@ -81,12 +85,20 @@ HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication
}
else
{
+ errorContext.generalErrorType = "ANCM Out-Of-Process Handler Load Failure";
+
if (FAILED_LOG(hr = FindNativeAssemblyFromGlobalLocation(pConfiguration, pstrHandlerDllName, handlerDllPath)))
{
+ auto handlerName = handlerDllPath.empty() ? s_pwzAspnetcoreOutOfProcessRequestHandlerName : handlerDllPath.c_str();
EventLog::Error(
ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING,
ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG,
- handlerDllPath.empty() ? s_pwzAspnetcoreOutOfProcessRequestHandlerName : handlerDllPath.c_str());
+ handlerName);
+
+ errorContext.detailedErrorContent = to_multi_byte_string(format(ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG, handlerName), CP_UTF8);
+ errorContext.statusCode = 500i16;
+ errorContext.subStatusCode = 36i16;
+ errorContext.errorReason = "The out of process request handler, aspnetcorev2_outofprocess.dll, could not be found next to the aspnetcorev2.dll.";
return hr;
}
@@ -96,6 +108,7 @@ HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication
hRequestHandlerDll = LoadLibrary(handlerDllPath.c_str());
RETURN_LAST_ERROR_IF_NULL(hRequestHandlerDll);
+
if (preventUnload)
{
// Pin module in memory
@@ -111,7 +124,7 @@ HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication
}
HRESULT
-HandlerResolver::GetApplicationFactory(const IHttpApplication &pApplication, std::unique_ptr& pApplicationFactory, const ShimOptions& options)
+HandlerResolver::GetApplicationFactory(const IHttpApplication& pApplication, std::unique_ptr& pApplicationFactory, const ShimOptions& options, ErrorContext& errorContext)
{
SRWExclusiveLock lock(m_requestHandlerLoadLock);
if (m_loadedApplicationHostingModel != HOSTING_UNKNOWN)
@@ -119,6 +132,12 @@ HandlerResolver::GetApplicationFactory(const IHttpApplication &pApplication, std
// Mixed hosting models
if (m_loadedApplicationHostingModel != options.QueryHostingModel())
{
+ errorContext.detailedErrorContent = to_multi_byte_string(format(ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR_MSG, pApplication.GetApplicationId(), options.QueryHostingModel()), CP_UTF8);
+ errorContext.statusCode = 500i16;
+ errorContext.subStatusCode = 34i16;
+ errorContext.generalErrorType = "ANCM Mixed Hosting Models Not Supported";
+ errorContext.errorReason = "Select a different application pool to create another application.";
+
EventLog::Error(
ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR,
ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR_MSG,
@@ -130,6 +149,13 @@ HandlerResolver::GetApplicationFactory(const IHttpApplication &pApplication, std
// Multiple in-process apps
if (m_loadedApplicationHostingModel == HOSTING_IN_PROCESS && m_loadedApplicationId != pApplication.GetApplicationId())
{
+ errorContext.detailedErrorContent = to_multi_byte_string(format(ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP_MSG, pApplication.GetApplicationId()), CP_UTF8);
+
+ errorContext.statusCode = 500i16;
+ errorContext.subStatusCode = 35i16;
+ errorContext.generalErrorType = "ANCM Multiple In-Process Applications in same Process";
+ errorContext.errorReason = "Select a different application pool to create another in-process application.";
+
EventLog::Error(
ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP,
ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP_MSG,
@@ -141,7 +167,7 @@ HandlerResolver::GetApplicationFactory(const IHttpApplication &pApplication, std
m_loadedApplicationHostingModel = options.QueryHostingModel();
m_loadedApplicationId = pApplication.GetApplicationId();
- RETURN_IF_FAILED(LoadRequestHandlerAssembly(pApplication, options, pApplicationFactory));
+ RETURN_IF_FAILED(LoadRequestHandlerAssembly(pApplication, options, pApplicationFactory, errorContext));
return S_OK;
}
@@ -181,7 +207,7 @@ HandlerResolver::FindNativeAssemblyFromGlobalLocation(
}
catch (...)
{
- EventLog::Info(
+ EventLog::Info(
ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING,
ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG,
pstrHandlerDllName);
@@ -204,7 +230,8 @@ HandlerResolver::FindNativeAssemblyFromHostfxr(
std::wstring& handlerDllPath,
const IHttpApplication &pApplication,
const ShimOptions& pConfiguration,
- std::shared_ptr stringRedirectionOutput
+ std::shared_ptr stringRedirectionOutput,
+ ErrorContext& errorContext
)
try
{
@@ -214,14 +241,25 @@ try
DWORD dwBufferSize = s_initialGetNativeSearchDirectoriesBufferSize;
DWORD dwRequiredBufferSize = 0;
- m_hHostFxrDll.Load(hostfxrOptions.GetHostFxrLocation());
-
+ try
+ {
+ m_hHostFxrDll.Load(hostfxrOptions.GetHostFxrLocation());
+ }
+ catch (...)
+ {
+ errorContext.detailedErrorContent = "Could not load hostfxr.dll.";
+ errorContext.statusCode = 500i16;
+ errorContext.subStatusCode = 32i16;
+ errorContext.generalErrorType = "ANCM Failed to Load dll";
+ errorContext.errorReason = "The application was likely published for a different bitness than w3wp.exe/iisexpress.exe is running as.";
+ throw;
+ }
{
auto redirectionOutput = LoggingHelpers::CreateOutputs(
pConfiguration.QueryStdoutLogEnabled(),
pConfiguration.QueryStdoutLogFile(),
pApplication.GetApplicationPhysicalPath(),
- std::move(stringRedirectionOutput)
+ stringRedirectionOutput
);
StandardStreamRedirection stdOutRedirection(*redirectionOutput.get(), m_pServer.IsCommandLineLaunch());
@@ -256,7 +294,16 @@ try
else
{
// If hostfxr didn't set the required buffer size, something in the app is misconfigured
- // Ex: Framework not found.
+ // This like almost always is framework not found.
+ auto output = to_multi_byte_string(stringRedirectionOutput->GetOutput(), CP_UTF8);
+ errorContext.detailedErrorContent.resize(output.length());
+ memcpy(&errorContext.detailedErrorContent[0], output.c_str(), output.length());
+
+ errorContext.statusCode = 500i16;
+ errorContext.subStatusCode = 31i16;
+ errorContext.generalErrorType = "ANCM Failed to Find Native Dependencies";
+ errorContext.errorReason = "The specified version of Microsoft.NetCore.App or Microsoft.AspNetCore.App was not found.";
+
EventLog::Error(
ASPNETCORE_EVENT_GENERAL_ERROR,
ASPNETCORE_EVENT_HOSTFXR_FAILURE_MSG
@@ -296,6 +343,16 @@ try
if (!fFound)
{
+ // This only occurs if the request handler isn't referenced by the app, which rarely happens if they are targeting the shared framework.
+ errorContext.statusCode = 500i16;
+ errorContext.subStatusCode = 33i16;
+ errorContext.generalErrorType = "ANCM Request Handler Load Failure";
+ errorContext.detailedErrorContent = to_multi_byte_string(format(ASPNETCORE_EVENT_INPROCESS_RH_REFERENCE_MSG, handlerDllPath.empty()
+ ? s_pwzAspnetcoreInProcessRequestHandlerName
+ : handlerDllPath.c_str()),
+ CP_UTF8);
+ errorContext.errorReason = "Make sure Microsoft.AspNetCore.App is referenced by your application.";
+
EventLog::Error(
ASPNETCORE_EVENT_GENERAL_ERROR,
ASPNETCORE_EVENT_INPROCESS_RH_REFERENCE_MSG,
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.h b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.h
index faa81855c3..9ab017bb50 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.h
@@ -16,11 +16,11 @@ class HandlerResolver
{
public:
HandlerResolver(HMODULE hModule, const IHttpServer &pServer);
- HRESULT GetApplicationFactory(const IHttpApplication &pApplication, std::unique_ptr& pApplicationFactory, const ShimOptions& options);
+ HRESULT GetApplicationFactory(const IHttpApplication &pApplication, std::unique_ptr& pApplicationFactory, const ShimOptions& options, ErrorContext& errorContext);
void ResetHostingModel();
private:
- HRESULT LoadRequestHandlerAssembly(const IHttpApplication &pApplication, const ShimOptions& pConfiguration, std::unique_ptr& pApplicationFactory);
+ HRESULT LoadRequestHandlerAssembly(const IHttpApplication &pApplication, const ShimOptions& pConfiguration, std::unique_ptr& pApplicationFactory, ErrorContext& errorContext);
HRESULT FindNativeAssemblyFromGlobalLocation(const ShimOptions& pConfiguration, PCWSTR libraryName, std::wstring& handlerDllPath);
HRESULT FindNativeAssemblyFromHostfxr(
const HostFxrResolutionResult& hostfxrOptions,
@@ -28,7 +28,8 @@ private:
std::wstring& handlerDllPath,
const IHttpApplication &pApplication,
const ShimOptions& pConfiguration,
- std::shared_ptr stringRedirectionOutput);
+ std::shared_ptr stringRedirectionOutput,
+ ErrorContext& errorContext);
HMODULE m_hModule;
const IHttpServer &m_pServer;
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/InProcessShimStaticHtml.htm b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/InProcessShimStaticHtml.htm
index a8c9d7fe1f..a9e6d96c75 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/InProcessShimStaticHtml.htm
+++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/InProcessShimStaticHtml.htm
@@ -2,7 +2,7 @@
- HTTP Error 500.0 - ANCM In-Process Handler Load Failure
+ HTTP Error %d.%d - %s
- HTTP Error 500.0 - ANCM In-Process Handler Load Failure
+ HTTP Error %d.%d - %s
- Common causes of this issue:
+ %s
-
- - The specified version of Microsoft.NetCore.App or Microsoft.AspNetCore.App was not found.
- - The in process request handler, Microsoft.AspNetCore.Server.IIS, was not referenced in the application.
- - ANCM could not find dotnet.
-
+ %s
Troubleshooting steps:
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/OutOfProcessShimStaticHtml.htm b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/OutOfProcessShimStaticHtml.htm
index 1194cf4025..b15ed7dccb 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/OutOfProcessShimStaticHtml.htm
+++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/OutOfProcessShimStaticHtml.htm
@@ -2,7 +2,7 @@
- HTTP Error 500.0 - ANCM Out-Of-Process Handler Load Failure
+ HTTP Error %d.%d - %s
- HTTP Error 500.0 - ANCM Out-Of-Process Handler Load Failure
+ HTTP Error %d.%d - %s
- Common causes of this issue:
-
- - The out of process request handler, aspnetcorev2_outofprocess.dll, could not be found next to the aspnetcorev2.dll.
- - Could not read configuration correctly. Check the application's associated web.config.
-
+ %s
+
+ %s
Troubleshooting steps:
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ShimOptions.cpp b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ShimOptions.cpp
index cb7f1488d7..fa1282cdb6 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ShimOptions.cpp
+++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ShimOptions.cpp
@@ -5,6 +5,7 @@
#include "StringHelpers.h"
#include "ConfigurationLoadException.h"
+#include "Environment.h"
#define CS_ASPNETCORE_HANDLER_VERSION L"handlerVersion"
@@ -41,4 +42,16 @@ ShimOptions::ShimOptions(const ConfigurationSource &configurationSource) :
m_fStdoutLogEnabled = section->GetRequiredBool(CS_ASPNETCORE_STDOUT_LOG_ENABLED);
m_struStdoutLogFile = section->GetRequiredString(CS_ASPNETCORE_STDOUT_LOG_FILE);
m_fDisableStartupPage = section->GetRequiredBool(CS_ASPNETCORE_DISABLE_START_UP_ERROR_PAGE);
+
+ // This will not include environment variables defined in the web.config.
+ // Reading environment variables can be added here, but it adds more code to the shim.
+ const auto detailedErrors = Environment::GetEnvironmentVariableValue(L"ASPNETCORE_DETAILEDERRORS").value_or(L"");
+ const auto aspnetCoreEnvironment = Environment::GetEnvironmentVariableValue(L"ASPNETCORE_ENVIRONMENT").value_or(L"");
+ const auto dotnetEnvironment = Environment::GetEnvironmentVariableValue(L"DOTNET_ENVIRONMENT").value_or(L"");
+
+ auto detailedErrorsEnabled = equals_ignore_case(L"1", detailedErrors) || equals_ignore_case(L"true", detailedErrors);
+ auto aspnetCoreEnvironmentEnabled = equals_ignore_case(L"Development", aspnetCoreEnvironment);
+ auto dotnetEnvironmentEnabled = equals_ignore_case(L"Development", dotnetEnvironment);
+
+ m_fShowDetailedErrors = detailedErrorsEnabled || aspnetCoreEnvironmentEnabled || dotnetEnvironmentEnabled;
}
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ShimOptions.h b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ShimOptions.h
index 3cfb47169e..5d1c04f8ab 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ShimOptions.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ShimOptions.h
@@ -59,6 +59,12 @@ public:
return m_fDisableStartupPage;
}
+ bool
+ QueryShowDetailedErrors() const noexcept
+ {
+ return m_fShowDetailedErrors;
+ }
+
ShimOptions(const ConfigurationSource &configurationSource);
private:
@@ -69,4 +75,5 @@ private:
std::wstring m_struStdoutLogFile;
bool m_fStdoutLogEnabled;
bool m_fDisableStartupPage;
+ bool m_fShowDetailedErrors;
};
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/applicationinfo.cpp b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/applicationinfo.cpp
index 317a8a5d4b..a0a6bfeb3b 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/applicationinfo.cpp
+++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/applicationinfo.cpp
@@ -15,6 +15,7 @@
#include "WebConfigConfigurationSource.h"
#include "ConfigurationLoadException.h"
#include "resource.h"
+#include "file_utility.h"
extern HINSTANCE g_hServerModule;
@@ -86,23 +87,39 @@ APPLICATION_INFO::CreateApplication(IHttpContext& pHttpContext)
const WebConfigConfigurationSource configurationSource(m_pServer.GetAdminManager(), pHttpApplication);
ShimOptions options(configurationSource);
- const auto hr = TryCreateApplication(pHttpContext, options);
+ ErrorContext errorContext;
+ errorContext.statusCode = 500i16;
+ errorContext.subStatusCode = 0i16;
+
+ const auto hr = TryCreateApplication(pHttpContext, options, errorContext);
if (FAILED_LOG(hr))
{
- // Log the failure and update application info to not try again
EventLog::Error(
ASPNETCORE_EVENT_ADD_APPLICATION_ERROR,
ASPNETCORE_EVENT_ADD_APPLICATION_ERROR_MSG,
pHttpApplication.GetApplicationId(),
hr);
+ auto page = options.QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_IN_PROCESS ? IN_PROCESS_SHIM_STATIC_HTML : OUT_OF_PROCESS_SHIM_STATIC_HTML;
+ std::string responseContent;
+ if (options.QueryShowDetailedErrors())
+ {
+ responseContent = FILE_UTILITY::GetHtml(g_hServerModule, page, errorContext.statusCode, errorContext.subStatusCode, errorContext.generalErrorType, errorContext.errorReason, errorContext.detailedErrorContent);
+ }
+ else
+ {
+ responseContent = FILE_UTILITY::GetHtml(g_hServerModule, page, errorContext.statusCode, errorContext.subStatusCode, errorContext.generalErrorType, errorContext.errorReason);
+ }
+
m_pApplication = make_application(
pHttpApplication,
hr,
- g_hServerModule,
options.QueryDisableStartupPage(),
- options.QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_IN_PROCESS ? IN_PROCESS_SHIM_STATIC_HTML : OUT_OF_PROCESS_SHIM_STATIC_HTML);
+ responseContent,
+ errorContext.statusCode,
+ errorContext.subStatusCode,
+ "Internal Server Error");
}
return S_OK;
}
@@ -124,14 +141,18 @@ APPLICATION_INFO::CreateApplication(IHttpContext& pHttpContext)
m_pApplication = make_application(
pHttpApplication,
E_FAIL,
- g_hServerModule);
+ false /* disableStartupPage */,
+ "" /* responseContent */,
+ 500i16 /* statusCode */,
+ 0i16 /* subStatusCode */,
+ "Internal Server Error");
return S_OK;
}
}
HRESULT
-APPLICATION_INFO::TryCreateApplication(IHttpContext& pHttpContext, const ShimOptions& options)
+APPLICATION_INFO::TryCreateApplication(IHttpContext& pHttpContext, const ShimOptions& options, ErrorContext& error)
{
const auto startupEvent = Environment::GetEnvironmentVariableValue(L"ASPNETCORE_STARTUP_SUSPEND_EVENT");
if (startupEvent.has_value())
@@ -157,7 +178,7 @@ APPLICATION_INFO::TryCreateApplication(IHttpContext& pHttpContext, const ShimOpt
}
}
- RETURN_IF_FAILED(m_handlerResolver.GetApplicationFactory(*pHttpContext.GetApplication(), m_pApplicationFactory, options));
+ RETURN_IF_FAILED(m_handlerResolver.GetApplicationFactory(*pHttpContext.GetApplication(), m_pApplicationFactory, options, error));
LOG_INFO(L"Creating handler application");
IAPPLICATION * newApplication;
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/applicationinfo.h b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/applicationinfo.h
index 252d4e0d2d..f90b0588d9 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/applicationinfo.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/applicationinfo.h
@@ -77,7 +77,7 @@ private:
CreateApplication(IHttpContext& pHttpContext);
HRESULT
- TryCreateApplication(IHttpContext& pHttpContext, const ShimOptions& options);
+ TryCreateApplication(IHttpContext& pHttpContext, const ShimOptions& options, ErrorContext& error);
IHttpServer &m_pServer;
HandlerResolver &m_handlerResolver;
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj
index fc02995961..8816dafbda 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj
@@ -196,6 +196,7 @@
+
@@ -220,11 +221,11 @@
+
-
@@ -249,6 +250,7 @@
+
@@ -277,4 +279,4 @@
-
+
\ No newline at end of file
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.cpp b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.cpp
index be6484e16b..118a67198b 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.cpp
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.cpp
@@ -45,6 +45,13 @@ Environment::GetEnvironmentVariableValue(const std::wstring & str)
throw std::system_error(GetLastError(), std::system_category(), "GetEnvironmentVariableW");
}
+ else if (requestedSize == 1)
+ {
+ // String just contains a nullcharacter, return empty string
+ // GetEnvironmentVariableW has inconsistent behavior when returning size for an empty
+ // environment variable.
+ return L"";
+ }
std::wstring expandedStr;
do
@@ -53,6 +60,10 @@ Environment::GetEnvironmentVariableValue(const std::wstring & str)
requestedSize = GetEnvironmentVariableW(str.c_str(), expandedStr.data(), requestedSize);
if (requestedSize == 0)
{
+ if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+ {
+ return std::nullopt;
+ }
throw std::system_error(GetLastError(), std::system_category(), "ExpandEnvironmentStringsW");
}
} while (expandedStr.size() != requestedSize + 1);
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxr.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxr.h
index 990963b6e7..85cae5b1ba 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxr.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxr.h
@@ -12,6 +12,16 @@ typedef INT(*hostfxr_main_fn) (DWORD argc, CONST PCWSTR argv[]);
typedef void(*corehost_error_writer_fn) (const WCHAR* message);
typedef corehost_error_writer_fn(*corehost_set_error_writer_fn) (corehost_error_writer_fn error_writer);
+struct ErrorContext
+{
+ // TODO consider adding HRESULT here
+ std::string detailedErrorContent;
+ USHORT statusCode;
+ USHORT subStatusCode;
+ std::string generalErrorType;
+ std::string errorReason;
+};
+
class HostFxrErrorRedirector: NonCopyable
{
public:
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/PollingAppOfflineApplication.cpp b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/PollingAppOfflineApplication.cpp
similarity index 100%
rename from src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/PollingAppOfflineApplication.cpp
rename to src/Servers/IIS/AspNetCoreModuleV2/CommonLib/PollingAppOfflineApplication.cpp
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/PollingAppOfflineApplication.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/PollingAppOfflineApplication.h
similarity index 100%
rename from src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/PollingAppOfflineApplication.h
rename to src/Servers/IIS/AspNetCoreModuleV2/CommonLib/PollingAppOfflineApplication.h
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorApplication.h
similarity index 58%
rename from src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h
rename to src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorApplication.h
index b5b86aa20c..6cb0cd9342 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ServerErrorApplication.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorApplication.h
@@ -9,16 +9,13 @@
class ServerErrorApplication : public PollingAppOfflineApplication
{
public:
- ServerErrorApplication(const IHttpApplication& pApplication, HRESULT hr, HINSTANCE moduleInstance)
- : ServerErrorApplication(pApplication, hr, moduleInstance, true /* disableStartupPage*/, 0 /* page */)
- {
- }
-
- ServerErrorApplication(const IHttpApplication& pApplication, HRESULT hr, HINSTANCE moduleInstance, bool disableStartupPage, int page)
+ ServerErrorApplication(const IHttpApplication& pApplication, HRESULT hr, bool disableStartupPage, const std::string& responseContent, USHORT status, USHORT substatus, const std::string& statusText)
: m_HR(hr),
m_disableStartupPage(disableStartupPage),
- m_page(page),
- m_moduleInstance(moduleInstance),
+ m_responseContent(responseContent),
+ m_statusCode(status),
+ m_subStatusCode(substatus),
+ m_statusText(statusText),
PollingAppOfflineApplication(pApplication, PollingAppOfflineApplicationMode::StopWhenAdded)
{
}
@@ -27,8 +24,8 @@ public:
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);
- *pRequestHandler = handler.release();
+ *pRequestHandler = std::make_unique(*pHttpContext, m_statusCode, m_subStatusCode, m_statusText, m_HR, m_disableStartupPage, m_responseContent).release();
+
return S_OK;
}
@@ -36,6 +33,8 @@ public:
private:
HRESULT m_HR;
bool m_disableStartupPage;
- int m_page;
- HINSTANCE m_moduleInstance;
+ std::string m_responseContent;
+ USHORT m_statusCode;
+ USHORT m_subStatusCode;
+ std::string m_statusText;
};
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h
index 3296c68c11..77d94230b2 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ServerErrorHandler.h
@@ -9,44 +9,36 @@
class ServerErrorHandler : public REQUEST_HANDLER
{
public:
- ServerErrorHandler(IHttpContext& pContext, USHORT statusCode, USHORT subStatusCode, const std::string& statusText, HRESULT hr, HINSTANCE module, bool disableStartupPage, int page) noexcept
- : ServerErrorHandler(pContext, statusCode, subStatusCode, statusText, hr, module, disableStartupPage, page, std::vector())
- {
- }
-
- ServerErrorHandler(IHttpContext& pContext, USHORT statusCode, USHORT subStatusCode, const std::string& statusText, HRESULT hr, HINSTANCE module, bool disableStartupPage, int page, const std::vector& content) noexcept
+ ServerErrorHandler(IHttpContext& pContext, USHORT statusCode, USHORT subStatusCode, const std::string& statusText, HRESULT hr, bool disableStartupPage, std::string& responseContent) 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_page(page),
- m_ExceptionInfoContent(content),
- m_moduleInstance(module)
+ m_ExceptionInfoContent(responseContent)
{
}
REQUEST_NOTIFICATION_STATUS ExecuteRequestHandler() override
{
- WriteStaticResponse(m_pContext, m_HR, m_disableStartupPage);
+ WriteResponse();
return RQ_NOTIFICATION_FINISH_REQUEST;
}
private:
- void WriteStaticResponse(IHttpContext& pContext, HRESULT hr, bool disableStartupErrorPage)
+ void WriteResponse()
{
- if (disableStartupErrorPage)
+ if (m_disableStartupPage)
{
- pContext.GetResponse()->SetStatus(m_statusCode, m_statusText.c_str(), m_subStatusCode, E_FAIL);
+ m_pHttpContext.GetResponse()->SetStatus(m_statusCode, m_statusText.c_str(), m_subStatusCode, E_FAIL);
return;
}
HTTP_DATA_CHUNK dataChunk = {};
- IHttpResponse* pResponse = pContext.GetResponse();
- pResponse->SetStatus(m_statusCode, m_statusText.c_str(), m_subStatusCode, hr, nullptr, true);
+ IHttpResponse* pResponse = m_pHttpContext.GetResponse();
+ pResponse->SetStatus(m_statusCode, m_statusText.c_str(), m_subStatusCode, m_HR, nullptr, true);
pResponse->SetHeader("Content-Type",
"text/html",
(USHORT)strlen("text/html"),
@@ -54,62 +46,16 @@ private:
);
dataChunk.DataChunkType = HttpDataChunkFromMemory;
- if (m_ExceptionInfoContent.size() > 0)
- {
- dataChunk.FromMemory.pBuffer = &m_ExceptionInfoContent[0];
- dataChunk.FromMemory.BufferLength = static_cast(m_ExceptionInfoContent.size());
- }
- else
- {
- static std::string s_html500Page = GetHtml(m_moduleInstance, m_page);
- dataChunk.FromMemory.pBuffer = s_html500Page.data();
- dataChunk.FromMemory.BufferLength = static_cast(s_html500Page.size());
- }
-
+ dataChunk.FromMemory.pBuffer = m_ExceptionInfoContent.data();
+ dataChunk.FromMemory.BufferLength = static_cast(m_ExceptionInfoContent.size());
+
pResponse->WriteEntityChunkByReference(&dataChunk);
}
- std::string
- GetHtml(HMODULE module, int page)
- {
- try
- {
- HRSRC rc = nullptr;
- HGLOBAL rcData = nullptr;
- std::string data;
- const char* pTempData = nullptr;
-
- THROW_LAST_ERROR_IF_NULL(rc = FindResource(module, MAKEINTRESOURCE(page), RT_HTML));
- THROW_LAST_ERROR_IF_NULL(rcData = LoadResource(module, rc));
- auto const size = SizeofResource(module, rc);
- THROW_LAST_ERROR_IF(size == 0);
- 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 (additionalErrorLink.has_value())
- {
- additionalHtml = format(" %S and ", additionalErrorLink->c_str(), additionalErrorLink->c_str());
- }
-
- return format(data, additionalHtml.c_str());
- }
- catch (...)
- {
- OBSERVE_CAUGHT_EXCEPTION();
- return "";
- }
- }
-
- IHttpContext& m_pContext;
HRESULT m_HR;
bool m_disableStartupPage;
- int m_page;
- HINSTANCE m_moduleInstance;
USHORT m_statusCode;
USHORT m_subStatusCode;
std::string m_statusText;
- std::vector m_ExceptionInfoContent;
+ std::string& m_ExceptionInfoContent;
};
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/file_utility.cpp b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/file_utility.cpp
index 2831eac64d..fb10427e3f 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/file_utility.cpp
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/file_utility.cpp
@@ -6,6 +6,7 @@
#include
#include "debugutil.h"
#include "exceptions.h"
+#include "Environment.h"
HRESULT
FILE_UTILITY::IsPathUnc(
@@ -167,3 +168,53 @@ Finished:
return hr;
}
+std::string FILE_UTILITY::GetHtml(HMODULE module, int page, USHORT statusCode, USHORT subStatusCode, const std::string& speicificReasonPhrase, const std::string& solution)
+{
+ return GetHtml(module, page, statusCode, subStatusCode, speicificReasonPhrase, solution, std::string());
+}
+
+std::string
+FILE_UTILITY::GetHtml(HMODULE module, int page, USHORT statusCode, USHORT subStatusCode, const std::string& specificReasonPhrase, const std::string& errorReason, const std::string& specificError)
+{
+ try
+ {
+ HRSRC rc = nullptr;
+ HGLOBAL rcData = nullptr;
+ std::string data;
+ const char* pTempData = nullptr;
+
+ THROW_LAST_ERROR_IF_NULL(rc = FindResource(module, MAKEINTRESOURCE(page), RT_HTML));
+ THROW_LAST_ERROR_IF_NULL(rcData = LoadResource(module, rc));
+ auto const size = SizeofResource(module, rc);
+ THROW_LAST_ERROR_IF(size == 0);
+ 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 (additionalErrorLink.has_value())
+ {
+ additionalHtml = format(" %S and ", additionalErrorLink->c_str(), additionalErrorLink->c_str());
+ }
+
+ std::string formattedError;
+ if (!specificError.empty())
+ {
+ formattedError = format("Specific error detected by ANCM:
%s
", specificError.c_str());
+ }
+
+ std::string formattedErrorReason;
+ if (!errorReason.empty())
+ {
+ formattedErrorReason = format(" Common solutions to this issue:
%s", errorReason.c_str());
+ }
+
+ return format(data, statusCode, subStatusCode, specificReasonPhrase.c_str(), statusCode, subStatusCode, specificReasonPhrase.c_str(), formattedErrorReason.c_str(), formattedError.c_str(), additionalHtml.c_str());
+ }
+ catch (...)
+ {
+ OBSERVE_CAUGHT_EXCEPTION();
+ return "";
+ }
+}
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/file_utility.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/file_utility.h
index 686e810cbe..fc3ce8935b 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/file_utility.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/file_utility.h
@@ -28,7 +28,11 @@ public:
static
std::string
- GetHtml(HMODULE module, int page);
+ GetHtml(HMODULE module, int page, USHORT statusCode, USHORT subStatusCode, const std::string& speicificReasonPhrase, const std::string& solution);
+
+ static
+ std::string
+ GetHtml(HMODULE module, int page, USHORT statusCode, USHORT subStatusCode, const std::string& speicificReasonPhrase, const std::string& solution, const std::string& error);
private:
static
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/requesthandler.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/requesthandler.h
index 6274efc07e..1c78fcd0ca 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/requesthandler.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/requesthandler.h
@@ -75,7 +75,7 @@ public:
{
}
-private:
+protected:
IHttpContext& m_pHttpContext;
mutable LONG m_cRefs = 1;
};
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/resources.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/resources.h
index 04ee2e0944..9535d1c0cb 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/resources.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/resources.h
@@ -43,7 +43,7 @@
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_MSG L"Application '%s' with physical root '%s' hit unexpected managed exception, exception code = '0x%x'. Please check the stderr logs for more information."
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_STDOUT_MSG L"Application '%s' with physical root '%s' hit unexpected managed exception, exception code = '0x%x'. First 30KB characters of captured stdout and stderr logs:\r\n%s"
#define ASPNETCORE_EVENT_INPROCESS_RH_ERROR_MSG L"Could not find 'aspnetcorev2_inprocess.dll'. Exception message:\r\n%s"
-#define ASPNETCORE_EVENT_INPROCESS_RH_REFERENCE_MSG L"Could not find the assembly '%s' referenced for the in-process application. Please confirm the Microsoft.AspNetCore.Server.IIS package is referenced in your application."
+#define ASPNETCORE_EVENT_INPROCESS_RH_REFERENCE_MSG L"Could not find the assembly '%s' referenced for the in-process application. Please confirm the Microsoft.AspNetCore.Server.IIS or Microsoft.AspNetCore.App is referenced in your application."
#define ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG L"Could not find the assembly '%s' for out-of-process application. Please confirm the assembly is installed correctly for IIS or IISExpress."
#define ASPNETCORE_EVENT_INPROCESS_START_SUCCESS_MSG L"Application '%s' started successfully."
#define ASPNETCORE_EVENT_INPROCESS_START_ERROR_MSG L"Application '%s' failed to start. Exception message:\r\n%s"
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhStaticHtml.htm b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhStaticHtml.htm
index 59d6b0dacb..8783b58adb 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhStaticHtml.htm
+++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessRhStaticHtml.htm
@@ -2,7 +2,7 @@
- HTTP Error 500.30 - ANCM In-Process Start Failure
+ HTTP Error %d.%d - %s
- HTTP Error 500.30 - ANCM In-Process Start Failure
+ HTTP Error %d.%d - %s
- Common causes of this issue:
-
- - The application failed to start
- - The application started but then stopped
- - The application started but threw an exception during startup
-
+ %s
+
+ %s
Troubleshooting steps:
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h
index 6db5fee164..d3e50e620f 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/StartupExceptionApplication.h
@@ -13,15 +13,18 @@ public:
StartupExceptionApplication(
IHttpServer& pServer,
IHttpApplication& pApplication,
- HINSTANCE moduleInstance,
BOOL disableLogs,
HRESULT hr,
- std::vector&& errorPageContent
- )
+ const std::string& errorPageContent,
+ USHORT statusCode,
+ USHORT subStatusCode,
+ const std::string& statusText)
: m_disableLogs(disableLogs),
m_HR(hr),
- m_moduleInstance(moduleInstance),
- m_errorPageContent(std::move(errorPageContent)),
+ m_error(errorPageContent),
+ m_statusCode(statusCode),
+ m_subStatusCode(subStatusCode),
+ m_statusText(std::move(statusText)),
InProcessApplicationBase(pServer, pApplication)
{
}
@@ -30,15 +33,17 @@ public:
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, m_errorPageContent);
+ *pRequestHandler = new ServerErrorHandler(*pHttpContext, m_statusCode, m_subStatusCode, m_statusText, m_HR, m_disableLogs, m_error);
return S_OK;
}
private:
- std::vector m_errorPageContent;
+ std::string m_error;
BOOL m_disableLogs;
HRESULT m_HR;
- HINSTANCE m_moduleInstance;
+ USHORT m_statusCode;
+ USHORT m_subStatusCode;
+ std::string m_statusText;
};
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp
index 710bbee754..cd9261a56c 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp
+++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/dllmain.cpp
@@ -17,6 +17,7 @@
#include "WebConfigConfigurationSource.h"
#include "ConfigurationLoadException.h"
#include "StartupExceptionApplication.h"
+#include "file_utility.h"
DECLARE_DEBUG_PRINT_OBJECT("aspnetcorev2_inprocess.dll");
@@ -28,7 +29,7 @@ HINSTANCE g_hWinHttpModule;
HINSTANCE g_hAspNetCoreModule;
HANDLE g_hEventLog = NULL;
bool g_fInProcessApplicationCreated = false;
-std::vector g_errorPageContent;
+std::string g_errorPageContent;
HINSTANCE g_hServerModule;
HRESULT
@@ -120,6 +121,10 @@ CreateApplication(
g_fInProcessApplicationCreated = true;
std::unique_ptr inProcessApplication;
+
+ // TODO not sure how easy it will be to untangle errors here
+ // ErrorContext errorContext;
+
if (!FAILED_LOG(hr = IN_PROCESS_APPLICATION::Start(*pServer, pSite, *pHttpApplication, pParameters, nParameters, inProcessApplication)))
{
*ppApplication = inProcessApplication.release();
@@ -129,7 +134,20 @@ 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, std::move(g_errorPageContent));
+ auto pErrorApplication = std::make_unique(*pServer,
+ *pHttpApplication,
+ options->QueryDisableStartUpErrorPage(),
+ hr,
+ FILE_UTILITY::GetHtml(g_hServerModule,
+ IN_PROCESS_RH_STATIC_HTML,
+ 500i16,
+ 30i16,
+ "ANCM In-Process Start Failure",
+ "- The application failed to start
- The application started but then stopped
- The application started but threw an exception during startup
",
+ g_errorPageContent),
+ 500i16,
+ 30i16,
+ "Internal Server Error");
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 e52ec8c8e4..a7bcaa3675 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp
+++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/managedexports.cpp
@@ -7,7 +7,7 @@
#include "EventLog.h"
extern bool g_fInProcessApplicationCreated;
-extern std::vector g_errorPageContent;
+extern std::string g_errorPageContent;
extern IHttpServer* g_pHttpServer;
//
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRhStaticHtml.htm b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRhStaticHtml.htm
index e7d2f04e7c..bedf0a8dce 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRhStaticHtml.htm
+++ b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/OutOfProcessRhStaticHtml.htm
@@ -2,7 +2,7 @@
- HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure
+ HTTP Error %d.%d - %s
- HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure
+ HTTP Error %d.%d - %s
- Common causes of this issue:
+ %s
-
- - The application process failed to start
- - The application process started but then stopped
- - The application process started but failed to listen on the configured port
-
+ %s
- Troubleshooting steps:
+ Troubleshooting steps:
- Check the system event log for error messages
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp
index 551d10c9f9..4fbf2abf40 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp
+++ b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp
@@ -4,8 +4,10 @@
#include "forwardinghandler.h"
#include "url_utility.h"
#include "exceptions.h"
+#include "ServerErrorApplication.h"
#include "ServerErrorHandler.h"
#include "resource.h"
+#include "file_utility.h"
// Just to be aware of the FORWARDING_HANDLER object size.
C_ASSERT(sizeof(FORWARDING_HANDLER) <= 632);
@@ -302,7 +304,21 @@ Failure:
}
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);
+ static std::string htmlResponse = FILE_UTILITY::GetHtml(g_hOutOfProcessRHModule,
+ OUT_OF_PROCESS_RH_STATIC_HTML,
+ 502,
+ 5,
+ "ANCM Out-Of-Process Startup Failure",
+ "- The application process failed to start
- The application process started but then stopped
- The application process started but failed to listen on the configured port
");
+
+ ServerErrorHandler handler(*m_pW3Context,
+ 502,
+ 5,
+ "Bad Gateway",
+ hr,
+ m_pApplication->QueryConfig()->QueryDisableStartUpErrorPage(),
+ htmlResponse);
+
handler.ExecuteRequestHandler();
}
else
diff --git a/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/StartupTests.cs b/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/StartupTests.cs
index 4374ba519a..7acbc1d2e3 100644
--- a/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/StartupTests.cs
+++ b/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/StartupTests.cs
@@ -7,6 +7,7 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
+using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
@@ -268,11 +269,60 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
Path.Combine(deploymentResult.ContentRoot, "aspnetcorev2_inprocess.dll"),
Path.Combine(deploymentResult.ContentRoot, "hostfxr.dll"),
true);
- await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult);
+
+ if (DeployerSelector.HasNewShim)
+ {
+ await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult, "HTTP Error 500.32 - ANCM Failed to Load dll");
+ }
+ else
+ {
+ await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult);
+ }
EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessHostfxrInvalid(deploymentResult), Logger);
}
+ [ConditionalFact]
+ public async Task PublishWithWrongBitness()
+ {
+ var deploymentParameters = Fixture.GetBaseDeploymentParameters(Fixture.InProcessTestSite);
+
+ if (deploymentParameters.ServerType == ServerType.IISExpress)
+ {
+ // TODO skip conditions for IISExpress
+ return;
+ }
+
+ deploymentParameters.ApplicationType = ApplicationType.Standalone;
+ deploymentParameters.AddServerConfigAction(element =>
+ {
+ element.RequiredElement("system.applicationHost").RequiredElement("applicationPools").RequiredElement("add").SetAttributeValue("enable32BitAppOnWin64", "true");
+ });
+
+ // Change ANCM dll to 32 bit
+ deploymentParameters.AddServerConfigAction(
+ element =>
+ {
+ var ancmElement = element
+ .RequiredElement("system.webServer")
+ .RequiredElement("globalModules")
+ .Elements("add")
+ .FirstOrDefault(e => e.Attribute("name").Value == "AspNetCoreModuleV2");
+
+ ancmElement.SetAttributeValue("image", ancmElement.Attribute("image").Value.Replace("x64", "x86"));
+ });
+ var deploymentResult = await DeployAsync(deploymentParameters);
+
+ if (DeployerSelector.HasNewShim)
+ {
+ await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult, "500.32 - ANCM Failed to Load dll");
+ }
+ else
+ {
+ await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult, "500.0 - ANCM In-Process Handler Load Failure");
+ }
+ }
+
[ConditionalFact]
[RequiresNewShim]
public async Task RemoveHostfxrFromApp_InProcessHostfxrLoadFailure()
@@ -283,7 +333,15 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
// We don't distinguish between load failure types so making dll empty should be enough
File.WriteAllText(Path.Combine(deploymentResult.ContentRoot, "hostfxr.dll"), "");
- await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult);
+
+ if (DeployerSelector.HasNewShim)
+ {
+ await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult, "HTTP Error 500.32 - ANCM Failed to Load dll");
+ }
+ else
+ {
+ await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult);
+ }
EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessHostfxrUnableToLoad(deploymentResult), Logger);
}
@@ -295,7 +353,14 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
var deploymentResult = await DeployAsync(deploymentParameters);
Helpers.ModifyFrameworkVersionInRuntimeConfig(deploymentResult);
- await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult);
+ if (DeployerSelector.HasNewShim)
+ {
+ await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult, "HTTP Error 500.31 - ANCM Failed to Find Native Dependencies");
+ }
+ else
+ {
+ await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult);
+ }
EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessFailedToFindNativeDependencies(deploymentResult), Logger);
}
@@ -309,14 +374,23 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
File.Delete(Path.Combine(deploymentResult.ContentRoot, "aspnetcorev2_inprocess.dll"));
- await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult);
-
- if (DeployerSelector.IsForwardsCompatibilityTest)
+ if (DeployerSelector.HasNewShim && DeployerSelector.HasNewHandler)
{
+ await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult, "HTTP Error 500.33 - ANCM Request Handler Load Failure ");
+
+ EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessFailedToFindRequestHandler(deploymentResult), Logger);
+ }
+ else if (DeployerSelector.HasNewShim)
+ {
+ // Forwards compat tests fail earlier due to a error with the M.AspNetCore.Server.IIS package.
+ await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult, "HTTP Error 500.31 - ANCM Failed to Find Native Dependencies");
+
EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessFailedToFindNativeDependencies(deploymentResult), Logger);
}
else
{
+ await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult);
+
EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessFailedToFindRequestHandler(deploymentResult), Logger);
}
}
@@ -750,11 +824,23 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
});
}
- private async Task AssertSiteFailsToStartWithInProcessStaticContent(IISDeploymentResult deploymentResult)
+ private Task AssertSiteFailsToStartWithInProcessStaticContent(IISDeploymentResult deploymentResult)
{
- var response = await deploymentResult.HttpClient.GetAsync("/HelloWorld");
+ return AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult, "HTTP Error 500.0 - ANCM In-Process Handler Load Failure");
+ }
+
+ private async Task AssertSiteFailsToStartWithInProcessStaticContent(IISDeploymentResult deploymentResult, string error)
+ {
+ HttpResponseMessage response = null;
+
+ // Make sure strings aren't freed.
+ for (var i = 0; i < 2; i++)
+ {
+ response = await deploymentResult.HttpClient.GetAsync("/HelloWorld");
+ }
+
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
- Assert.Contains("HTTP Error 500.0 - ANCM In-Process Handler Load Failure", await response.Content.ReadAsStringAsync());
+ Assert.Contains(error, await response.Content.ReadAsStringAsync());
StopServer();
}
}
diff --git a/src/Servers/IIS/IIS/test/Common.FunctionalTests/MultiApplicationTests.cs b/src/Servers/IIS/IIS/test/Common.FunctionalTests/MultiApplicationTests.cs
index 87d9c73dd0..d22856610f 100644
--- a/src/Servers/IIS/IIS/test/Common.FunctionalTests/MultiApplicationTests.cs
+++ b/src/Servers/IIS/IIS/test/Common.FunctionalTests/MultiApplicationTests.cs
@@ -47,6 +47,12 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
Assert.Equal(200, (int)result1.StatusCode);
Assert.Equal(500, (int)result2.StatusCode);
StopServer();
+
+ if (DeployerSelector.HasNewShim)
+ {
+ Assert.Contains("500.35 - ANCM Multiple In-Process Applications in same Process", await result2.Content.ReadAsStringAsync());
+ }
+
EventLogHelpers.VerifyEventLogEvent(result, EventLogHelpers.OnlyOneAppPerAppPool(), Logger);
}
@@ -68,6 +74,12 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
Assert.Equal(200, (int)result1.StatusCode);
Assert.Equal(500, (int)result2.StatusCode);
StopServer();
+
+ if (DeployerSelector.HasNewShim)
+ {
+ Assert.Contains("500.34 - ANCM Mixed Hosting Models Not Supported", await result2.Content.ReadAsStringAsync());
+ }
+
EventLogHelpers.VerifyEventLogEvent(result, "Mixed hosting model is not supported.", Logger);
}
diff --git a/src/Servers/IIS/IIS/test/Common.FunctionalTests/Utilities/EventLogHelpers.cs b/src/Servers/IIS/IIS/test/Common.FunctionalTests/Utilities/EventLogHelpers.cs
index d2a94632c4..a487ba20dd 100644
--- a/src/Servers/IIS/IIS/test/Common.FunctionalTests/Utilities/EventLogHelpers.cs
+++ b/src/Servers/IIS/IIS/test/Common.FunctionalTests/Utilities/EventLogHelpers.cs
@@ -259,7 +259,15 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
public static string InProcessFailedToFindRequestHandler(IISDeploymentResult deploymentResult)
{
- return "Could not find the assembly '(.*)' referenced for the in-process application. Please confirm the Microsoft.AspNetCore.Server.IIS package is referenced in your application.";
+ if (DeployerSelector.HasNewShim)
+ {
+ return "Could not find the assembly '(.*)' referenced for the in-process application. Please confirm the Microsoft.AspNetCore.Server.IIS or Microsoft.AspNetCore.App is referenced in your application.";
+
+ }
+ else
+ {
+ return "Could not find the assembly '(.*)' referenced for the in-process application. Please confirm the Microsoft.AspNetCore.Server.IIS package is referenced in your application.";
+ }
}
public static string CouldNotStartStdoutFileRedirection(string file, IISDeploymentResult deploymentResult)
diff --git a/src/Servers/IIS/IntegrationTesting.IIS/src/IISDeploymentParameters.cs b/src/Servers/IIS/IntegrationTesting.IIS/src/IISDeploymentParameters.cs
index 04d4dfa7ce..b57a68eff1 100644
--- a/src/Servers/IIS/IntegrationTesting.IIS/src/IISDeploymentParameters.cs
+++ b/src/Servers/IIS/IntegrationTesting.IIS/src/IISDeploymentParameters.cs
@@ -47,6 +47,5 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
public IDictionary WebConfigBasedEnvironmentVariables { get; set; } = new Dictionary();
public IDictionary HandlerSettings { get; set; } = new Dictionary();
-
}
}