ASP.NET中使用嵌入式捆绑资源 [英] ASP.NET using embedded resources in Bundling

查看:284
本文介绍了ASP.NET中使用嵌入式捆绑资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个通用的方法提供在我的网络解决方案为不同的组件,能使用从嵌入的资源嵌入的JavaScript和CSS文件。 本博客文章显示了使用技术一个的VirtualPathProvider。这工作得很好,但需要的VirtualPathProvider被列入包含嵌入式资源的每个组件。

我试图从博客文章提升的VirtualPathProvider,使装配可以传递到它,它从加载其装配的资源:

 公共EmbeddedVirtualPathProvider(的VirtualPathProvider previous,装配组装)
{
    这previous = previous。
    this.assembly =组装;
}

在初始化它读取所有嵌入的资源从通过装配:

 保护覆盖无效初始化()
{
    base.Initialize();    this.assemblyResourceNames = this.assembly.GetManifestResourceNames();
    this.assemblyName = this.assembly.GetName()名称。
}

以及的GetFile 读取来自通过装配内容:

 公众覆盖VirtualFile的GetFile(字符串virtualPath)
{
    如果(IsEmbeddedPath(virtualPath))
    {
        如果(virtualPath.StartsWith(〜,System.StringComparison.OrdinalIgnoreCase))
        {
            virtualPath = virtualPath.Substring(1);
        }        如果(!virtualPath.StartsWith(/,System.StringComparison.OrdinalIgnoreCase))
        {
            virtualPath = string.Concat(/,virtualPath);
        }        VAR资源名称= string.Concat(this.assembly.GetName()名称,virtualPath.Replace(/)。);
        VAR流= this.assembly.GetManifestResourceStream(资源名称);        如果(流!= NULL)
        {
            返回新EmbeddedVirtualFile(virtualPath,流);
        }
        其他
        {
            返回_ previous.GetFile(virtualPath);
        }
    }
    其他
        返回_ previous.GetFile(virtualPath);
}

检查是否资源是本次大会的嵌入资源是通过检查初始化方法读取的资源名称:

 私人布尔IsEmbeddedPath(字符串路径)
{
    VAR资源名称= string.Concat(this.assemblyName,path.TrimStart('〜')更换(/)。);
    返回this.assemblyResourceNames.Contains(资源名称,StringComparer.OrdinalIgnoreCase);
}

我移动 EmbeddedVirtualPathProvider 类主Web项目(项目A),因此它不需要包含在每个装配包含嵌入的资源,并使用其注册以下code在的Global.asax

  HostingEnvironment.RegisterVirtualPathProvider(
    新EmbeddedVirtualPathProvider(
        HostingEnvironment.VirtualPathProvider,
        typeof运算(ProjectB.SomeType).Assembly));

在包含嵌入的资源项目(项目B)我还创建在以下捆绑一个 PostApplicationStartMethod

  BundleTable.Bundles.Add(新ScriptBundle(〜/嵌入式/ JS)
     .INCLUDE(〜/脚本/ SomeFolder / MyScript.js)
 );

脚本/ MyScript.js 是项目B嵌入的资源。

有了这个,我收到以下异常:


  

目录C:\\网\\项目A \\脚本\\ SomeFolder \\'不存在。未能开始监视文件更改。


更新
这个要点

更新
另外,本身的VirtualPathProvider似乎很好地工作。如果我而不是直接加载该文件通过捆绑,并设置在 web.config中的以下条目它加载嵌入的JavaScript从项目B:

 < system.webServer>
  <&处理GT;
    <添加名称=MyStaticFileHandler路径=* JS。动词=GET,HEADTYPE =System.Web.StaticFileHandler/>
  < /处理器>
< /system.webServer>


解决方案

在ASP.net优化创建它叫 GetCacheDependency 为脚本的虚拟目录的包。你的 GetCacheDependency 实施只检查虚拟文件,虚拟目录它依赖基的VirtualPathProvider 其中检查目录存在并且失败的。

要解决这个问题,你必须检查路径是的脚本的一个目录的并为 GetCacheDependency 返回null。

要安全地确定是否 virtualPath 是一个包目录,你可以使用 BundleTable.Bundles 收集或使用约定(即:每包应以〜/嵌入式开始)。

 公众覆盖的CacheDependency GetCacheDependency(
    字符串virtualPath,
    IEnumerable的virtualPathDependencies,
    日期时间utcStart)
{
    //如果(virtualPath.StartsWith(〜/嵌入))
    如果(BundleTables.Bundles.Any(B = GT; b.Path == virtualPath))
    {
        返回null;
    }
    如果(this.IsEmbeddedPath(virtualPath))
    {
        返回null;
    }
    其他
    {
        返回此._ previous
                   .GetCacheDependency(virtualPath,virtualPathDependencies,utcStart);
    }
}

I'm trying to implement a generic approach for providing the possibility for different assemblies in my web solution to use embedded JavaScript and CSS files from embedded resources. This blog post shows a technique using a VirtualPathProvider. This works fine, but the VirtualPathProvider needs to be included in each assembly containing embedded resources.

I tried to enhance the VirtualPathProvider from the blog post, so that an assembly can be passed into it and it loads the resource from its assembly:

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

On initialization it reads all embedded resources from the passed assembly:

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

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

And the GetFilereads the content from the passed assembly:

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

Checking if resource is an embedded resource of this assembly is by checking the resource names read in the Initialize method:

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

I moved the EmbeddedVirtualPathProvider class to the main web project (ProjectA), so that it doesn't need to be included in each assembly containing embedded resources and registered it using the following code in Global.asax:

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

In the project containing the embedded resources (ProjectB) I still create the following bundle in a PostApplicationStartMethod:

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

Scripts/MyScript.js is the embedded resource in ProjectB.

With this I receive the following exception:

Directory 'C:\webs\ProjectA\Scripts\SomeFolder\' does not exist. Failed to start monitoring file changes.

Update Full stack trace available in this Gist.

Update Also the VirtualPathProvider itself seems to work fine. If I load the file directly and not through the bundle and set the following entry in the web.config it loads the embedded javascript from ProjectB:

<system.webServer>
  <handlers>
    <add name="MyStaticFileHandler" path="*.js" verb="GET,HEAD" type="System.Web.StaticFileHandler"/>
  </handlers>
</system.webServer>

解决方案

When ASP.net optimization create the bundle it call GetCacheDependency for the virtual directory of the script. Your GetCacheDependency implementation only check virtual file, for virtual directory it relies on the base VirtualPathProvider which check if directory exists and failed.

To solve this issue, you have to check if the path is a directory of one of your script and return null for the GetCacheDependency.

To safely determine if virtualPath is a bundle directory, you can use the BundleTable.Bundles collection or using a convention (ie: every bundle should starts with ~/Embedded).

public override CacheDependency GetCacheDependency(
    string virtualPath, 
    IEnumerable virtualPathDependencies, 
    DateTime utcStart)
{
    // if(virtualPath.StartsWith("~/Embedded"))
    if(BundleTables.Bundles.Any(b => b.Path == virtualPath))
    {
        return null; 
    }
    if (this.IsEmbeddedPath(virtualPath))
    {
        return null;
    }
    else
    {
        return this._previous
                   .GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
    }
}

这篇关于ASP.NET中使用嵌入式捆绑资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆