ASP.NET 如果动态加载,MVC 包将不会更新
ASP.NET MVC bundle won't update if loaded dynamically
我有一个 Angular.js 应用程序,因为它是一个单页应用程序,所以我会根据用户导航动态加载一些脚本,所以我不会过载。
问题是,其中一些脚本在 ASP.NET MVC 包中被丑化和缩小,当我更新源脚本时,导入的包永远不会更新。
为什么会这样,我该怎么做才能强制更新?
为什么会这样
ASP.NET 包带有缓存机制。当您使用 Scripts.Render
将包添加到页面时,引擎会自动将 v
查询字符串放入包 URL.
@Scripts.Render("~/bundles/commands")
产生如下内容:
<script src="/bundles/commands?v=eiR2xO-xX5H5Jbn3dKjSxW7hNCH9DfgZHqGApCP3ARM1"></script>
如果不提供该参数,则返回缓存的结果。如果您手动添加脚本标签,没有它,您可能会面临同样的缓存问题。
提供了有关 v
查询字符串的信息 here(“ 捆绑缓存 ”),但不是很有用。
我能做什么
您仍然可以动态加载捆绑的脚本,但您必须添加 v
参数。请注意,如果您尝试随机生成的哈希(我试过),它就不起作用。感谢 ,使用这种方法可以实现:
private static string GetHashByBundlePath(string bundlePath)
{
BundleContext bundleContext = new BundleContext(new HttpContextWrapper(System.Web.HttpContext.Current), BundleTable.Bundles, bundlePath);
Bundle bundle = BundleTable.Bundles.GetBundleFor(bundlePath);
BundleResponse bundleResponse = bundle.GenerateBundleResponse(bundleContext);
Type bundleReflection = bundleResponse.GetType();
MethodInfo method = bundleReflection.GetMethod("GetContentHashCode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
object contentHash = method.Invoke(bundleResponse, null);
return contentHash.ToString();
}
所以您可以做的是:Return 来自 ASP.NET 视图的 bundle hash 并在您需要加载脚本时获取它。
我的应用程序,我创建了一个特定于它的 JS 对象:
var appBundles = {
commands: "/bundles/commands?v=eiR2xO-xX5H5Jbn3dKjSxW7hNCH9DfgZHqGApCP3ARM1"
};
希望对您有所帮助!
当我使用 GTM 从一个 MVC 应用程序加载捆绑包到另一个 MVC 应用程序时,我遇到了捆绑包未更新的问题(听起来很混乱,但在多个 MVC 应用程序之间共享代码的上下文中它实际上是有意义的)。
我想到的是 Marcos Lima 在他的回答中写的,但更进一步。
我添加了一个 Bundle
控制器,代码如下:
public class BundleController : Controller
{
private static string GetHashByBundlePath(string bundlePath)
{
BundleContext bundleContext = new BundleContext(new HttpContextWrapper(System.Web.HttpContext.Current), BundleTable.Bundles, bundlePath);
Bundle bundle = BundleTable.Bundles.GetBundleFor(bundlePath);
BundleResponse bundleResponse = bundle.GenerateBundleResponse(bundleContext);
Type bundleReflection = bundleResponse.GetType();
MethodInfo method = bundleReflection.GetMethod("GetContentHashCode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
object contentHash = method.Invoke(bundleResponse, null);
return contentHash.ToString();
}
public ActionResult Index(string bundleName)
{
string bundlePath = "~/bundles/" + bundleName;
var hash = GetHashByBundlePath(bundlePath);
return RedirectPermanent(bundlePath + "?v=" + hash);
}
}
然后我添加了这条路线:
routes.MapRoute(
name: "Bundle",
url: "Bundle/{bundleName}",
defaults: new { controller = "Bundle", action = "Index" }
);
最终结果是我通过控制器请求捆绑包,但是因为我进行了 301 重定向,Index
操作 运行 每个用户只有一次并且 returns捆绑包的当前版本,然后从浏览器缓存中提供捆绑包。当我实际更新包时,我在请求中添加了一些查询参数 url(在 GTM 中),现在所有用户都获得了更新的包。
当然,我假设捆绑包放置在 ~/bundles/
路径中,但如果您的捆绑包放置在其他地方,那应该很容易更改。事实上,路线甚至不是必需的。
我有一个 Angular.js 应用程序,因为它是一个单页应用程序,所以我会根据用户导航动态加载一些脚本,所以我不会过载。
问题是,其中一些脚本在 ASP.NET MVC 包中被丑化和缩小,当我更新源脚本时,导入的包永远不会更新。
为什么会这样,我该怎么做才能强制更新?
为什么会这样
ASP.NET 包带有缓存机制。当您使用 Scripts.Render
将包添加到页面时,引擎会自动将 v
查询字符串放入包 URL.
@Scripts.Render("~/bundles/commands")
产生如下内容:
<script src="/bundles/commands?v=eiR2xO-xX5H5Jbn3dKjSxW7hNCH9DfgZHqGApCP3ARM1"></script>
如果不提供该参数,则返回缓存的结果。如果您手动添加脚本标签,没有它,您可能会面临同样的缓存问题。
提供了有关 v
查询字符串的信息 here(“ 捆绑缓存 ”),但不是很有用。
我能做什么
您仍然可以动态加载捆绑的脚本,但您必须添加 v
参数。请注意,如果您尝试随机生成的哈希(我试过),它就不起作用。感谢
private static string GetHashByBundlePath(string bundlePath)
{
BundleContext bundleContext = new BundleContext(new HttpContextWrapper(System.Web.HttpContext.Current), BundleTable.Bundles, bundlePath);
Bundle bundle = BundleTable.Bundles.GetBundleFor(bundlePath);
BundleResponse bundleResponse = bundle.GenerateBundleResponse(bundleContext);
Type bundleReflection = bundleResponse.GetType();
MethodInfo method = bundleReflection.GetMethod("GetContentHashCode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
object contentHash = method.Invoke(bundleResponse, null);
return contentHash.ToString();
}
所以您可以做的是:Return 来自 ASP.NET 视图的 bundle hash 并在您需要加载脚本时获取它。
我的应用程序,我创建了一个特定于它的 JS 对象:
var appBundles = {
commands: "/bundles/commands?v=eiR2xO-xX5H5Jbn3dKjSxW7hNCH9DfgZHqGApCP3ARM1"
};
希望对您有所帮助!
当我使用 GTM 从一个 MVC 应用程序加载捆绑包到另一个 MVC 应用程序时,我遇到了捆绑包未更新的问题(听起来很混乱,但在多个 MVC 应用程序之间共享代码的上下文中它实际上是有意义的)。
我想到的是 Marcos Lima 在他的回答中写的,但更进一步。
我添加了一个 Bundle
控制器,代码如下:
public class BundleController : Controller
{
private static string GetHashByBundlePath(string bundlePath)
{
BundleContext bundleContext = new BundleContext(new HttpContextWrapper(System.Web.HttpContext.Current), BundleTable.Bundles, bundlePath);
Bundle bundle = BundleTable.Bundles.GetBundleFor(bundlePath);
BundleResponse bundleResponse = bundle.GenerateBundleResponse(bundleContext);
Type bundleReflection = bundleResponse.GetType();
MethodInfo method = bundleReflection.GetMethod("GetContentHashCode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
object contentHash = method.Invoke(bundleResponse, null);
return contentHash.ToString();
}
public ActionResult Index(string bundleName)
{
string bundlePath = "~/bundles/" + bundleName;
var hash = GetHashByBundlePath(bundlePath);
return RedirectPermanent(bundlePath + "?v=" + hash);
}
}
然后我添加了这条路线:
routes.MapRoute(
name: "Bundle",
url: "Bundle/{bundleName}",
defaults: new { controller = "Bundle", action = "Index" }
);
最终结果是我通过控制器请求捆绑包,但是因为我进行了 301 重定向,Index
操作 运行 每个用户只有一次并且 returns捆绑包的当前版本,然后从浏览器缓存中提供捆绑包。当我实际更新包时,我在请求中添加了一些查询参数 url(在 GTM 中),现在所有用户都获得了更新的包。
当然,我假设捆绑包放置在 ~/bundles/
路径中,但如果您的捆绑包放置在其他地方,那应该很容易更改。事实上,路线甚至不是必需的。