ASP.NET Bundling/Minification and Embedded Resources
Asked Answered
A

1

13

I'm trying to use the technique described in this blog to add embedded dll resources to my bundles.

I have created the custom VirtualPathProvider below.

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

I then register this and set up the bundles;

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

I have also implemented a custom EmbeddedResourceHttpHandler as described in the article which works when requesting the file as a direct http request.

Problem: The embedded files aren't being included in the bundle, they're just ignored. When debugging the FileExists method is called several times but never for ~/Embedded/files/styles/etc/styles.css

What am I missing?

Secondary Problem

When using the latest version of the Microsoft ASP.NET Web Optimization Framework. The VirtualPathProvider works as expected, however it prevents the IRouteHandler from executing. If the FileExists method is changed to return false this allows the RouteHandler to execute but obviously breaks the VirtualPathProvider.

I'm assuming it's not using a configured route because it's looking for a physical file when FileExists returns true? Is this a configuration or an implementation issue?

Ardeth answered 31/3, 2014 at 14:17 Comment(4)
Have you solved this issue?Forequarter
@Christian unfortunately not, noArdeth
I'm having exactly the same issue! Can you post your web.config? Are you using some ignore.routes for static files? Are you using RouteExistingFiles=True ? Lets put some effort and solve this ?Forequarter
I've posted some code from my attempts and opened a question at: #28500385. It might help you ... If you find something please keep in touchForequarter
L
13

You will need to tell the BundleTable to use your VirtualPathProvider like this:

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

This functionality was added in v1.1.0 of the Microsoft ASP.NET Web Optimization Framework.

Also you need to make sure that requests for CSS file go through the ASP.NET pipeline by adding this to your web.config.

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

The secondary problem can be solved by setting RouteCollection.RouteExistingFiles to true

Lamkin answered 14/2, 2015 at 13:59 Comment(3)
I get 'System.Web.Optimization.BundleTable' does not contain a definition for 'VirtualPathProvider' when using this code, however I am already registering my provider using HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedVirtualPathProvider(typeof(My.Custom.Type)));Ardeth
That means you are using an older version of that framework. Which also explains why it is not picking up your already registered VPP. That functionality was added in the same version of the framework.Lamkin
Spot on, thanks. I've upgraded to the latest version of the optimization framework which has resolved the issueArdeth

© 2022 - 2024 — McMap. All rights reserved.