I have just created a customized VirtualPathProvider for my ASP.NET web application. It basically maps all virtual files in "~/Storage" and subdirectories to a directory other than the solution's directory.
Code essentials
private bool IsPathVirtual(string virtualPath)
{
String checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
return checkPath.StartsWith(VirtualRootPath, StringComparison.InvariantCultureIgnoreCase);
}
public override bool DirectoryExists(string virtualDir)
{
return IsPathVirtual(virtualDir) ? ((FileSystemVirtualDirectory)GetDirectory(virtualDir)).Exists() : Previous.DirectoryExists(virtualDir);
}
public override bool FileExists(string virtualPath)
{
return IsPathVirtual(virtualPath) ? ((FileSystemVirtualFile)GetFile(virtualPath)).Exists() : Previous.FileExists(virtualPath);
}
In my case VirtualRootPath = "~/Storage"
, but that it configurable.
The problem
In IIS Express, when I debug via Visual Studio, the two public methods, required to resolve a virtual path, are not always called.
- Calling
http://localhost:7749/Storage
triggers breakpoints on both methods. A 404 error is returned and desired. This is a correct behaviour to me - Calling
http://localhost:7749/Storage/ExistingFile.txt
doesn't trigger debug, and a different 404 error is returned. This is not correct
The difference between the two 404 errors is that when I call for the directory, it's ASP.NET responding (Server error in application '/'
) but when I call for the file inside that directory, it's IIS 8.0 responding (HTTP Error 404.0 - Not Found
).
The question
Why, even if I correctly registered the VirtualPathProvider
in my HostingEnvironment
, doesn't IIS 8.0 let ASP.NET pipeline handle the HTTP request so it could be resolved correctly?
The workaround
After reading VirtualPathProvider doesn't (quite) work in production on IIS 7.5 I realized it could be a Web.config
problem. Judging from the other question, it looks like that IIS handles certain file extensions independently, no matter if ASP.NET maps those to a virtual resource, a controller, or anything else. So, since I was trying to read an XML file (and perhaps not a JPEG), IIS didn't bother ASP.NET.
The workaround has been putting this line in Web.config
's system.webServer.handlers
section:
<add name="AspNetStaticFileHandler-XML" path="*.xml" verb="*" type="System.Web.StaticFileHandler" />
But this workaround works only for XML files. How to make a permanent fix that works for all files under the storage directory?