我们在BundleTransformer MVC 4安装程序中使用ASP.NET库。我们的web应用程序是一个相当薄的层,所有服务器逻辑都在后端服务中处理。
安装完后,所有资源都将沿着web应用程序安装在文件系统上,但出于更新的原因,我们需要能够从服务中为JavaScript和CSS (较少的)资源提供服务--然后它们将覆盖本地(文件系统)版本。
本质上,如果从服务中获得,我们将从那里提供所请求的资源。如果没有,我们回到文件系统并从那里服务文件。
这一切都很有魅力,然后我们引入了LESS和@import语句,现在事情已经不那么好了。
我们仍然希望在Http中缓存较少转换的结果,而且每当依赖项发生变化时,我们都希望使该结果无效。VirtualPathProvider中的当前实现可以做到这一点,但是如果我更新单个文件(例如JavaScript文件),它将不会被更新。
我的VirtualPathProvider看起来是这样的:
public class ViewsAndScriptsPathProvider : VirtualPathProvider {
private static IApplicationServiceResourcesManager ResourceManager {
get { return InstanceProvider.Get<IApplicationServiceResourcesManager>(); }
}
public override bool FileExists(string virtualPath) {
var exists = ResourceManager.Exists(virtualPath);
return exists || base.FileExists(virtualPath);
}
public override VirtualFile GetFile(string virtualPath) {
VirtualFile file;
if (ResourceManager.TryGet(virtualPath, out file)) {
return file;
}
return base.GetFile(virtualPath);
}
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) {
bool isRelevant = ResourceManager.IsRelevant(virtualPath);
if (isRelevant) {
var cachekeys = virtualPathDependencies.Cast<string>().Where(dependency => virtualPath != dependency).ToArray();
return new CacheDependency(null, cachekeys);
}
if (IsBundle(virtualPath)) {
return new CacheDependency(null, new[] { ResourceManager.ComponentCacheKey }, utcStart);
}
return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
private bool IsBundle(string virtualPath) {
return virtualPath.StartsWith("~/bundles/", StringComparison.InvariantCultureIgnoreCase)
|| virtualPath.StartsWith("~/css/", StringComparison.InvariantCultureIgnoreCase);
}
public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies) {
byte[] bhash;
string filehash;
if (ResourceManager.TryGetFileHash(virtualPath, out bhash)) {
filehash = BitConverter.ToString(bhash);
} else {
filehash = Previous.GetFileHash(virtualPath, virtualPathDependencies);
}
return filehash;
}
}将ResourceManager视为服务的代理/缓存。
我最大的问题是,我不完全理解CacheDependency的工作。如果我添加一个包含virtualPath本身的cachekey (第二个参数),那么服务器中就会有一个无限循环。如果我简单地返回null,那么它将不适用于较少的@imports。
如果有人能够解释或指出VirtualPathProvider应该如何实现GetCacheDependency和GetFileHash函数,我可能能够解决这个问题。
发布于 2015-02-09 14:52:25
实际上,我在一段时间前已经想出了一个解决方案,这与HttpCache与CacheDependency对象的工作方式有关。然而,这是相当复杂的。
基本上,我有三种方案:
对于1.我使用CacheDependency对象作为文件位置。这是标准的,默认情况下是VirtualPathProvider的工作方式。
对于2.我使用一个自定义(派生) ResourceCacheDependency,它实现了在代理有新版本时使自己失效的逻辑。
对于3.我使用AggregateCacheDependency对象,它具有物理文件的CacheDependency和ResourceCacheDependency对象。
对于所有虚拟路径依赖项(资源的依赖项列表),我重复上述假设,并将其构建到AggreateCacheDependency中(它可能有很多依赖项)。
在VirtualPathProvider的自定义实现中,我重写了GetCacheDependency方法,以便根据上面的分析返回相关的CacheDependency对象。
https://stackoverflow.com/questions/24997636
复制相似问题