ASP.Net MVC/Web API Custom Dynamic Bundle, работающий в рабочей среде, но не Dev

В моей среде разработки я получаю 404 ответа при попытке загрузить динамически сгенерированный пакет. Как ни странно, этого не происходит в нашей производственной среде, так что это не совсем катастрофично, но делает разработку немного разочаровывающей.

Что должно произойти, это:

  1. При предварительном запуске приложения (WebActivator PreStart) настройте компоненты Dependency Resolver, Web API и MVC.
  2. При пост-запуске приложения (WebActivator PostStart) загрузите сервис через средство разрешения зависимостей (скажем, IMyService).
  3. Создавать обычай IBundleTransform (JsonBundleTransform - см. ниже для кода).
  4. Вызов IEnumerable<string> IMyService.ListSupportedGroups(),
  5. Перебрать поддерживаемые группы и создать собственный пакет (CustomBundle - увидеть ниже...).
  6. Добавить пользовательские пакеты в BundleTable.Bundles,
  7. Добавить статические файлы JS/CSS в BundleTable.Bundles,
  8. Ссылаться на различные пакеты на страницах и просматривать содержимое в браузере.

Сбой на шаге 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" включенным, но это имеет проблемы с производительностью, поскольку нет никаких причин для запуска статических файлов через весь управляемый конвейер.

Другие вопросы по тегам