使用预编译时从App_Themes提供图像时出错?

时间:2014-01-21 20:12:51

标签: asp.net asp.net-mvc app-themes

我有一个包含WebForms和MVC部分的ASP.NET站点。当我尝试预编译网站时,一切都有效,除了在App_Themes下提供图像/ css。

如果我要求/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 

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,但只有在我发布我的网络应用程序时才会发生,并且在本地工作正常。我想出了两个可能的解决方案。

Hacky解决方案

通过查看源代码我可以看到它抛出了这个错误,因为“BuildManager”对象有一个字段“_forbiddenTopLevelDirectories”,如果路径位于许多特殊目录中,它会检查并抛出一个预测,“App_Themes “成为其中之一。

因此,通过使用反射,我通过调用全局文件Application_Start方法中的以下代码从集合中删除“App_Themes”对象。

        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字段的后果并不了解,这可能会产生意想不到的副作用。

替代解决方案

我注意到的另一件事是,当webconfig中模块节点的runAllManagedModulesForAllRequests属性设置为false时,我不会收到错误。因此,如果您的应用程序可以使用此设置为false,请考虑此解决方案

<modules runAllManagedModulesForAllRequests="false">