MVC4 - Связывание не работает, если для оптимизаций установлено значение true
Интересно, что я здесь не делаю. Я использую ASP.NET С# MVC4, и я хочу использовать новую функцию оптимизации css/js.
Вот моя часть HTML
@Styles.Render("~/content/css")
Вот моя часть BunduleConfig.cs
bundles.Add(new StyleBundle("~/content/css").Include(
"~/content/css/reset.css",
"~/content/css/bla.css"));
// BundleTable.EnableOptimizations = true;
Выход (работает):
<link href="/content/css/reset.css" rel="stylesheet"/>
<link href="/content/css/bla.css" rel="stylesheet"/>
Однако, когда я раскомментирую BundleTable.EnableOptimizations = true;
вывод html, это выглядит как
<link href="/content/css?v=5LoJebKvQJIN-fKjKYCg_ccvmBC_LF91jBasIpwtUcY1" rel="stylesheet"/>
И это, конечно, 404. Я понятия не имею, где я сделал что-то не так, пожалуйста, помогите, впервые работая с MVC4.
Ответы
Ответ 1
Я предполагаю, что проблема заключается в том, что вы помещаете пакет в виртуальный URL, который на самом деле существует, но является каталогом.
MVC создает виртуальный файл из вашего пакета и обслуживает его по пути, указанному вами как путь к пакету.
Правильное решение этой проблемы состоит в том, чтобы использовать путь пакета, который непосредственно не сопоставляется с существующим каталогом, и вместо этого использует в этом каталоге имя виртуального файла (которое также не отображается на имя реального файла).
Пример:
Если на вашем сайте есть папка с именем /content/css, сделайте свой css-пакет следующим образом:
В BundleConfig.cs:
bundles.Add(new StyleBundle("~/content/css/AllMyCss.css").Include(
"~/content/css/reset.css",
"~/content/css/bla.css"));
И на странице:
@Styles.Render("~/content/css/AllMyCss.css")
Обратите внимание, что это предполагает, что у вас нет файла с именем AllMyCss.css в вашей папке css.
Ответ 2
Я не уверен, что это веб-оптимизация, или WebGrease, которая настолько придирчива, но одна (или и то и другое) из них, и вам нужно быть предельно осторожным.
Прежде всего, в коде нет ничего плохого:
bundles.Add(new StyleBundle("~/content/css").Include(
"~/content/css/reset.css",
"~/content/css/bla.css"));
Фактически это именно то, что делает Microsoft. Основная причина, по которой они не используют ~/bundles
для css, заключается в том, что относительные пути закручиваются для изображений. Подумайте о том, как ваш браузер видит пакет - точно так же, как он видит какой-либо другой URL-адрес, и все правила нормального пути все еще применяются в отношении относительных путей. Представьте, что у вашего css был путь изображения к ../images/bullet.png
. Если вы использовали ~/bundles
, браузер будет искать в каталоге выше bundles
, который фактически не существует. Вероятно, это будет выглядеть в ~/images
, где вы, вероятно, имеете его в ~/content/images
.
Я нашел пару вещей, которые могут действительно сломать его и вызвать 404 ошибки:
- FYI: моя структура каталогов
Content/CSS
, которая содержит папку images
для изображений CSS.
- У меня есть
EnableOptimizations=true
для принудительного использования пакетов при тестировании
- Первое, что вам нужно сделать, это "View Source" и просто нажать на ссылки css, чтобы увидеть, работают ли они.
Скажем, мы разрабатываем сайт о кошках. У вас может быть этот
@Styles.Render("~/Content/css/cats.css") // dont do this - see below why
bundles.Add(new StyleBundle("~/content/css/cats.css").Include(
"~/content/css/reset.css",
"~/content/css/bla.css"));
Это создает ссылку CSS для этого пути в вашем HTML:
/Content/css/cats.css?v=JMoJspikowDah2auGQBfQAWj1OShXxqAlXxhv_ZFVfQ1
Однако это даст 404, потому что я поставил расширение .css и IIS (я думаю) запутался.
Если я изменю его на это, тогда он отлично работает:
@Styles.Render("~/Content/css/cats")
bundles.Add(new StyleBundle("~/content/css/cats").Include(
"~/content/css/reset.css",
"~/content/css/bla.css"));
Еще одна проблема, уже упомянутая другими, заключается в том, что вы не должны делать
@Styles.Render("~/Content/css")
если у вас есть каталог или файл css (вряд ли у вас будет файл с именем css
без расширения) в вашем каталоге Content
.
Дополнительный трюк заключается в том, что вам нужно убедиться, что ваш сгенерированный HTML имеет номер версии
<link href="/Content/css/cats?v=6GDW6wAXIN5DJCxVtIkkxLGpojoP-tBQiKgBTQMSlWw1" rel="stylesheet"/>
Если это не так и выглядит так, то у вас, вероятно, нет точного соответствия имени пакета между вашей таблицей Bundle и в вашем файле cshtml.
<link href="/Content/css/cats" rel="stylesheet"/>
Ответ 3
Не забудьте убедиться, что существует пакет HttpModule.
<modules>
<remove name="BundleModule" />
<add name="BundleModule" type="System.Web.Optimization.BundleModule" />
</modules>
Это ужалило меня в первый раз. Не уверен, что необходимая конфигурация должна быть добавлена пакетом NuGet, но это было не в моем случае.
Ответ 4
Это выглядит правильно для меня. Когда оптимизация включена, вы будете иметь только один ref, и это будет имя, указанное вами в вашем StyleBundle (/content/css). В режиме отладки (или более конкретно с debug = false в вашей веб-конфигурации) вы получите не оптимизированные файлы как обычно. Если вы посмотрите, вы увидите, что они просто текст, когда вы их набрали. Однако при включении оптимизаций (обычно, когда вы запускаете в режиме деблокирования) вместо этого вы получите wierd look URL.
Если вы посмотрите на результат этого, он будет уменьшен. Строка запроса? V = 5KLoJ.... основана на хэше, взятом из файлов в комплекте. Это так, что ссылка может быть безопасно кэширована HTTP столько, сколько вы хотите. Навсегда, если вы хотите, но я думаю, что по умолчанию - год. Однако, если вы измените какую-либо из своих таблиц стилей, она создаст новый хеш и "перехватит кеш", чтобы вы получили новую копию в браузере.
Сказав все это, я не уверен, почему вы получаете 404. Я подозреваю, что это связано с вашей конфигурацией маршрутизации или с настройкой IIS. Вы работаете в Visual Studio с помощью IISExpress?
Ответ 5
Я просто решил аналогичную проблему. Проблема заключалась в следующем: я установил "выбрано" через NuGet
.
И в классе BundleConfig
строка, содержащая файл CSS
, выглядела так:
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css",));
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/chosen.css"));
В некоторых случаях, когда в этом классе я имел следующую строку:
BundleTable.EnableOptimizations = true;
Исправление состояло в том, чтобы объединить 2 bundles.Add()
следующим образом:
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/site.css",
"~/Content/chosen.css"
));
И это исправило это для меня.
Ответ 6
Это также может быть связано с тем, что по какой-то причине вы не развернули пакет bundleconfig.json на сервере.