What is the correct configuration to implement a custom virtual path provider in IIS 7.5? The following code works as expected when run from Visual Studio using the ASP.NET Development Server but does not load the image when run from IIS.
.NET 4.0 Project File
CustomVirtualPathProvider.zip - SkyDrive file
Web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Default.aspx
<%@ Page Title="Home Page" Language="C#" AutoEventWireup="true" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Virtual Path Provider</title>
</head>
<body>
<img src="Box.png" />
</body>
</html>
Global.asax
public class Global : System.Web.HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new WebApplication1.CustomVirtualPathProvider());
}
}
CustomVirtualFile.cs
public class CustomVirtualFile : System.Web.Hosting.VirtualFile
{
private string _VirtualPath;
public CustomVirtualFile(string virtualPath) : base(virtualPath)
{
_VirtualPath = virtualPath.Replace("/", string.Empty);
}
public override Stream Open()
{
string ImageFile =
System.IO.Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, @"Crazy\Image\Path", _VirtualPath);
return System.IO.File.Open(ImageFile, FileMode.Open, FileAccess.Read);
}
}
CustomVirtualPathProvider.cs
public class CustomVirtualPathProvider : System.Web.Hosting.VirtualPathProvider
{
Collection<string> ImageTypes;
public CustomVirtualPathProvider() : base()
{
ImageTypes = new Collection<string>();
ImageTypes.Add(".PNG");
ImageTypes.Add(".GIF");
}
public override bool FileExists(string virtualPath)
{
if (IsImage(virtualPath))
{
return true;
}
return base.FileExists(virtualPath);
}
public override System.Web.Hosting.VirtualFile GetFile(string virtualPath)
{
if (IsImage(virtualPath))
{
return new CustomVirtualFile(virtualPath);
}
return base.GetFile(virtualPath);
}
private bool IsImage(string file)
{
return ImageTypes.IndexOf(file.ToUpperInvariant().Substring(file.Length - 4, 4)) > -1;
}
}
Filesystem
\Crazy\Image\Path\Box.png
IIS Configuration
Default site with no configuration changes.
Here is what I found to "fix" my issue.
http://sunali.com/2008/01/09/virtualpathprovider-in-precompiled-web-sites/
In brief:
HostingEnviornment explicitly ignores Virtual Path Providers in precompiled sites. You can circumvent this limitation by using reflection to call an internal version that omits this check. Thus, instead of calling
HostingEnviornment.RegisterVirtualPathProvider(new EmbeddedViewVirtualPathProvider();
call this instead:
typeof(HostingEnvironment).GetMethod("RegisterVirtualPathProviderInternal",
BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.NonPublic)
.Invoke(null, new object[] {new EmbeddedViewPathProvider()});
I had the same problem but Tom Clarkson led me on the right track, he's absolutely right in that you need additional configuration in order to make IIS serve the content provider by the virtual path provider. I found a solution here
Here is an example web.config-snippet that I think will work for you
<system.web>
<httpHandlers>
<add path="*.png" verb="*" type="System.Web.StaticFileHandler" validate="true" />
<add path="*.gif" verb="*" type="System.Web.StaticFileHandler" validate="true" />
</httpHandlers>
</system.web>
You could also register a "wildcard httphandler" under a special location (eg "/MyVirtualFiles"), which might be useful if your virtual path provider serves many different file types.
<location path="MyVirtualFiles">
<system.web>
<httpHandlers>
<add path="*" verb="*" type="System.Web.StaticFileHandler" validate="true" />
</httpHandlers>
</system.web>
</location>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With