12

我试图使用this blog中描述的技术将嵌入式dll资源添加到我的软件包中。ASP.NET打包/缩小和嵌入式资源

我在下面创建了自定义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") 
    ); 
} 

为请求的文件作为一个直接的HTTP请求时,它的工作原理在文章中描述的我也实现了自定义EmbeddedResourceHttpHandler

问题:不被列入 嵌入的文件捆绑,他们只是忽略。当调试FileExists方法被称为几次,但从来没有~/Embedded/files/styles/etc/styles.css

我错过了什么?

次要问题

在使用最新版本的Microsoft ASP.NET网站优化框架。 VirtualPathProvider按预期工作,但它阻止执行IRouteHandler。如果FileExists方法更改为返回false,则允许RouteHandler执行,但显然会破坏VirtualPathProvider

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

+1

解决? –

+0

@Christian不幸的是,没有 –

+0

我有完全相同的问题!你可以发布你的web.config?你是否在使用一些ignore.routes作为静态文件?你使用RouteExistingFiles = True?让我们付出一些努力并解决这个问题? –

回答

12

你需要告诉BundleTable使用您的VirtualPathProvider这样的:

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

此功能在v1.1.0 of the Microsoft ASP.NET Web Optimization Framework加入。

此外,您需要确保对CSS文件的请求通过将此添加到您的web.config来通过ASP.NET管道。

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

次要问题可以通过你已经解决了这个问题,设置RouteCollection.RouteExistingFilestrue

+0

当我使用这段代码时,'System.Web.Optimization.BundleTable'没有包含'VirtualPathProvider'的定义,但是我已经使用' HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedVirtualPathProvider(typeof(My.Custom.Type)));' –

+0

这意味着您正在使用该框架的旧版本。这也解释了为什么它没有拿起你已经注册的VPP。该功能已添加到相同版本的框架中。 – mwijnands

+0

现货,谢谢。我已升级到已解决问题的最新版本的优化框架 –