Getting an error serving images from App_Themes when using precompilation?

醉酒当歌 提交于 2019-12-08 08:24:40

问题


I have an ASP.NET site with both WebForms and MVC sections to it. When I try to precompile the site, everything works except serving images/css from under App_Themes.

If I request something like /foo/App_Themes/themeName/my.png, I get this error:

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

I only get this when precompiling, it works fine otherwise. Presumably MVC routing is interfering somehow, but I don't know why or how to disable it.

In case it's helpful, here's the stack trace:

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 

回答1:


I was having the same issue but it only occured when I published my web application and would work fine locally. I came up with two potential solutions.

Hacky solution

By looking at the source code I could see it was throwing this error as the "BuildManager" object had a field "_forbiddenTopLevelDirectories" which it would check and throw an expection if the path was in a number of special directories, "App_Themes" being one of them.

So by using reflection I remove the "App_Themes" object from the collection by calling the following code in the global file Application_Start method.

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

This solved the issue and my css + image files would now be correctly served when deployed. Warning - I do not have a good understanding of the consequences of editing the _forbiddenTopLevelDirectories field and doing this may have unintended side effects.

Alternative solution

Another thing i noticed was I would not recieve the errors when the runAllManagedModulesForAllRequests attribute of the modules node in the webconfig was set to false. So if your application can work with this set to false consider this solution

<modules runAllManagedModulesForAllRequests="false">



来源:https://stackoverflow.com/questions/21268124/getting-an-error-serving-images-from-app-themes-when-using-precompilation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!