ASP.Net MVC/Web API Custom Dynamic Bundle, работающий в рабочей среде, но не Dev
В моей среде разработки я получаю 404 ответа при попытке загрузить динамически сгенерированный пакет. Как ни странно, этого не происходит в нашей производственной среде, так что это не совсем катастрофично, но делает разработку немного разочаровывающей.
Что должно произойти, это:
- При предварительном запуске приложения (WebActivator PreStart) настройте компоненты Dependency Resolver, Web API и MVC.
- При пост-запуске приложения (WebActivator PostStart) загрузите сервис через средство разрешения зависимостей (скажем,
IMyService
). - Создавать обычай
IBundleTransform
(JsonBundleTransform
- см. ниже для кода). - Вызов
IEnumerable<string> IMyService.ListSupportedGroups()
, - Перебрать поддерживаемые группы и создать собственный пакет (
CustomBundle
- увидеть ниже...). - Добавить пользовательские пакеты в
BundleTable.Bundles
, - Добавить статические файлы JS/CSS в
BundleTable.Bundles
, - Ссылаться на различные пакеты на страницах и просматривать содержимое в браузере.
Сбой на шаге 8 для пользовательских пакетов с ошибками 404. При отладке пользовательский преобразователь пакета никогда не вызывается. Однако, как я уже упоминал выше, в работе все работает нормально, хотя я сравнил файлы конфигурации и не вижу ничего, чего не хватает в моих конфигурациях dev, которые должны иметь какой-либо эффект. Кроме того, в производстве связанный контент отображается правильно, независимо от значения compilation->debug в web.config.
Другие заметки:
- Я использую IIS 7.5 в производстве, IIS 8 в разработке.
- Когда я устанавливаю debug="false" в dev, я получаю 404 на все мои связки.
- Это работало, но остановилось в какой-то момент, и я не могу определить, когда или почему это произошло.
Код, который я использую, выглядит следующим образом (избыточный код удален, имена изменены для защиты невинных и т. Д.):
Преобразование
public class JsonBundleTransform: IBundleTransform
{
public void Process( BundleContext context, BundleResponse response )
{
var bundle = context.BundleCollection.FirstOrDefault(b => b.Path == context.BundleVirtualPath) as CustomBundle;
response.Content = string.Format( ";var obj = {0};", JsonConvert.SerializeObject( bundle.KeyValues ) );
response.ContentType = "application/javascript";
response.Cacheability = HttpCacheability.Server;
}
}
Custom Bundle
public class CustomBundle: Bundle
{
public CustomBundle( string virtualPath, IBundleTransform transform, IMyService myService, string groupId ) : base( virtualPath, transform )
{
keyValues = myService.GetKeyValuesByGroupId( groupId );
}
public IDictionary<string, string> KeyValues { get; private set; }
}
Конфиг
public class BundleConfig
{
public static void RegisterBundles( BundleCollection bundles, IMyService myService )
{
var transform = new JsonBundleTransform();
var jsonBundles = myService
.ListSupportedGroups()
.Select( groupId =>
new CustomBundle(
string.Format( "~/resource/script/keyValues-{0}.js", groupId ),
transform,
myService,
groupId
)
);
foreach ( var jsonBundle in jsonBundles ) {
bundles.Add( jsonBundle );
}
// Static bundles added here...
}
}
Рендеринг сценария
@Scripts.Render( Url.Content( string.Format( "~/resource/script/keyValues-{0}.js", Model.GroupId ) ) ) )
Есть идеи, что мне здесь не хватает, чтобы заставить это работать?
Заранее спасибо за любую помощь или совет.
редактировать
Учитывая, что он работает в производстве, я твердо склоняюсь к мысли, что проблема - это проблема окружающей среды, а не проблема кода - хотя, по жизни я не могу понять, что это такое. Я думаю, что наиболее вероятный кандидат - это что-то делать с настройками или ссылками (если честно, версии IIS кажутся маловероятными).
1 ответ
Если вы добавите ".js" к виртуальному пути ваших пакетов, IIS будет интерпретировать любой запрос для этих пакетов как запрос статического файла, если только:
- Вы поручили IIS запускать все управляемые модули для всех запросов.
- Вы явно настроили IIS для обработки URL-адресов вашего пакета с помощью обработчика маршрутизации
Если вы сравниваете производственную и dev-конфигурацию, я подозреваю, что вы обнаружите, что для рабочей среды установлено значение "runAllManagedModulesForAllRequests", равное "true".
Самое простое решение этой проблемы - просто удалить расширение ".js" из виртуальных путей ваших пакетов. Если вы предпочитаете сохранить расширение, вы можете настроить IIS для передачи запросов обработчику маршрутизации:
<system.webServer>
<handlers>
<add name="UrlRoutingHandler"
type="System.Web.Routing.UrlRoutingHandler,
System.Web, Version=4.0.0.0,
Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
path="/resource/script/*"
verb="GET"/>
</handlers>
</system.webServer>
Вы также можете оставить "runAllManagedModulesForAllRequests" включенным, но это имеет проблемы с производительностью, поскольку нет никаких причин для запуска статических файлов через весь управляемый конвейер.