Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cannot be cast to [B]; Same context (Default); Different Temp File

I'm having difficulty finding why exactly the following error is happening. I'll outline the puzzling aspects below the error description.

[A]ASP.common_resultmessagepanel_ascx cannot be cast to
[B]ASP.common_resultmessagepanel_ascx.

Type A originates from 'App_Web_resultmessagepanel.ascx.38131f0b.2c4hpv_z, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
in the context 'Default' at location
'C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\MyWebApp\dc3e0df6\ba1606c8\App_Web_resultmessagepanel.ascx.38131f0b.2c4hpv_z.dll'.

Type B originates from 'App_Web_wz3shqfq, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
in the context 'Default' at location
'C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\MyWebApp\dc3e0df6\ba1606c8\App_Web_wz3shqfq.dll'.

The class referenced in the error is a web user control inheriting from System.Web.UI.UserControl and implementing System.Web.UI.ITextControl.
The control is registered and used on a master page. None of the parent master pages or implementing pages have instances of the control.
The class and the markup page are both in the web application project.
The exception does not happen as a direct result of the application code, it happens during internal .NET Framework code execution.
The project is a web application, not a web site.
The web application is compiled into a single binary, with culture specific resources compiled into one binary per culture.

The context reported for each type in the exception is the same, but I was able to verify that when the exception occurs there are in fact 2 separate class definitions in the Temporary ASP.NET Files folder for the application.

The user control has always existed and was used in the application, but the exception first started happening after the user control was added to a master page.

The exception does not happen consistently. Once the temporary files get created, the exception will happen every time the page is requested. If anything causes the temporary files to be cleared or recreated, it is random as to whether the duplicate temporary class definitions/DLLs will be created again. This could be a web.config change, recycling the app pool, sometimes even just an updated/rebuilt web application binary.

The last bit of the stack trace:

   ASP.Default.__BuildControl__control35(Control ctrl) in C:\Projects\ABC.Web\App_Themes\Default\CheckBox.skin:3
   System.Web.UI.ControlSkin.ApplySkin(Control control) +12
   System.Web.UI.PageTheme.ApplyControlSkin(Control control) +119
   System.Web.UI.Control.ApplyStyleSheetSkin(Page page) +61
   ASP.masterpages_mymaster_master.__BuildControlpnlResults() in C:\Projects\ABC.Web\MasterPages\MyMaster.master:10
   ASP.masterpages_mymaster_master.__BuildControl__control2(Control __ctrl) in C:\Projects\ABC.Web\MasterPages\MyMaster.master:9
   System.Web.UI.CompiledTemplateBuilder.InstantiateIn(Control container) +12
   System.Web.UI.MasterPage.InstantiateInContentPlaceHolder(Control contentPlaceHolder, ITemplate template) +87

The supposed offending source (the only line in the skin file C:\Projects\ABC.Web\App_Themes\Default\CheckBox.skin):

<asp:CheckBox runat="server" SkinID="FormInput" CssClass="FormLabel FormInputCheckBox" />

At this point I don't know if this issue is caused by the solution, its configuration, IIS and the app pool, or something related to the actual temp file directory itself where maybe old files are not getting cleared out. I've verified that the temp folder is not being indexed by the OS.

I'm worried that in a production environment, the app pool will recycle or some configuration setting will change and cause those temp files to be recreated with the duplicate class definition, and thus the error. We can't have someone testing the application every time the app pool recycles and deleting temp files if the error occurs until the application loads correctly. So I need to find out what is causing the duplication, but at this point I don't really know where else to investigate.

Any ideas?


I've removed the user control from the master page, and put it directly into each of the pages that required it and were implementing the master page.

So far the exception hasn't happened again. I'm going to give it another couple days of test time to see if it crops up again.

I still want to know why the exception was happening at all. Anyone with in-depth knowledge of how IIS runs .net web apps, or how the temp files are created?


New theory!

While it is a web project with a compiled binary, the IIS instance I am running for development is pointed to the project folder. So the source code files are actually in the web path. I think IIS might be compiling the source code files into separate binaries, especially if the app pool recycles. Thus accounting for the duplicated temp files that are being created and the error.

Other developers were experiencing the errors while running the project from within visual studio. I don't know how this would account for those cases, but I wouldn't rule it out as being the cause either.

like image 861
ulty4life Avatar asked Jul 23 '11 02:07

ulty4life


2 Answers

I'm not sure what's happening in your case, but I had this happen to me under the following circumstances:

Website project type, not Web Application.

/Controls folder containing many ascx usercontrols.

/Client/Controls folder containing other ascx usercontrols, some of which register and reference /Controls usercontrols.

/Controls/BadControl.ascx using /Client/Controls/DupedControl.ascx as a child control.

The compiler runs into a circular dependency as it tries to compile each folder into a separate assembly.

/Controls/BadControl.ascx needs /Client/Controls to be compiled first.

/Client/Controls needs /Controls to be compiled first.

So the compiler punts and compiles DupedControl.ascx into its own separate assembly first. Then /Controls, then /Client/Controls in which DupedControl still gets included.

At this point there are two distinct Types for DupedControl in two separate assemblies. DupedControl.ascx (markup) points to the correct Type -- let's call it TypeA, in the folder's assembly -- while BadControl's reference points to the dupe TypeB in the small extra assembly.

When a page using BadControl executes, DupedControl TypeA gets instantiated via the markup, but BadControl tries to cram it into a TypeB variable, resulting in the error you described.

The solution is to move ascx files around to get rid of the circular reference. I can't remember for certain, but I think maybe the "single page assemblies" and "fixed naming" options might also resolve it.

All that said, Web Application projects compile to a single assembly, so I didn't think this kind of circular folder reference would be possible. Perhaps the problem lies elsewhere.

like image 102
wonkim00 Avatar answered Sep 30 '22 12:09

wonkim00


After a year and a half of seeing this error intermittently pop up for developers in our team, I've finally been able to gather enough data to draw some conclusions.

The key elements in the scenario causing the error are source code files in the web path, and low available memory on the dev machine that is running the application. The low memory condition causes the application pool to recycle or release memory more frequently than it would in a dedicated web hosting environment. When the memory containing the compiled web app code is released, and then a page is requested, the compiled code is reloaded into app pool memory. Since source code files are in the web path, .NET recompiles from the source code files and reloads into memory.

This situation does not happen in a dedicated hosting environment where only the compiled DLL and static files are deployed, and has never happened in our production environment. Additionally memory usage in a dedicated environment should ideally never reach a point where frequent app pool recycling is necessary.

The Visual Studio solution consists of several projects, and developers typically have multiple VS instances, a SQL Server Mgmt instance, and other sundry processes running which cause low available memory on dev machines. The lower the available memory, the more frequently and reliably the error will happen.

To clear the error state, an application pool flush / iisreset will clear out memory, and then a rebuild will usually fix the problem. If available memory is still low, the problem may persist until more memory is available in which to run the application. Simply closing down some applications or otherwise releasing memory back to the OS should do the trick.

I'm still not sure why running the app through Visual Studio's web server instead of IIS has same issue, but if it handles memory the same way IIS does, it stands to reason that the behavior is the same.

like image 20
ulty4life Avatar answered Sep 30 '22 12:09

ulty4life