Объединение/минимизация ASP.NET и встроенные ресурсы

Я пытаюсь использовать технику, описанную в в этом блоге, чтобы добавить встроенные ресурсы dll в мои пакеты.

Я создал пользовательский VirtualPathProvider ниже.

public class EmbeddedVirtualPathProvider : VirtualPathProvider {

    private Type _rootType;

    public EmbeddedVirtualPathProvider(Type rootType) {
        _rootType = rootType;
    }

    public override bool FileExists(string virtualPath) {
        if (IsEmbeddedPath(virtualPath))
            return true;
        else
            return Previous.FileExists(virtualPath);
    }

    public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) {
        if (IsEmbeddedPath(virtualPath)) {
            return null;
        }
        else {
            return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
        }
    }

    public override VirtualDirectory GetDirectory(string virtualDir) {
        return Previous.GetDirectory(virtualDir);
    }

    public override bool DirectoryExists(string virtualDir) {
        return Previous.DirectoryExists(virtualDir);
    }

    public override VirtualFile GetFile(string virtualPath) {
        if (IsEmbeddedPath(virtualPath)) {
            string fileNameWithExtension = virtualPath.Substring(virtualPath.LastIndexOf("/") + 1);

            string nameSpace = _rootType.Namespace;
            string manifestResourceName = String.Format("{0}.{1}", nameSpace, fileNameWithExtension);
            var stream = _rootType.Assembly.GetManifestResourceStream(manifestResourceName);
            return new EmbeddedVirtualFile(virtualPath, stream);
        }
        else
            return Previous.GetFile(virtualPath);
    }

    private bool IsEmbeddedPath(string path) {
        return path.Contains("~/Embedded");
    }
}

public class EmbeddedVirtualFile : VirtualFile {
    private Stream _stream;
    public EmbeddedVirtualFile(string virtualPath, Stream stream)
        : base(virtualPath) {
        _stream = stream;
    }

    public override Stream Open() {
        return _stream;
    }
} 

Затем зарегистрирую это и настрою пакеты;

public static void RegisterBundles(BundleCollection bundles) {

    HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedVirtualPathProvider(typeof(My.Custom.Type)));

    bundles.Add(new StyleBundle("~/Embedded/css").Include(
        "~/Embedded/files/styles/etc/styles.css")
    );
}

Я также внедрил пользовательский EmbeddedResourceHttpHandler, как описано в статье, которая работает при запросе файла как прямой HTTP-запрос.

Проблема: Вложенные файлы не включаются в комплект, они просто игнорируются. Когда отладка метода FileExists вызывается несколько раз, но никогда для ~/Embedded/files/styles/etc/styles.css

Что мне не хватает?

Дополнительная проблема

При использовании последней версии Microsoft ASP.NET Web Optimization Framework. VirtualPathProvider работает так, как ожидалось, однако это предотвращает выполнение IRouteHandler. Если метод FileExists изменен для возврата false, это позволяет выполнить RouteHandler, но, очевидно, нарушает VirtualPathProvider.

Я предполагаю, что он не использует настроенный маршрут, потому что он ищет физический файл, когда FileExists возвращает true? Это проблема конфигурации или реализации?

Ответы

Ответ 1

Вам нужно будет сообщить BundleTable, чтобы использовать ваш VirtualPathProvider следующим образом:

BundleTable.VirtualPathProvider = new EmbeddedVirtualPathProvider(typeof(My.Custom.Type));

Эта функциональность была добавлена ​​в v1.1.0 Структуры веб-оптимизации Microsoft ASP.NET.

Также вам нужно убедиться, что запросы на файл CSS проходят через конвейер ASP.NET, добавив это в ваш web.config.

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">

Вторую проблему можно решить, установив RouteCollection.RouteExistingFiles в true