【问题标题】:ASP.NET MVC bundle won't update if loaded dynamically如果动态加载 ASP.NET MVC 包将不会更新
【发布时间】:2015-10-13 12:47:38
【问题描述】:

我有一个 Angular.js 应用程序,因为它是一个单页应用程序,所以我会根据用户导航动态加载一些脚本,因此不会出现过载。

问题是,其中一些脚本在 ASP.NET MVC 包中被丑化和缩小,当我更新源脚本时,导入的包永远不会更新。

为什么会发生这种情况,我可以做些什么来强制更新?

【问题讨论】:

    标签: angularjs asp.net-mvc bundling-and-minification


    【解决方案1】:

    为什么会这样

    ASP.NET 包带有一个缓存机制。当您使用 Scripts.Render 将捆绑包添加到页面时,引擎会自动将 v 查询字符串放入捆绑包 URL。

    @Scripts.Render("~/bundles/commands")
    

    产生类似的东西:

    <script src="/bundles/commands?v=eiR2xO-xX5H5Jbn3dKjSxW7hNCH9DfgZHqGApCP3ARM1"></script>
    

    如果不提供该参数,则返回缓存的结果。如果您手动添加脚本标签,没有它,您可能会面临同样的缓存问题。

    here 提供了有关 v 查询字符串的信息(“Bundle Caching”),但不是很有帮助。

    我能做什么

    您仍然可以动态加载捆绑的脚本,但您必须添加v 参数。请注意,如果您尝试随机生成的哈希(我尝试过),它不起作用。感谢Frison B Alexander,可以使用这种方法:

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

    所以你可以做的是:从 ASP.NET 视图返回捆绑散列,并在需要加载脚本时获取它。

    我的应用程序,我创建了一个特定于它的 JS 对象:

    var appBundles = {
        commands: "/bundles/commands?v=eiR2xO-xX5H5Jbn3dKjSxW7hNCH9DfgZHqGApCP3ARM1"
    };
    

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      当我使用 GTM 从一个 MVC 应用程序加载另一个 MVC 应用程序中的包时,我遇到了包没有更新的问题(听起来很乱,但在多个 MVC 应用程序之间共享代码的情况下它实际上是有意义的)。

      我想出的是马科斯·利马在他的回答中写的,但更进一步。

      我添加了一个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 操作仅对每个用户运行一次,它返回捆绑包的当前版本,然后从之后浏览器缓存。当我实际更新包时,我在请求 url(在 GTM 中)中添加了一些查询参数,所有用户现在都得到了更新的包。

      当然,我假设捆绑包放置在~/bundles/ 路径中,但如果您的捆绑包放在其他地方,这应该很容易更改。事实上,这条路线甚至没有必要。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-08
        • 2013-06-14
        • 1970-01-01
        • 2021-10-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多