Получаете ошибку при отображении изображений из App_Themes при использовании предварительной компиляции?

У меня есть сайт ASP.NET с разделами WebForms и MVC. Когда я пытаюсь предварительно скомпилировать сайт, все работает, кроме предоставления изображений / css из App_Themes.

Если я запрошу что-то вроде /foo/App_Themes/themeName/my.png, я получаю такую ​​ошибку:

The file '/foo/App_Themes/themeName/my.png.cshtml' is in the special directory 'App_Themes', which is not allowed.

Я получаю это только при предварительной компиляции, в остальном все работает нормально. Предположительно, маршрутизация MVC каким-то образом мешает, но я не знаю, почему и как ее отключить.

Если это полезно, вот трассировка стека:

System.Web.Compilation.BuildManager.ValidateVirtualPathInternal(VirtualPath virtualPath, Boolean allowCrossApp, Boolean codeFile) +9930801
System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) +455
System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) +103
System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound) +165
System.Web.Compilation.BuildManager.GetObjectFactory(String virtualPath, Boolean throwIfNotFound) +33
System.Web.WebPages.BuildManagerWrapper.GetObjectFactory(String virtualPath) +26
System.Web.WebPages.BuildManagerWrapper.ExistsInPrecompiledSite(String virtualPath) +80
System.Web.WebPages.BuildManagerWrapper.Exists(String virtualPath) +13
System.Web.WebPages.<>c__DisplayClass1.<Exists>b__0(IVirtualPathFactory factory) +15
System.Linq.Enumerable.Any(IEnumerable`1 source, Func`2 predicate) +146
System.Web.WebPages.VirtualPathFactoryManager.Exists(String virtualPath) +73
System.Web.WebPages.DefaultDisplayMode.GetDisplayInfo(HttpContextBase httpContext, String vir tualPath, Func`2 virtualPathExists) +42
System.Web.WebPages.<>c__DisplayClassb.<GetDisplayInfoForVirtualPath>b__8(IDisplayMode mode) +22
System.Linq.WhereSelectListIterator`2.MoveNext() +104
System.Linq.Enumerable.FirstOrDefault(IEnumerable`1 source, Func`2 predicate) +94
System.Web.WebPages.DisplayModeProvider.GetDisplayInfoForVirtualPath(String virtualPath, HttpContextBase httpContext, Func`2 virtualPathExists, IDisplayMode currentDisplayMode, Boolean requireConsistentDisplayMode) +204
System.Web.WebPages.WebPageRoute.GetRouteLevelMatch(String pathValue, IEnumerable`1 supportedExtensions, IVirtualPathFactory virtualPathFactory, HttpContextBase context, DisplayModeProvider displayModeProvider) +201
System.Web.WebPages.WebPageRoute.MatchRequest(String pathValue, IEnumerable`1 supportedExtensions, IVirtualPathFactory virtualPathFactory, HttpContextBase context, DisplayModeProvider displayModes) +281
System.Web.WebPages.WebPageRoute.DoPostResolveRequestCache(HttpContextBase context) +235
System.Web.WebPages.WebPageHttpModule.OnApplicationPostResolveRequestCache(Object sender, EventArgs e) +89
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69 

person Scott Stafford    schedule 21.01.2014    source источник
comment
Это не MVC-маршрутизация, поскольку любая из App_XXX папок считается особыми папками в IIS. Учитывая, что роль папки App_Themes заключалась в том, чтобы позволить вам предоставлять файлы css / images / skin для элементов управления WebForms, а роль этой папки обесценивается (отсутствие лучшего слова) в MVC, я бы предположил, что установлен механизм просмотра бритвы чтобы выдать ошибку при проверке путей к вашим файлам содержимого. В любом из выполненных мною поисков упоминается, что эта папка больше не актуальна для сайта MVC, и даже в некоторых упоминается необходимость включения <head runat="server"> в более ранние версии MVC.   -  person Tommy    schedule 22.01.2014
comment
Вышеупомянутое предположение об исключении основано на первой строке трассировки стека. Вот пример необходимости изменить конвейер в приложении с той же ошибкой: forum.smartertools.com/threads/   -  person Tommy    schedule 22.01.2014
comment
@Tommy: Полагаю, именно поэтому никто в Интернете, кажется, никогда не жил в моем аду на сегодня. Я думаю, что у меня есть патч от IgnoreRoute'ing App_Themes, который я опубликую в качестве ответа, если он продолжит успешно тестировать.   -  person Scott Stafford    schedule 22.01.2014
comment
Согласны, информации о MVC и папке App_Themes почти не было, удачи вам в работе!   -  person Tommy    schedule 22.01.2014
comment
Вздох ... routes.IgnoreRoute("App_Themes/{*anything}"); исправил это локально в Cassini, но не повлиял на развертывание в IIS6. Необъяснимо.   -  person Scott Stafford    schedule 22.01.2014
comment
Это работало в Win2008 / IIS7: routes.IgnoreRoute ({appthemes}, new {appthemes = @App_Themes (/.)?});   -  person BoKDamgaard    schedule 22.08.2014
comment
Вы когда-нибудь находили решение этой проблемы? У меня такая же проблема, и я могу исправить ее, только изменив атрибут runAllManagedModulesForAllRequests узла модулей в web.config на false, однако я ищу решение, которое позволяет мне сохранить это как истинное   -  person user2945722    schedule 03.01.2017


Ответы (1)


У меня была такая же проблема, но она возникла только тогда, когда я опубликовал свое веб-приложение, и работал нормально локально. Я придумал два возможных решения.

Хакерское решение

Посмотрев на исходный код, я увидел, что он выдавал эту ошибку, поскольку объект «BuildManager» имел поле «_forbiddenTopLevelDirectories», которое он проверял и выдавал ожидание, если бы путь находился в нескольких специальных каталогах, одним из которых является «App_Themes». их.

Поэтому, используя отражение, я удаляю объект «App_Themes» из коллекции, вызывая следующий код в методе глобального файла Application_Start.

        var buildManagerType = typeof(BuildManager);
        var theBuilderManager = buildManagerType.GetField("_theBuildManager"
             , BindingFlags.Static | BindingFlags.NonPublic)
             .GetValue(null);

        var forbiddenDirectoryField = buildManagerType
        .GetField("_forbiddenTopLevelDirectories",
        BindingFlags.Instance | BindingFlags.NonPublic)
       .GetValue(theBuilderManager);

        var removeMethod = forbiddenDirectoryField.GetType().GetMethod("Remove");

        removeMethod.Invoke(forbiddenDirectoryField, new object[] { "App_Themes" });

Это решило проблему, и мои файлы изображений css + теперь будут корректно обслуживаться при развертывании. Предупреждение. Я плохо понимаю последствия редактирования поля _forbiddenTopLevelDirectories, и это может иметь непредвиденные побочные эффекты.

Альтернативное решение

Еще я заметил, что я не получал ошибок, если для атрибута runAllManagedModulesForAllRequests узла модулей в webconfig было установлено значение false. Поэтому, если ваше приложение может работать с этим набором false, рассмотрите это решение

<modules runAllManagedModulesForAllRequests="false">

person user2945722    schedule 03.01.2017