asp.net-mvc-4 – MVC4 StyleBundle不以正确的顺序呈现捆绑包

我试图渲染一堆css文件,但是输出的顺序是错误的.我试过解决方案@ MVC4 Beta Minification and Bundling: Ordering files and debugging in browser,但没有帮助.这是捆绑包:
bundles.Add(new StyleBundle("~/stylesheet")
    .Include("~/css/main.css")
    .Include("~/css/mvc.css")
    .Include("~/js/jquery.thickBox.css")
    .Include("~/js/jquery.rating.css")
    .Include("~/css/ProductListing.css")
    .Include("~/css/dropdown/dropdown.css")
    .Include("~/css/dropdown/dropdown.vertical.css")
    .Include("~/js/fancybox/jquery.fancybox-1.3.1.css")
    .Include("~/css/scartpopup.css")
    .Include("~/css/ShoppingCart.css")
    .Include("~/css/ceeBox.css")
    .Include("~/css/tooltip.css")
    .Include("~/css/recent_blog_posts.css")
    .Include("~/css/ProductDetail.css")
    .Include("~/css/jquery-ui-1.7.3.custom.css")
    .Include("~/css/filter_Box.css")
    .Include("~/css/custom_page.css")
    .Include("~/css/Checkout.css")
    .Include("~/css/CheckoutButton.css")
);

这里是结果,你可以看到jquery-ui来到顶部.

<link href="/css/jquery-ui-1.7.3.custom.css" rel="stylesheet"/>
<link href="/css/main.css" rel="stylesheet"/>
<link href="/css/mvc.css" rel="stylesheet"/>
<link href="/js/jquery.thickBox.css" rel="stylesheet"/>
<link href="/js/jquery.rating.css" rel="stylesheet"/>
<link href="/css/ProductListing.css" rel="stylesheet"/>
<link href="/css/dropdown/dropdown.css" rel="stylesheet"/>
<link href="/css/dropdown/dropdown.vertical.css" rel="stylesheet"/>
<link href="/js/fancybox/jquery.fancybox-1.3.1.css" rel="stylesheet"/>
<link href="/css/scartpopup.css" rel="stylesheet"/>
<link href="/css/ShoppingCart.css" rel="stylesheet"/>
<link href="/css/ceeBox.css" rel="stylesheet"/>
<link href="/css/tooltip.css" rel="stylesheet"/>
<link href="/css/recent_blog_posts.css" rel="stylesheet"/>
<link href="/css/ProductDetail.css" rel="stylesheet"/>
<link href="/css/filter_Box.css" rel="stylesheet"/>
<link href="/css/custom_page.css" rel="stylesheet"/>
<link href="/css/Checkout.css" rel="stylesheet"/>
<link href="/css/CheckoutButton.css" rel="stylesheet"/>

如何确保样式表以正确的顺序呈现?

解决方法

捆绑不应该以完全相同的顺序呈现CSS文件,它遵循不同的逻辑.如果需要按照定义进行渲染,那么您应该创建一个自定义IBundleOrderer,并将其设置为所需的Orderer的捆绑包:
public class AsDefinedBundleOrderer : IBundleOrderer
{
    public IEnumerable<FileInfo> OrderFiles(BundleContext context,IEnumerable<FileInfo> files)
    {
        return files;
    }
}

var bundle = new StyleBundle("~/stylesheet");
bundle.Orderer = new AsDefinedBundleOrderer();
bundles.Add(bundle);

那么这样做就不会对列表造成任何影响,所以Render会按照相同的顺序将它们渲染出来.

更新认排序

Bundling使用IBundleOrderer的概念对Bundle中的项进行排序.
Bundle类有它的Orderer属性,如下所示:

public IBundleOrderer Orderer
{
  get
  {
    if (this._orderer == null)
      return (IBundleOrderer) DefaultBundleOrderer.Instance;
    else
      return this._orderer;
  }
  set
  {
    this._orderer = value;
    this.InvalidateCacheEntries();
  }
}

所以认的orderer实际上是一个DefaultBundleOrderer,直到你用自定义的orderer覆盖它.

IBundleOrderer具有以下签名:

public interface IBundleOrderer
{
  IEnumerable<FileInfo> OrderFiles(BundleContext context,IEnumerable<FileInfo> files);
}

DefaultBundleOrderer的实现由BundleContext命令文件,这里是从OrderFiles的执行的代码段:

foreach (BundleFileSetordering ordering in (IEnumerable<BundleFileSetordering>) context.BundleCollection.FileSetorderList)
    DefaultBundleOrderer.AddOrderingFiles(ordering,(IEnumerable<FileInfo>) list,fileMap,foundFiles,result);

所以不同的结果是因为这样.这当然不是随机排序算法:)
规则在BUndleCollection类中定义:

public static void AddDefaultFileOrderings(IList<BundleFileSetordering> list)
{
  if (list == null)
    throw new ArgumentNullException("list");
  BundleFileSetordering bundleFileSetordering1 = new BundleFileSetordering("css");
  bundleFileSetordering1.Files.Add("reset.css");
  bundleFileSetordering1.Files.Add("normalize.css");
  list.Add(bundleFileSetordering1);
  BundleFileSetordering bundleFileSetordering2 = new BundleFileSetordering("jquery");
  bundleFileSetordering2.Files.Add("jquery.js");
  bundleFileSetordering2.Files.Add("jquery-min.js");
  bundleFileSetordering2.Files.Add("jquery-*");
  bundleFileSetordering2.Files.Add("jquery-ui*");
  bundleFileSetordering2.Files.Add("jquery.ui*");
  bundleFileSetordering2.Files.Add("jquery.unobtrusive*");
  bundleFileSetordering2.Files.Add("jquery.validate*");
  list.Add(bundleFileSetordering2);
  BundleFileSetordering bundleFileSetordering3 = new BundleFileSetordering("modernizr");
  bundleFileSetordering3.Files.Add("modernizr-*");
  list.Add(bundleFileSetordering3);
  BundleFileSetordering bundleFileSetordering4 = new BundleFileSetordering("dojo");
  bundleFileSetordering4.Files.Add("dojo.*");
  list.Add(bundleFileSetordering4);
  BundleFileSetordering bundleFileSetordering5 = new BundleFileSetordering("moo");
  bundleFileSetordering5.Files.Add("mootools-core*");
  bundleFileSetordering5.Files.Add("mootools-*");
  list.Add(bundleFileSetordering5);
  BundleFileSetordering bundleFileSetordering6 = new BundleFileSetordering("prototype");
  bundleFileSetordering6.Files.Add("prototype.js");
  bundleFileSetordering6.Files.Add("prototype-*");
  bundleFileSetordering6.Files.Add("scriptaculous-*");
  list.Add(bundleFileSetordering6);
  BundleFileSetordering bundleFileSetordering7 = new BundleFileSetordering("ext");
  bundleFileSetordering7.Files.Add("ext.js");
  bundleFileSetordering7.Files.Add("ext-*");
  list.Add(bundleFileSetordering7);
}

所以当你从Application_Start调用它:

BundleConfig.RegisterBundles(BundleTable.Bundles);

实际上,您传递库中定义的认BundleCollection.

所以我们将BundleFileSetordering实例逐个传递到:

private static void AddOrderingFiles(BundleFileSetordering ordering,IEnumerable<FileInfo> files,Dictionary<string,HashSet<FileInfo>> fileMap,HashSet<FileInfo> foundFiles,List<FileInfo> result)
{
  foreach (string key in (IEnumerable<string>) ordering.Files)
  {
    if (key.EndsWith("*",StringComparison.OrdinalIgnoreCase))
    {
      string str = key.Substring(0,key.Length - 1);
      foreach (FileInfo fileInfo in files)
      {
        if (!foundFiles.Contains(fileInfo) && fileInfo.Name.StartsWith(str,StringComparison.OrdinalIgnoreCase))
        {
          result.Add(fileInfo);
          foundFiles.Add(fileInfo);
        }
      }
    }
    else if (fileMap.ContainsKey(key))
    {
      List<FileInfo> list = new List<FileInfo>((IEnumerable<FileInfo>) fileMap[key]);
      list.sort((IComparer<FileInfo>) FileInfoComparer.Instance);
      foreach (FileInfo fileInfo in list)
      {
        if (!foundFiles.Contains(fileInfo))
        {
          result.Add(fileInfo);
          foundFiles.Add(fileInfo);
        }
      }
    }
  }
}

结论

如果我们想要简化这个过程,我们可以说,如果找到多个可能的话,这个库优先选择某种文件,并对其他文件进行一些排序.这是大多数时候的预期行为,但是您可以看到它与AsDefinedBundleOrderer很容易覆盖,所以它对给定的文件集没有任何影响,因此顺序仍然是原始的.

相关文章

### 创建一个gRPC服务项目(grpc服务端)和一个 webapi项目(...
一、SiganlR 使用的协议类型 1.websocket即时通讯协议 2.Ser...
.Net 6 WebApi 项目 在Linux系统上 打包成Docker镜像,发布为...
一、 PD简介PowerDesigner 是一个集所有现代建模技术于一身的...
一、存储过程 存储过程就像数据库中运行的方法(函数) 优点:...
一、Ueditor的下载 1、百度编辑器下载地址:http://ueditor....