ASP.NET捆绑/缩小和嵌入式资源

13

我正在尝试使用这篇博客中描述的技术,将嵌入式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请求中请求文件时可以工作。

问题: 嵌入的文件没有被包含在Bundle中,它们只是被忽略了。当调试时,FileExists方法被多次调用,但从未为~/Embedded/files/styles/etc/styles.css调用。

我错过了什么?

次要问题

当使用最新版本的Microsoft ASP.NET Web Optimization Framework时。 VirtualPathProvider按预期工作,但它会阻止IRouteHandler执行。如果将FileExists方法更改为返回false,则允许RouteHandler执行,但显然会破坏VirtualPathProvider

我假设它没有使用配置的路由,因为当FileExists返回true时它正在寻找物理文件?这是配置问题还是实现问题?


1
你解决了这个问题吗? - Cristian E.
很抱歉,@Christian,不行。 - Red Taz
我也遇到了完全相同的问题!你能发一下你的web.config吗?你是否使用了忽略静态文件的ignore.routes?你是否使用了RouteExistingFiles=True?我们一起努力解决这个问题吧! - Cristian E.
我已经发布了一些代码,并在https://dev59.com/oIfca4cB1Zd3GeqPoNag上提出了一个问题。它可能会对你有所帮助...如果你发现了什么,请保持联系。 - Cristian E.
1个回答

13
您需要告诉BundleTable使用您的VirtualPathProvider,如下所示:

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

这个功能是在Microsoft ASP.NET Web Optimization Framework的v1.1.0版本中添加的。
同时,您需要通过将以下内容添加到web.config文件来确保对CSS文件的请求通过ASP.NET管道进行处理。
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">

RouteCollection.RouteExistingFiles设置为true可以解决次要问题。


当我使用此代码时,我会收到“System.Web.Optimization.BundleTable”不包含“VirtualPathProvider”的定义错误,然而我已经使用HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedVirtualPathProvider(typeof(My.Custom.Type)));注册了我的提供者。 - Red Taz
这意味着您正在使用该框架的旧版本。这也解释了为什么它没有拾取您已经注册的VPP。该功能是在该框架的同一版本中添加的。 - mwijnands
非常准确,谢谢。我已经升级到最新版本的优化框架,这解决了问题。 - Red Taz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接