Getting an error serving images from App_Themes when using precompilation? - asp.net

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

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">

Related

What is causing the double folder in the url path when redirecting?

I have migrated an old, but unfortunately still in use application from one server to another. The code has not been touched whatsoever. Basically a copy and paste from one server (Windows Server 2003) to the other (Windows Server 2016 Standard).
AFAIK, this error never occurred on the previous server, however now when redirecting to a specific page, the file containing folder is duplicated in the path.
New server is using IIS Version 10.
As this worked fine on the previous server, and no code has been touched, I assume this is some setting than needs tweaking in IIS/web.config.
What could be causing this?
I have compared IIS settings between the two servers. But these versions are so far part there is not really much to compare.
Here is the error from the log:
An unhandled exception occurred:
System.Web.HttpException (0x80004005): The file ´/SearchAndOrder/SearchAndOrder/ConfirmBasket.aspx´ does not exist.
at System.Web.UI.Util.CheckVirtualFileExists(VirtualPath virtualPath)
at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound)
at System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp)
at System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath)
at System.Web.UI.PageHandlerFactory.System.Web.IHttpHandlerFactory2.GetHandler(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath)
at System.Web.HttpApplication.MapHttpHandler(HttpContext context, String requestType, VirtualPath path, String pathTranslated, Boolean useAppConfig)
at System.Web.HttpApplication.MapHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Here is the duplicated folder:
/SearchAndOrder/SearchAndOrder/ConfirmBasket.aspx
The path should be:
/SearchAndOrder/ConfirmBasket.aspx

The file '/test.aspx' does not exist. CheckVirtualFileExists exception

When hosting a website in an Azure web app, I get the this error when trying to access a non existing aspx file.
I'm expecting to get a 404 response, but instead I get a 500 exception.
I request an other file type I get the expected 404 response.
When I run the same site on an IIS I get the expected 404 for the aspx file
Failed Request Trace: Link to Failed Request Trace
Stacktrace
System.Web.HttpException (0x80004005): The file '/test.aspx' does not exist. at System.Web.UI.Util.CheckVirtualFileExists(VirtualPath virtualPath
at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate
at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate
at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound
at System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp
at System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath
at System.Web.HttpApplication.MaterializeHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute(
at System.Web.HttpApplication.<>c__DisplayClass285_0.<ExecuteStepImpl>b__0(
at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
I'm expecting to get a 404 response, but instead I get a 500 exception.
The ASP.NET pipeline tries to find the handler for the request that ends with /test.aspx, which is actually the page itself, unless you've routed the request to some other URL.
If it can't find this handler, you get the error. It's not a 404 because the request didn't even get handled. So the actual status code returned is 500.

ASP.NET sub Application compilation error

My application deploy as Sup-App in a big site, sometimes it got compilation error like this:
Exception information:
Exception type: HttpCompileException
Exception message: (0): error CS1704: An assembly with the same simple name 'App_GlobalResources, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null has already been imported. Try removing one of the references or sign them to enable side-by-side.
at System.Web.Compilation.AssemblyBuilder.Compile()
at System.Threading.Tasks.Parallel.<>c__DisplayClass32`2.<PartitionerForEachWorker>b__30()
at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
at System.Threading.Tasks.Task.<>c__DisplayClass11.<ExecuteSelfReplicating>b__10(Object param0)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Web.Compilation.BuildProvidersCompiler.PerformBuild()
at System.Web.Compilation.CodeDirectoryCompiler.GetCodeDirectoryAssembly(VirtualPath virtualDir, CodeDirectoryType dirType, String assemblyName, StringSet excludedSubdirectories, Boolean isDirectoryAllowed)
at System.Web.Compilation.BuildManager.CompileCodeDirectory(VirtualPath virtualDir, CodeDirectoryType dirType, String assemblyName, StringSet excludedSubdirectories)
at System.Web.Compilation.BuildManager.EnsureFirstTimeDirectoryInit(VirtualPath virtualDir)
at System.Web.Compilation.BuildManager.GetBuildResultFromCacheInternal(String cacheKey, Boolean keyFromVPP, VirtualPath virtualPath, Int64 hashCode, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResultFromCacheInternal(VirtualPath virtualPath, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound)
at System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp)
at System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath)
at System.Web.HttpApplication.MaterializeHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
May you please give me some guidance? what kind of this error and how to workaround it?
Try to delete the bin folder on the target server before publishing and check...
The only problem I could see is if the local bin directory contains newer versions of existing components.

EditorFor() throws NullReferenceException [duplicate]

I have a weird problem with EditorFor in one of my views. The following code throws an ArgumentNullException.
<%: Html.EditorFor(x => x.Name) %>
However, the following code is fine.
<%: Html.TextBoxFor(x => x.Name) %>
Model.Name is a string variable - and it's set.
EditorFor works in another view - until this view crashes, at which point then I have to restart the development web server (Cassini) or all the EditorFor calls crash with the same message.
I ran a test with the MVC 2 source, hoping I could get some insight, but that worked OK! Presumably the MVC 2 RTM source on there should be the one in VS2010 (dates seem to tie in).
I've just switched to TextBoxFor, as that's fine - but I'd like to know what the issue is. I'm running under .NET 4, VS2010 and Win7 x64.
[Update: same issue occurs with DisplayFor.]
Partial stack trace is:
[ArgumentNullException: Value cannot be null.
Parameter name: stream]
System.IO.StreamReader..ctor(Stream stream, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize) +9496369
System.Web.UI.TemplateParser.ParseFile(String physicalPath, VirtualPath virtualPath) +232
System.Web.UI.TemplateParser.ParseInternal() +86
System.Web.UI.TemplateParser.Parse() +160
System.Web.Compilation.BaseTemplateBuildProvider.get_CodeCompilerType() +110
System.Web.Compilation.BuildProvider.GetCompilerTypeFromBuildProvider(BuildProvider buildProvider) +65
System.Web.Compilation.BuildProvidersCompiler.ProcessBuildProviders() +218
System.Web.Compilation.BuildProvidersCompiler.PerformBuild() +40
System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath) +8945798
System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) +320
System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) +111
System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound) +125
System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp) +52
System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(String virtualPath, Type requiredBaseType) +28
System.Web.Mvc.BuildManagerWrapper.System.Web.Mvc.IBuildManager.CreateInstanceFromVirtualPath(String virtualPath, Type requiredBaseType) +36
System.Web.Mvc.WebFormView.Render(ViewContext viewContext, TextWriter writer) +172
System.Web.Mvc.Html.TemplateHelpers.ExecuteTemplate(HtmlHelper html, ViewDataDictionary viewData, String templateName, DataBoundControlMode mode, GetViewNamesDelegate getViewNames) +1154
System.Web.Mvc.Html.TemplateHelpers.TemplateHelper(HtmlHelper html, ModelMetadata metadata, String htmlFieldName, String templateName, DataBoundControlMode mode, Object additionalViewData, ExecuteTemplateDelegate executeTemplate) +1626
System.Web.Mvc.Html.TemplateHelpers.TemplateHelper(HtmlHelper html, ModelMetadata metadata, String htmlFieldName, String templateName, DataBoundControlMode mode, Object additionalViewData) +86
System.Web.Mvc.Html.TemplateHelpers.TemplateFor(HtmlHelper`1 html, Expression`1 expression, String templateName, String htmlFieldName, DataBoundControlMode mode, Object additionalViewData, TemplateHelperDelegate templateHelper) +210
System.Web.Mvc.Html.TemplateHelpers.TemplateFor(HtmlHelper`1 html, Expression`1 expression, String templateName, String htmlFieldName, DataBoundControlMode mode, Object additionalViewData) +129
System.Web.Mvc.Html.EditorExtensions.EditorFor(HtmlHelper`1 html, Expression`1 expression) +87
What does the Editor template look like for the property you are passing? (I assume x.Name is a string, so you should have a template called String.ascx in Views/Shared/EditorTemplates).
It likely the editor template that is getting loaded for string does not like a null string being passed.
If you don't have a custom editor template for string (and all you want is a basic textbox), then there is no reason to use EditorFor.

FSharp site on shared server, which dll's do I need to include in the bin folder?

Which dll's do I need to include in the bin folder?
or do I need to install F# on the server it self ?
N.B:
Resolved
All the FSharp dlls are now in the site Bin
The site is deployed using the Publish option from Visual Studio
The allow precompiled site to be updatable has to be unchecked
Error from my site:
The system cannot find the file specified
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ComponentModel.Win32Exception: The system cannot find the file specified
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[Win32Exception (0x80004005): The system cannot find the file specified]
System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo) +2097
System.Diagnostics.Process.Start() +140
Microsoft.FSharp.Compiler.CodeDom.Internal.Compiler.compileFiles(String args, CompilerResults res) +120
Microsoft.FSharp.Compiler.CodeDom.Internal.Compiler.compileAssemblyFromFileBatch(CompilerParameters options, String[] fileNames, CompilerResults results, FastFunc`2 sortf) +278
System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromFile(CompilerParameters options, String[] fileNames) +23
System.Web.Compilation.AssemblyBuilder.Compile() +843
System.Web.Compilation.BuildProvidersCompiler.PerformBuild() +164
System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath) +267
System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile) +582
System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile) +93
System.Web.UI.BaseTemplateParser.GetReferencedType(VirtualPath virtualPath, Boolean allowNoCompile) +325
System.Web.UI.PageParser.EnsureMasterPageFileFromConfigApplied() +89
System.Web.UI.PageParser.HandlePostParse() +16
System.Web.UI.TemplateParser.Parse() +155
System.Web.Compilation.BaseTemplateBuildProvider.get_CodeCompilerType() +105
System.Web.Compilation.BuildProvider.GetCompilerTypeFromBuildProvider(BuildProvider buildProvider) +54
System.Web.Compilation.BuildProvidersCompiler.ProcessBuildProviders() +182
System.Web.Compilation.BuildProvidersCompiler.PerformBuild() +29
System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath) +267
System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile) +582
System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile) +93
System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean noAssert) +111
System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp, Boolean noAssert) +54
System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath) +31
System.Web.UI.PageHandlerFactory.System.Web.IHttpHandlerFactory2.GetHandler(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath) +40
System.Web.HttpApplication.MapHttpHandler(HttpContext context, String requestType, VirtualPath path, String pathTranslated, Boolean useAppConfig) +139
System.Web.MapHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +128
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +161
Version Information: Microsoft .NET Framework Version:2.0.50727.1433; ASP.NET Version:2.0.50727.1433
If you 'pre-compile' the web site using the aspnet_compiler.exe tool (or using the Publish button in Visual Studio) without compiling it as "updatable" (meaning that all ASPX and FS files have to be compiled into DLLs) then I think you'll need just:
FSharp.Core.dll (contains the core F# libraries, lists, tuples, etc.)
possibly FSharp.PowerPack.dll (as Robert mentioned)
Other DLLs from the F# installation shouldn't be needed for the runtime. If you want to compile the Web application on the server (using the F# CodeDOM) (i.e. deploy it as an updatable web site), then you'll need to install F# on the server and you'll need the rights to spawn "fsc.exe" (so that doesn't look like a case for shared server).
Installing F# on the server will definitely cure your problems, but isn't strictly necessary. You will have definitely picked up a dependency on FSharp.core.dll, you may also have picked up a dependency on FSharp.PowerPack.dll if you have referenced it from your project, and well any other FSharp.*.dlls that you may have referenced. You can generally use reflector to find which dlls your application depends on.
I was able to fix the issue by unchecking the allow this precompiled site to be updatable and by having all the dlls in the directory.
Thanks for the suggestions.

Resources