Custom Virtual Path Provider in IIS

What is the correct configuration for implementing a custom virtual path provider in IIS 7.5? The following code works as expected when starting from Visual Studio using the ASP.NET development server, but does not load the image when starting 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

The default site without configuration changes.

+4
source share
3 answers

Here is what I found to “fix” my problem.

http://sunali.com/2008/01/09/virtualpathprovider-in-precompiled-web-sites/

In short:

HostingEnviornment explicitly ignores virtual path providers on precompiled sites. You can get around this limitation by using reflection to invoke an internal version that omits this check. So 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()}); 
+6
source

I had the same problem, but Tom Clarkson led me on the right path, he is absolutely right, because you need additional configuration so that IIS serves the content provider as 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 can also register "wildcard httphandler" in a special place (for example, "/ MyVirtualFiles"), which can be useful if the virtual path provider serves many different types of files.

 <location path="MyVirtualFiles"> <system.web> <httpHandlers> <add path="*" verb="*" type="System.Web.StaticFileHandler" validate="true" /> </httpHandlers> </system.web> </location> 
+5
source

When FileExists returns true, it is interpreted as "there is a file, IIS can serve it without ASP.NET." To get the next step in actually downloading the file to go through the virtual path provider, you need to configure IIS to use ASP.NET to serve all image files and add the code to global.asax or the http handler that your virtual path provider will use.

+1
source

All Articles