ASP.NET中使用嵌入式捆绑资源 [英] ASP.NET using embedded resources in Bundling
问题描述
我想实现一个通用的方法提供在我的网络解决方案为不同的组件,能使用从嵌入的资源嵌入的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
GetFile
reads 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 inGlobal.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. YourGetCacheDependency
implementation only check virtual file, for virtual directory it relies on the baseVirtualPathProvider
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 theBundleTable.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屋!