Over the past weekend I installed SQL Server 2005 Express Reporting Services according to the directions in KB934164 on my Windows 7 machine (which did not go particularly smoothly due to problems with the default Application Pool Identity that caused some Reporting Services Configuration steps to fail... but that is another story). Returning to developing ASP.NET in VS2010 I found that most pages of the site I am working on would no longer load in the ASP.NET Development Server for debugging. The failing pages produced the following error message:
Failed to map the path '/'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Failed to map the path '/'.
Source Error:
[No relevant source lines]
Source File: source file.cs Line: 0
Stack Trace:
[InvalidOperationException: Failed to map the path '/'.]
System.Web.Configuration.ProcessHostConfigUtils.MapPathActual(String siteName, VirtualPath path) +253
System.Web.Configuration.ProcessHostMapPath.MapPathCaching(String siteID, VirtualPath path) +669
System.Web.Configuration.ProcessHostMapPath.GetPathConfigFilenameWorker(String siteID, VirtualPath path, String& directory, String& baseName) +19
System.Web.Configuration.ProcessHostMapPath.System.Web.Configuration.IConfigMapPath.GetPathConfigFilename(String siteID, String path, String& directory, String& baseName) +37
System.Web.Configuration.HostingPreferredMapPath.GetPathConfigFilename(String siteID, String path, String& directory, String& baseName) +75
System.Web.Configuration.WebConfigurationHost.GetStreamName(String configPath) +8848790
System.Configuration.Internal.DelegatingConfigHost.GetStreamName(String configPath) +13
System.Configuration.BaseConfigurationRecord.InitConfigFromFile() +154
[ConfigurationErrorsException: An error occurred loading a configuration file: Failed to map the path '/'.]
System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors(Boolean ignoreLocal) +650948
System.Configuration.BaseConfigurationRecord.ThrowIfParseErrors(ConfigurationSchemaErrors schemaErrors) +31
System.Configuration.Configuration..ctor(String locationSubPath, Type typeConfigHost, Object[] hostInitConfigurationParams) +356
System.Configuration.Internal.InternalConfigConfigurationFactory.System.Configuration.Internal.IInternalConfigConfigurationFactory.Create(Type typeConfigHost, Object[] hostInitConfigurationParams) +29
System.Web.Configuration.WebConfigurationHost.OpenConfiguration(WebLevel webLevel, ConfigurationFileMap fileMap, VirtualPath path, String site, String locationSubPath, String server, String userName, String password, IntPtr tokenHandle) +775
System.Web.Configuration.WebConfigurationManager.OpenWebConfigurationImpl(WebLevel webLevel, ConfigurationFileMap fileMap, String path, String site, String locationSubPath, String server, String userName, String password, IntPtr userToken) +84
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(String path) +36
Microsoft.Reporting.WebForms.ReportViewer.ConfigContainsHandler() +87
Microsoft.Reporting.WebForms.ReportViewer.OnInit(EventArgs e) +111
System.Web.UI.Control.InitRecursive(Control namingContainer) +333
System.Web.UI.Control.InitRecursive(Control namingContainer) +210
System.Web.UI.Control.InitRecursive(Control namingContainer) +210
System.Web.UI.Control.InitRecursive(Control namingContainer) +210
System.Web.UI.Control.InitRecursive(Control namingContainer) +210
System.Web.UI.Control.InitRecursive(Control namingContainer) +210
System.Web.UI.Control.InitRecursive(Control namingContainer) +210
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +6741
System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +242
System.Web.UI.Page.ProcessRequest() +80
System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context) +21
System.Web.UI.Page.ProcessRequest(HttpContext context) +49
pageclass.ProcessRequest(HttpContext context) in source file.cs:0
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
The error could easily be reproduced by calling System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.ApplicationPath)
.
After a bit of searching, I found several discussions of the problem (or very similar problems) and all of the posts that contained a solution involved running Visual Studio as Administrator (e.g. Gabe Sumner on Sitefinity or Miha Markič on Righthand Blogs). I found this solution unacceptable (for a number of reasons) and decided to dig deeper.
After much tracing and browsing around in .NET Reflector, I determined that System.Web.Configuration.ProcessHostConfigUtils
makes calls to several external functions in System.Web.Hosting.UnsafeIISMethods
which were failing. Although these calls failed, the code in ProcessHostConfigUtils
ignores the failures up until it throws the nearly useless message quoted above (rather than using the failure message from the UnsafeIISMethods
methods). Using reflection, I invoked the external methods directly, then converted the HRESULT to an exception using System.Runtime.InteropServices.Marshal.GetExceptionForHR
and received the following error message:
Filename: redirection.config
Error: Cannot read configuration file due to insufficient permissions
Finally! Something useful. So I granted my user account read permission on C:\Windows\System32\inetsrv\config and the problem was solved (note that I don't have any sensitive information in this directory which would need to remain private, so I don't have a problem with extra read-only access).
It seems very odd that this file would be loaded at all, given that IIS is not configured with the "shared configuration" feature that uses redirection.config (in fact it has the default configuration in every way). It also seems strange that the code would need to consult the global IIS configuration, although this could be due to any number of reasons (legitimate or due to code which makes incorrect assumptions about IIS and the ASP.NET Development Server co-existing on a machine). However, since all of the code necessary to reproduce the problem is outside of my control, there isn't much more I can do. Enjoy the workaround.