我刚刚追查了一个由于缺少javascript文件而导致的错误,它无声地失败了。
文件的缩小版本存在但不是完整版本,客户端上没有呈现链接(我期待)但我也没有例外。我想知道文件是否不存在。
(为了清楚,捆绑包没有尝试包含缩小版本,它试图包含完整版本,但是缩小版本存在于脚本目录中)
我是否必须编写一些自定义内容来检测此内容,或者MVC是否内置了任何内容来报告此内容?
感谢
答案 0 :(得分:26)
我开始使用Bundle
的以下扩展方法:
public static class BundleHelper
{
[Conditional("DEBUG")] // remove this attribute to validate bundles in production too
private static void CheckExistence(string virtualPath)
{
int i = virtualPath.LastIndexOf('/');
string path = HostingEnvironment.MapPath(virtualPath.Substring(0, i));
string fileName = virtualPath.Substring(i + 1);
bool found = Directory.Exists(path);
if (found)
{
if (fileName.Contains("{version}"))
{
var re = new Regex(fileName.Replace(".", @"\.").Replace("{version}", @"(\d+(?:\.\d+){1,3})"));
fileName = fileName.Replace("{version}", "*");
found = Directory.EnumerateFiles(path, fileName).FirstOrDefault(file => re.IsMatch(file)) != null;
}
else // fileName may contain '*'
found = Directory.EnumerateFiles(path, fileName).FirstOrDefault() != null;
}
if (!found)
throw new ApplicationException(String.Format("Bundle resource '{0}' not found", virtualPath));
}
public static Bundle IncludeExisting(this Bundle bundle, params string[] virtualPaths)
{
foreach (string virtualPath in virtualPaths)
CheckExistence(virtualPath);
return bundle.Include(virtualPaths);
}
public static Bundle IncludeExisting(this Bundle bundle, string virtualPath, params IItemTransform[] transforms)
{
CheckExistence(virtualPath);
return bundle.Include(virtualPath, transforms);
}
}
这样您就不必明确调用辅助方法PreCheck()
。它还支持ASP.NET的通配符{version}
和*
:
bundles.Add(new ScriptBundle("~/test")
.IncludeExisting("~/Scripts/jquery/jquery-{version}.js")
.IncludeExisting("~/Scripts/lib*")
.IncludeExisting("~/Scripts/model.js")
);
答案 1 :(得分:1)
我无法相信这种反模式"存在!如果您没有看到错误,则没有错误!
无论如何,我喜欢上面的解决方案。另一个是输出链接/脚本,即使它在BundleTable.EnableOptimizations为false时丢失 - 这是一个非常明显的事情,在调试时尝试,然后在浏览器上的各种检查器/调试器中显而易见的是哪个文件是失踪。对于调试事情来说,这似乎是一件显而易见的事情,我花了几个小时没有意识到丢失文件。另一方面,默默地忽略了捆绑的缺失部分,这是错误的,它加强了我可怕的调试会话。
嗯,这不会让我两次受伤 - 创伤持久。
答案 2 :(得分:1)
使用BundleTable.VirtualPathProvider
包装器的另一种方法:
public class VirtualPathProviderExt : VirtualPathProvider
{
private readonly VirtualPathProvider _provider;
public VirtualPathProviderExt(VirtualPathProvider provider)
{
_provider = provider;
}
public override string CombineVirtualPaths(string basePath, string relativePath)
{
return _provider.CombineVirtualPaths(basePath, relativePath);
}
public override ObjRef CreateObjRef(Type requestedType)
{
return _provider.CreateObjRef(requestedType);
}
public override bool DirectoryExists(string virtualDir)
{
return _provider.DirectoryExists(virtualDir);
}
public override bool Equals(object obj)
{
return _provider.Equals(obj);
}
private static readonly Regex _ignorePathsRegex = new Regex(@"\.debug\.\w+$|^~/bundle.config$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public override bool FileExists(string virtualPath)
{
var result = _provider.FileExists(virtualPath);
if (!result && !_ignorePathsRegex.IsMatch(virtualPath))
{
Logger.Instance.Log(RecType.Error, "Bundle file not found: " + virtualPath);
}
return result;
}
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
{
return _provider.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
public override string GetCacheKey(string virtualPath)
{
return _provider.GetCacheKey(virtualPath);
}
public override VirtualDirectory GetDirectory(string virtualDir)
{
return _provider.GetDirectory(virtualDir);
}
public override VirtualFile GetFile(string virtualPath)
{
return _provider.GetFile(virtualPath);
}
public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies)
{
return _provider.GetFileHash(virtualPath, virtualPathDependencies);
}
public override int GetHashCode()
{
return _provider.GetHashCode();
}
public override object InitializeLifetimeService()
{
return _provider.InitializeLifetimeService();
}
public override string ToString()
{
return _provider.ToString();
}
}
捆绑帮手:
public static class BundleHelpers
{
public static void InitBundles()
{
if (!(BundleTable.VirtualPathProvider is VirtualPathProviderExt))
{
BundleTable.VirtualPathProvider = new VirtualPathProviderExt(BundleTable.VirtualPathProvider);
}
}
}
在BundleHelpers.InitBundles()
中运行BundleConfig.cs
:
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
BundleHelpers.InitBundles();
...
答案 3 :(得分:0)
我稍微更改了代码。而不是抛出错误,它不会添加任何捆绑文件。如果您对多个项目使用相同的通用捆绑包配置,则需要这样做
public static class BundleHelper
{
private static bool CheckExistence(string virtualPath)
{
int i = virtualPath.LastIndexOf('/');
string path = HostingEnvironment.MapPath(virtualPath.Substring(0, i));
string fileName = virtualPath.Substring(i + 1);
bool found = Directory.Exists(path);
if (found)
{
if (fileName.Contains("{version}"))
{
var re = new Regex(fileName.Replace(".", @"\.").Replace("{version}", @"(\d+(?:\.\d+){1,3})"));
fileName = fileName.Replace("{version}", "*");
found = Directory.EnumerateFiles(path, fileName).Where(file => re.IsMatch(file)).FirstOrDefault() != null;
}
else // fileName may contain '*'
found = Directory.EnumerateFiles(path, fileName).FirstOrDefault() != null;
}
return found;
//if (!found)
//throw new ApplicationException(String.Format("Bundle resource '{0}' not found", virtualPath));
}
public static Bundle IncludeExisting(this Bundle bundle, params string[] virtualPaths)
{
foreach (string virtualPath in virtualPaths)
if (CheckExistence(virtualPath))
{
bundle.Include(virtualPath);
}
return bundle;
}
public static Bundle IncludeExisting(this Bundle bundle, string virtualPath, params IItemTransform[] transforms)
{
if (CheckExistence(virtualPath))
bundle.Include(virtualPath, transforms);
return bundle;
}
}