85

I'm trying to use a specific locale (es-CL) in my ASP.NET MVC 5 application. I've the following:

  1. Changed web.config uiculture and culture to "es-CL"
  2. Installed the Globalize and jQuery.Validation.Globalize packages
  3. Changed the default language in my views: <html lang="es-cl">
  4. Created a new Bundle and included in the appropriate views.

In BundleConfig.cs:

bundles.Add(new ScriptBundle("~/bundles/jqueryval")
    .Include("~/Scripts/jquery.validate.js")
    .Include("~/Scripts/jquery.validate.unobtrusive.js"));

bundles.Add(new ScriptBundle("~/bundles/globalization")
    .Include("~/Scripts/globalize/globalize.js")
    .Include("~/Scripts/globalize/cultures/globalize.culture.es-CL.js")
    .Include("~/Scripts/jquery.validate.globalize.js"));

In the appropriate views:

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/bundles/globalization")
}

However, the generated source code is the following:

<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>

<script src="/Scripts/jquery.validate.globalize.js"></script>
<script src="/Scripts/globalize/globalize.js"></script>
<script src="/Scripts/globalize/cultures/globalize.culture.es-CL.js"></script>

Please note that the jquery.validate.globalize.js script is being loaded before globalize.js, which is not what I want.

Why is this happening? Is it possible to rely in the include order in a single bundle, or am I forced to put this single script in a different bundle and specify it in my view?

6
  • 1
    Have a look at this question stackoverflow.com/questions/11979718/… Commented Oct 11, 2013 at 17:03
  • @PaulMcCowat yes, but I'm not using the minified versions yet. I'm using Microsoft.AspNet.Web.Optimizations 1.1.0. Commented Oct 11, 2013 at 17:08
  • @LeonardoHerrera I would think it is like Chris mentioned in his comments, that known files are moved around to an order specified by the bundler... but I can't be sure since I don't know what those files are, which led me to ask. I'll be interested to know if using the IBundleOrderer works for you since specifying the order didn't. Commented Oct 11, 2013 at 19:36
  • look at @Softlion answer in [this link][1] [1]: stackoverflow.com/questions/11979718/… Commented Jun 17, 2015 at 7:02
  • @section Scripts { @Scripts.Render("~/bundles/jqueryval") } appears to have resolved the issue of my scripts loading out of order.... Commented Nov 10, 2016 at 16:25

3 Answers 3

104

By default, bundling order is alphabetical for names with wildcards (as pointed out in the comments). However, it also orders based on what it thinks your dependency tree is, and jQuery scripts seem to get slotted to the top. You need to create an object that implement IBundleOrder:

class NonOrderingBundleOrderer : IBundleOrderer
{
    public IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files)
    {
        return files;
    }
}

This prevents the default ordering. Now to use it:

var bundle = new ScriptBundle("~/bundles/globalization")
    .Include("~/Scripts/globalize/globalize.js")
    .Include("~/Scripts/globalize/cultures/globalize.culture.es-CL.js")
    .Include("~/Scripts/jquery.validate.globalize.js");

bundle.Orderer = new NonOrderingBundleOrderer();

bundles.Add(bundle);

ref: http://stevescodingblog.co.uk/changing-the-ordering-for-single-bundles-in-asp-net-4/

For further reading, an answer to MikeSmithDev's question provides further insight into the default ordering for popular script libraries:

Ordering of Files within a bundle - What are the known libraries?

Sign up to request clarification or add additional context in comments.

10 Comments

Not to nitpick, but "by default, bundling order is alphabetical" is true when you use things like wild cards... when you specify the order, like he has, it should use his order. I can only assume the bundler is moving around known file types and is ignoring his order.
It looks like the bundler also orders using some logic about dependencies. It thinks that jquery.validate.globalize.js is required for the other two. From the ref: "[The bundler] will even put known framework javascript files first in the bundle automatically, such as jQuery or Prototype scripts, to make sure they run before your own code which uses their types gets executed"
The spesific order is: jquery.js jquery-min.js jquery-* jquery-ui* jquery.ui* jquery.unobtrusive* jquery.validate* modernizr-* dojo.* mootools-core* mootools-* prototype.js prototype-* scriptaculous-* ext.js ext-*
here is where programming is not fun. why VS make this complicated?
The fact that this exists blows my mind with how stupid it is. Really.. the bundler knows better how to order my dependencies better than I've typed them? Gulp.js (or even Grunt) FTW!
|
31

In the last version of MVC 5 (at october 27 of 2014), yo should use this class instead:

class AsIsBundleOrderer : IBundleOrderer
{
    public IEnumerable<BundleFile> OrderFiles(BundleContext context, IEnumerable<BundleFile> files)
    {
        return files;
    }
}

And create the bundle like the other response:

var bundle = new ScriptBundle("~/bundles/globalization")
.Include("~/Scripts/globalize/globalize.js")
.Include("~/Scripts/globalize/cultures/globalize.culture.es-CL.js")
.Include("~/Scripts/jquery.validate.globalize.js");

bundle.Orderer = new AsIsBundleOrderer();

bundles.Add(bundle);

4 Comments

Where can I find this info? Can you provide a link please?
I just try to use the method of the current response for this question but I found my selkf with an error in ASP.NET MVC 5, so I check the IBundleOrderer interface and made the changes
There is no Orderer Property. I am using MVC 5.2.x
I just test it with MVC 5.2.3 and tehres is the Orderer Property.
30

To reduce the codes during creating bundles, I suggest you create an extension method.

Require infrastructure classes:

class NonOrderingBundleOrderer : IBundleOrderer
{
    public IEnumerable<BundleFile> OrderFiles(BundleContext context, IEnumerable<BundleFile> files)
    {
        return files;
    }
}


static class BundleExtentions
{
    public static Bundle NonOrdering(this Bundle bundle)
    {
        bundle.Orderer=new NonOrderingBundleOrderer();
        return bundle;
    }
}

Now simply use it like this:

All in one command 😎

bundles.Add(new ScriptBundle("~/bundles/jqueryval")
               .NonOrdering()
               .Include(
                    "~/Scripts/globalize/globalize.js",
                    "~/Scripts/globalize/cultures/globalize.culture.es-CL.js",
                    //...
                );

1 Comment

Nice way of thinking!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.