ASP.NET MVC - порядок конфигурации пакета

84

Я пытаюсь использовать конкретный языковой стандарт (es-CL) в своем приложении ASP.NET MVC 5. Имею следующее:

  1. Изменено uiculture и culture в web.config на "es-CL".
  2. Установлены пакеты Globalize и jQuery.Validation.Globalize
  3. Изменил язык по умолчанию в моих представлениях: <html lang="es-cl">
  4. Создал новый Bundle и включил в соответствующие представления.

В 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"));

В соответствующих представлениях:

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

Однако сгенерированный исходный код выглядит следующим образом:

<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>

Обратите внимание, что скрипт jquery.validate.globalize.js загружается раньше globalize.js , а я не хочу.

Почему это происходит? Можно ли полагаться на порядок включения в одном пакете, или я вынужден поместить этот единственный скрипт в другой пакет и указать его в моем представлении?

Леонардо Эррера
источник
1
Взгляните на этот вопрос stackoverflow.com/questions/11979718/…
Пол МакКоват
@PaulMcCowat да, но я еще не использую мини-версии. Я использую Microsoft.AspNet.Web.Optimizations 1.1.0.
Леонардо Эррера
@LeonardoHerrera Я бы подумал, что это похоже на то, что Крис упомянул в своих комментариях, что известные файлы перемещаются в порядке, указанном сборщиком ... но я не могу быть уверен, так как я не знаю, что это за файлы, что привело меня спросить . Мне будет интересно узнать, работает ли для вас использование IBundleOrderer, поскольку указание порядка не помогло.
MikeSmithDev
посмотрите ответ @Softlion в [эта ссылка] [1] [1]: stackoverflow.com/questions/11979718/…
Omid-RH
@section Scripts { @Scripts.Render("~/bundles/jqueryval") }похоже, решил проблему с загрузкой моих скриптов не по порядку ....
petrosmm

Ответы:

103

По умолчанию, для имен с подстановочными знаками порядок объединения является алфавитным (как указано в комментариях). Однако он также упорядочивает на основе того, что, по его мнению, является вашим деревом зависимостей, и jQueryскрипты, кажется, занимают верхние позиции. Вам необходимо создать объект, реализующий IBundleOrder:

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

Это предотвращает порядок по умолчанию. Теперь использовать его:

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

ссылка: http://stevescodingblog.co.uk/changing-the-ordering-for-single-bundles-in-asp-net-4/

Для дальнейшего чтения ответ на вопрос MikeSmithDev дает более подробное представление о порядке по умолчанию для популярных библиотек сценариев:

Упорядочивание файлов в пакете - какие библиотеки известны?

Мистер Эпик
источник
Не для придирки, но «по умолчанию порядок комплектации в алфавитном порядке» верен, когда вы используете такие вещи, как подстановочные знаки ... когда вы указываете порядок, как он, он должен использовать его порядок. Я могу только предположить, что сборщик перемещается по известным типам файлов и игнорирует свой заказ.
MikeSmithDev
Похоже, что сборщик также заказывает, используя некоторую логику зависимостей. Он считает, что jquery.validate.globalize.jsэто необходимо для двух других. Из ссылки: «[Сборщик] даже автоматически помещает известные файлы javascript фреймворка в пакет автоматически, такие как сценарии jQuery или Prototype, чтобы убедиться, что они выполняются до того, как будет выполнен ваш собственный код, использующий их типы»
Мистер Эпик,
3
Конкретный порядок: 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- *
ravndal
6
вот где программирование - это не развлечение. почему VS усложняют это?
Jaider
5
Тот факт, что это существует, поражает меня тем, насколько это глупо. В самом деле ... сборщик лучше знает, как упорядочить мои зависимости, чем я их ввел? Gulp.js (или даже Grunt) FTW!
Джон Калвинер,
30

В последней версии MVC 5 (от 27 октября 2014 г.) вам следует использовать вместо этого этот класс:

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

И создайте пакет, как и другой ответ:

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);
Себастьян Рохас
источник
Где я могу найти эту информацию? Не могли бы вы дать ссылку?
PussInBoots 06
Я просто пытаюсь использовать метод текущего ответа на этот вопрос, но я обнаружил, что у меня селкф с ошибкой в ​​ASP.NET MVC 5, поэтому я проверил интерфейс IBundleOrderer и внес изменения
Себастьян Рохас
Свойство Заказчика отсутствует. Я использую MVC 5.2.x
Legends
1
Я просто тестирую его с помощью MVC 5.2.3, а tehres - это свойство Orderer.
Себастьян Рохас
29

Чтобы уменьшить количество кодов при создании пакетов, я предлагаю вам создать метод расширения.

Требуются классы инфраструктуры:

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

Теперь просто используйте это так:

Все в одной команде 😎

bundles.Add(new ScriptBundle("~/bundles/jqueryval")
               .NonOrdering()
               .Include(
                    "~/Scripts/globalize/globalize.js",
                    "~/Scripts/globalize/cultures/globalize.culture.es-CL.js",
                    //...
                );
баран
источник
1
Хороший образ мышления!
Аруна