ASP.NET使用捆绑中的嵌入式资源

问题描述 投票:15回答:2

我正在尝试实现一种通用方法,以使我的Web解决方案中的不同程序集可以使用来自嵌入式资源的嵌入式JavaScript和CSS文件。 This blog post显示了使用VirtualPathProvider的技术。这很好,但是VirtualPathProvider必须包含在每个包含嵌入式资源的程序集中。

我试图从博客文章中增强VirtualPathProvider,以便可以将程序集传递到其中,并从其程序集中加载资源:

public EmbeddedVirtualPathProvider(VirtualPathProvider previous, Assembly assembly)
{
    this.previous = previous;
    this.assembly = assembly;
}

初始化时,它从传递的程序集中读取所有嵌入式资源:

protected override void Initialize()
{
    base.Initialize();

    this.assemblyResourceNames = this.assembly.GetManifestResourceNames();
    this.assemblyName = this.assembly.GetName().Name;
}

[GetFile从传递的程序集中读取内容:

public override VirtualFile GetFile(string virtualPath)
{
    if (IsEmbeddedPath(virtualPath))
    {
        if (virtualPath.StartsWith("~", System.StringComparison.OrdinalIgnoreCase))
        {
            virtualPath = virtualPath.Substring(1);
        }

        if (!virtualPath.StartsWith("/", System.StringComparison.OrdinalIgnoreCase))
        {
            virtualPath = string.Concat("/", virtualPath);
        }

        var resourceName = string.Concat(this.assembly.GetName().Name, virtualPath.Replace("/", "."));
        var stream = this.assembly.GetManifestResourceStream(resourceName);

        if (stream != null)
        {
            return new EmbeddedVirtualFile(virtualPath, stream);
        }
        else
        {
            return _previous.GetFile(virtualPath);
        }
    }
    else
        return _previous.GetFile(virtualPath);
}

[检查资源是否为该程序集的嵌入式资源是通过检查在Initialize方法中读取的资源名称:

private bool IsEmbeddedPath(string path)
{
    var resourceName = string.Concat(this.assemblyName, path.TrimStart('~').Replace("/", "."));
    return this.assemblyResourceNames.Contains(resourceName, StringComparer.OrdinalIgnoreCase);
}

我将EmbeddedVirtualPathProvider类移至主Web项目(ProjectA),因此不需要将其包含在每个包含嵌入式资源的程序集中,并在Global.asax中使用以下代码对其进行注册:

HostingEnvironment.RegisterVirtualPathProvider(
    new EmbeddedVirtualPathProvider(
        HostingEnvironment.VirtualPathProvider,
        typeof(ProjectB.SomeType).Assembly));

在包含嵌入式资源的项目(ProjectB)中,我仍然在PostApplicationStartMethod中创建以下捆绑软件:

 BundleTable.Bundles.Add(new ScriptBundle("~/Embedded/Js")
     .Include("~/Scripts/SomeFolder/MyScript.js")
 );

Scripts/MyScript.js是ProjectB中的嵌入式资源。

因此,我收到以下异常:

目录'C:\ webs \ ProjectA \ Scripts \ SomeFolder \'不存在。无法开始监视文件更改。

更新this Gist中提供了完整的堆栈跟踪。

更新

同样,VirtualPathProvider本身似乎也可以正常工作。如果我直接而不是通过捆绑软件加载文件,并在web.config中设置以下条目,则它将从ProjectB加载嵌入式javascript:
<system.webServer>
  <handlers>
    <add name="MyStaticFileHandler" path="*.js" verb="GET,HEAD" type="System.Web.StaticFileHandler"/>
  </handlers>
</system.webServer>
    

我正在尝试实现一种通用方法,以使我的Web解决方案中的不同程序集可以使用来自嵌入式资源的嵌入式JavaScript和CSS文件。这篇博客文章...

c# asp.net-mvc embedded-resource bundling-and-minification virtualpathprovider
2个回答
1
投票

当ASP.net优化创建捆绑包时,它将为脚本的虚拟目录调用GetCacheDependency。您的GetCacheDependency实现仅检查虚拟文件,对于虚拟目录,它依赖于基础VirtualPathProvider,该基础检查目录是否存在并且失败。


0
投票

关于以下错误

© www.soinside.com 2019 - 2024. All rights reserved.