Пользовательский поставщик виртуального пути в IIS

Какова правильная конфигурация для реализации настраиваемого поставщика виртуального пути в IIS 7.5? Следующий код работает должным образом при запуске из Visual Studio с помощью сервера разработки ASP.NET, но не загружает изображение при запуске из IIS.

Файл проекта .NET 4.0

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());
    }
}

Пользовательский виртуальный файл.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;
    }
}

Файловая система

\Crazy\Image\Path\Box.png

Конфигурация IIS

Сайт по умолчанию без изменений конфигурации.


person Robert    schedule 20.11.2010    source источник
comment
вы пытались отладить и взломать свой код? вызывается Application_Start, как насчет вашего конструктора CustomVirtualPathProvider или любого из его методов?   -  person Pauli Østerø    schedule 13.12.2010


Ответы (3)


Вот что я нашел, чтобы «исправить» мою проблему.

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

Вкратце:

HostingEnviornment явно игнорирует поставщиков виртуальных путей в предварительно скомпилированных сайтах. Вы можете обойти это ограничение, используя отражение для вызова внутренней версии, которая пропускает эту проверку. Таким образом, вместо вызова

HostingEnviornment.RegisterVirtualPathProvider(new EmbeddedViewVirtualPathProvider();

назовите это вместо этого:

typeof(HostingEnvironment).GetMethod("RegisterVirtualPathProviderInternal",
      BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.NonPublic)
    .Invoke(null, new object[] {new EmbeddedViewPathProvider()});
person Adam Carr    schedule 13.12.2010
comment
Что означает... это еще не ответ. Пожалуйста, добавьте в качестве комментария вместо этого :) - person Pauli Østerø; 13.12.2010

У меня была та же проблема, но Том Кларксон привел меня на правильный путь, он абсолютно прав в том, что вам нужна дополнительная настройка, чтобы заставить IIS обслуживать поставщика контента поставщиком виртуального пути. Я нашел решение здесь

Вот пример фрагмента web.config, который, я думаю, вам подойдет.

<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>

Вы также можете зарегистрировать «обработчик http с подстановочными знаками» в специальном месте (например, «/MyVirtualFiles»), что может быть полезно, если ваш провайдер виртуального пути обслуживает множество разных типов файлов.

<location path="MyVirtualFiles">
  <system.web>
    <httpHandlers>
      <add path="*" verb="*" type="System.Web.StaticFileHandler" validate="true" />
    </httpHandlers>
  </system.web>
</location>
person Emil G    schedule 14.01.2011

Когда FileExists возвращает true, это интерпретируется как «там есть файл, IIS может обслуживать его без ASP.NET». Чтобы перейти к следующему шагу фактической загрузки файла для прохождения через поставщика виртуального пути, вам необходимо настроить IIS на использование ASP.NET для обслуживания всех файлов изображений и добавить код в global.asax или обработчик http, который будет использовать ваш провайдер виртуального пути.

person Tom Clarkson    schedule 01.01.2011