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

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.

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.

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.

SOLVED!
I had similar problem, caused from LoadControl() strange behaviour.. and solved not instantiating my control before.
strange but true..
MyUserControl myuc = new MyUserControl();
myuo = (MyUserControl)Page.LoadControl("~/UserControls/MyUserCOntrol.ascx");
doesnt work
MyUserControl myuc = (MyUserControl)Page.LoadControl("~/UserControls/MyUserCOntrol.ascx");
works

I belive we found a solution to this problem. We always tried fixing this by deleting the whole "Temporary ASP.NET Files" folder.
At some point this solution would no longer be good enough and the error kept popping up every 30 minutes or so. We found that deleting just the file responsible and then restarting the application pool of the application in question is a permenant fix (at least for us). So for you case you would delete the follwing file (bold) and then restart the applications application pool:
[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'.
This permenantly fixed the problem for us.
EDIT:
Found a permenant solution, at least for us.
In web.config look for tag and add batch="false" to it. So it would look something like:
compilation debug="false" targetFramework="4.7.2" batch="false"
The error never repeated after this.

Related

Is it necessary to recycle app pool in order to refresh cached query plans?

I'm not sure if I'm asking the right question exactly, but if you know the answer then you'll probably understand what I'm asking.
I updated a stored proc and tested in dev w/ no problem. So then I updated the proc in production and it caused errors. Took me a bit to figure out what was going on because all I changed was a field in the select list from i.Price to Price = coalesce(r.Price, i.Price). Eventually I figured the only difference could be that r.Price is a decimal value whereas i.Price is a money value so the return type of the field had changed.
Normally that shouldn't matter for c# code. the DataReader value gets cast to decimal either way just fine. But all I had to do to fix the error was reset the app pool and then it worked. I believe I could have also updated my query to cast to a money type and that probably would have worked as well.
I know I've run into this kind of issue a few times before, enough to know there's some kind of caching going on under the hood in asp.net and/or the sql assemblies.
My question is, how can I get this cache to refresh without recycling the app pool. Or is that the only way?
Here what exactly happens when you deploy :
ASP.NET has a feature called shadow copying that enables assemblies that are used in an application domain to be updated without unloading the AppDomain. Normally, this is required because the Common Language Runtime (CLR) will lock the assemblies so you can’t just copy a new assembly over it. Shadow copying means that the original assembly is copied to a temporary location. The copied assembly is locked, and the original assembly can be updated with a new version.
What is assembly interning?
From :
From MSDN:
The ASP.NET shadow copy feature enables assemblies that are used in an application domain to be updated without unloading that AppDomain (necessary because the CLR locks assemblies that are being used). This is done by copying application assemblies to a separate location (either a default CLR-determined location or a user-specified one) and loading the assemblies from that location. This allows the original assembly to be updated while the shadow copy is locked. ASP.NET turns on this feature by default for Bin folder assemblies so that DLLs can continue to be updated while a site is up and running.
https://msdn.microsoft.com/en-us/magazine/hh882452.aspx
App Pool will be recycled automatically when below happens:
Any modifications in the Application’s BIN Directory
Making changes in any Configuration File/s, like Web.config or others ( if you have any specific config file in your application say in a directory called App_Config).
Making modifications in the Source code files in APP_CODE Directory. This maybe change in any Source code files, or adding or deleting files from this directory.
Making changes in the Global.asax file
Making Changes in the Machine.config file.
Making any modifications in the Web Application’s Root Directory. This means creating files/subdirectories on the fly can lead to application pool recycling.
Modifications for references of Web Services of App_WebReferences directory.
Modifying the Security Settings of any directory in the Root directory. (Like specifying read security rights for everyone or any other specific user or user group.)
For more details :
Does any change in any file inside bin folder cause application recycle in ASP.NET web application?

Glimpse MVC3 DLL being 'forgotten' as part of Application Pool recycle

We're trying to get Glimpse up and running in our environment but coming across a strange problem.
We've installed Glimpse.Core, Glimpse.AspNet, and Glimpse.Mvc3.dll and when we configure web.config to enable Glimpse everything works fine until the Application Pool recycles. Once the AppPool recycles, it's as if the site 'forgets' about Glimpse.Mvc3.dll and the Mvc3 tabs (Execution, Model, Metadata) disappear.
Here are the steps (for us) to reproduce:
Modify web.config to include Glimpse configuration
All tabs will show including Execution, Metadata, and Model Binding
Perform an Application Pool recycle
The MVC3 Glimpse tabs will no longer show (but the others will)
Prior to the AppPool recycle, Glimpse.axd shows the following Registered Tabs:
Glimpse.AspNet (1.3.1)
Configuration - Glimpse.AspNet.Tab.Configuration
Environment - Glimpse.AspNet.Tab.Environment
Request - Glimpse.AspNet.Tab.Request
Routes - Glimpse.AspNet.Tab.Routes
Server - Glimpse.AspNet.Tab.Server
Session - Glimpse.AspNet.Tab.Session
Glimpse (1.5.0)
Timeline - Glimpse.Core.Tab.Timeline
Trace - Glimpse.Core.Tab.Trace
Glimpse.Mvc3 (1.3.2)
Execution - Glimpse.Mvc.Tab.Execution
Metadata - Glimpse.Mvc.Tab.Metadata
Model Binding - Glimpse.Mvc.Tab.ModelBinding
Views - Glimpse.Mvc.Tab.Views
And post AppPool recycle, Glimpse.axd shows the following Registered Tabs:
Glimpse.AspNet (1.3.1)
Configuration - Glimpse.AspNet.Tab.Configuration
Environment - Glimpse.AspNet.Tab.Environment
Request - Glimpse.AspNet.Tab.Request
Routes - Glimpse.AspNet.Tab.Routes
Server - Glimpse.AspNet.Tab.Server
Session - Glimpse.AspNet.Tab.Session
Glimpse (1.5.0)
Timeline - Glimpse.Core.Tab.Timeline
Trace - Glimpse.Core.Tab.Trace
It's as if the site is 'forgetting' about Glimpse.Mvc3.dll as part of the AppPool recycle.
Any ideas/suggestions greatly appreciated.
The reason seems to be ASP.Net and the way it loads assemblies from your application directory for the first time and after a recycle. On first start, the assemblies are loaded from your application's bin directory and after a recycle (or even an IIS restart) it loads the assemblies from the Temporary ASP.NET Files directory. And depending on the situation more or less assemblies are loaded.
You can see this for yourself by adding the following lines to your Application_Start method in your Global.asax
protected void Application_Start()
{
Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
bool glimpseMvc3AssemblyLoaded = loadedAssemblies.Any(a => a.FullName.Contains("Glimpse.Mvc3"));
File.AppendAllText(
"C:\\temp\\output.txt",
string.Format(
"{0}{1} assemblies loaded and Glimpse.Mvc3 is{2} one of them",
Environment.NewLine,
loadedAssemblies.Length,
glimpseMvc3AssemblyLoaded ? string.Empty : " not"));
}
If you run that then you will see the following entries in your output.txt file (although numbers may differ)
On first initial start:
60 assemblies loaded and Glimpse.Mvc3 is one of them
After recycles
30 assemblies loaded and Glimpse.Mvc3 is not one of them
30 assemblies loaded and Glimpse.Mvc3 is not one of them
After removing the corresponding directory inside the Temporary ASP.NET Files directory
70 assemblies loaded and Glimpse.Mvc3 is one of them
How does this correlate with Glimpse. Well Glimpse makes a call to AppDomain.Current.GetAssemblies() after which it will look for types that implement ITab, but if the Glimpse.Mvc3 assembly isn't returned then tabs defined inside of it won't be discovered and hence not shown.
Does this solve your issue? I'm afraid not, but I think it is better to continue this discussion on the glimpse issue tracker, as a matter of fact I already found a similar issue over there, but I'm not sure if it is yours.
Update
There will be a fix in one of the upcoming releases of Glimpse, but in the meanwhile there is a solution/workaround, as mentioned in one of the comments on the Glimpse issue.
Simply add the following statement to the Global.asax Application_Start method
BuildManager.GetReferencedAssemblies()
and you're good to go

Could not load file or assembly when trying to remove/delete Resource/Application

I have a Biztalk application that is basically a housing for a schema that other applications are using. I now want to remove this application, but am unable to from the BizTalk Server Admin Console, when I right-click --> Remove I get an error that says
Could not load file or assembly <assembly_name>.dll or one of its dependencies. The system cannot find the path specified (mscorlib)
followed by:
The system cannot find the path specified (Exception from HRESULT: 0x80070003)
So I go to remove the assembly from the Application and get the exact same error. I remove all references to it in other biztalk resources and still the same error when trying to delete the application or resource. I did notice that in the Modify Resouces dialog of referencing assemblies, this rogue assembly is listed as a dependency status of Not Found.
The strange thing is, when Messages come through, the resources which depend on the rogue assembly, still work fine and no errors are thrown (despite them using components of the assembly which shows as Not Found).
I have made sure to check the GAC and the assembly is loaded to it.
So now I have to ask:
where is Biztalk actually looking for this assembly?
is there a way I can just force a deletion of this application?
why does it care if the assembly is not found, when I'm trying to delete it?
why does it show as Not Found, yet still work?
Thanks.
I think the key is "or one of its dependencies." If it's a dependency it may be using the standard windows mechanism for finding a dll. It searches the current directory and the windows directory for them.
"where is Biztalk actually looking for this assembly?"
Look in the 'resources' section of your application in the biztalk management console. It shows a column with the location of the assembly.
I'd stop all the host instances/orchestrations, and then unload all your stuff from the GAC - if messages are actually still going through then stuff is still loaded that is using your schema.

Assembly unavailable after Web.config change

I'm using a custom framework that uses reflection to do a GetTypeByName(string fullName) on the fully-qualified type name that it gets from the database, to create an instance of said type and add it to the page, resulting in a standard modular kind of thing.
GetTypeByName is a utility function of mine that simply iterates through Thread.GetDomain().GetAssemblies(), then performs an assembly.GetType(fullName) to find the relevant type. Obviously this result gets cached for future reference and speed.
However, I'm experiencing some issues whereby if the web.config gets updated (and, in some scarier instances if the application pool gets recycled) then it will lose all knowledge of certain assemblies, resulting in the inability to render an instance of the module type. Debugging shows that the missing assembly literally does not exist in the current thread assemblies list.
To get around this I added a second check which is a bit dirty but recurses through the /bin/ directory's DLLs and checks that each one exists in the assemblies list. If it doesn't, it loads it using Assembly.Load and fixing the context issue thanks to 'Solving the Assembly Load Context Problem'.
This would work, only it seems that (and I'm aware this shouldn't be possible) some projects still have access to the missing assembly, for example my actual web project rather than the framework itself - and it then complains that duplicate references have been added!
Has anyone ever heard of anything like this, or have any ideas why an assembly would simply drop out of existence on a config change? Short of a solution, what is the most elegant workaround to get all the assemblies in the bin to reload? It needs to be all in one "hit" so that the site visitors don't see any difference other than a small delay, so an app_offline.htm file is out of the question. Programatically renaming a DLL in the bin and then naming it back does work, but requires "modify" permissions for the IIS user account, which is insane.
Thanks for any pointers the community can gather!
Generally, you should avoid relying on what assemblies are currently loaded in an appdomain, as that happens dynamically. Instead, simply call System.Web.Compilation.BuildManager.GetType() instead of Type.GetType() or Assembly.GetType(). This should just do the right thing for you, and not be affected by appdomain cycles.
As you obviously know, there are many situations where the current appdomain is unloaded and reloaded. After each reload, all assemblies are unloaded and the whole application starts running "from scratch".
Assemblies are by default loaded on demand. Usually that is the case when the JIT stumbles across some reference. In consequence, a appdomain reload will clear out the assemblies in the appdomain and they will only appear again later on when the JIT loads them.
As solution I'd rever to using the static Type.GetType() method and supply an assembly qualified name (e.g. a type name with the assembly name included). That's the same thing the framework uses when loading types specified in the config file, and it will make sure that the required assembly is searched and loaded on demand without using any tricks. See the remarks section of the method above (the method name above name is a link).
This will require updates to your database to hold assembly qualified names instead of "only" fully qualified type names. However, it also makes sure that you don't run into name collisions when two assemblies provide different type with the same name, so this is a good idea anyways I think.
I've never heard of this problem before.
I'm not sure if this will work, as I only recently read about it while researching workarounds to ODAC dependencies, but specifying the probing path for assemblies may fix your issue.
see: http://msdn.microsoft.com/en-us/library/823z9h8w(VS.80).aspx
sample:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;bin2\subbin;bin3"/>
</assemblyBinding>
</runtime>
</configuration>
I have a similar problem, when I update 2-5 files, ether web.config, ether other files, and asp.net needs to recreate the running files, then some times did not find some classes/function that exist on dll files, and my system is not working - throw errors like yours.
My solution to that is that I place the app_offline.htm on the root, make my updates, then rename/remove the app_offline.htm and my system works fine.
I am sure that have something to do with the cached compiled files, but I did not have deaply search whats exactly cause that.
[what is the most elegant workaround to get all the assemblies in the bin to reload]
Now what is the most elegant workaround on this is to call the HttpRuntime.UnloadAppDomain and actually make your application to stop and starts again.
http://msdn.microsoft.com/en-us/library/system.web.httpruntime.unloadappdomain(VS.80).aspx
I do not know if this solve your issue, you need to make tests.
probably on Global.asax make something like that
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError().GetBaseException();
...if ex is your error, and you get more than 2 ...
{
HttpRuntime.UnloadAppDomain();
}
}
I would try to create some basic class from which assembly, which is interesting for you without reflection on Application Start to make sure it is loaded.
E.g.
var temp = new BaseModuleBuilder();
This do not look smart, but it is very straitforward and asp.net should do everything for you. In case when your list is too dynamic, it could be something like
var temp = Activator.CreateInstance(Type.GetType("BaseModuleBuilder, Modules.dll"));
Make sure to always specify DLL when working with dynacmically loaded classes.

Unable to retrieve session value

On page load I am populating my own list object, storing in session & it is getting stored, When I am debugging i can see that list object is stored in session, But When I am reading that session variable in next page, it's throwing error like
The type 'Dispensary.ResourceScheduling.Views.SchedulingPopup' exists in both 'WebApplication.dll' and 'App_Web_6bndsqgu.dll'
So Can u please help me how to resolve this issue.
Thanks in advance.
Do a full rebuild on your project.
If that still doesn't work, delete everything in the C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\[mywebsite] folder, where [mywebsite] is the name of your project. If the DLLs are locked you will have to stop and restart the website in IIS.
Occasionally I've noticed that Visual Studio gets confused and leaves behind the temporary DLLs. This doubles up your classes but is has nothing to do with session values.
You have corrupted .NET temporary files. Before the full rebuild or anything else, do a "Clean Solution". This reliably cleans up .NET temporary files, plus any other accumulated sludge.
Corrupted .NET temporary files can occur from a number of situations, most notably editing binding expressions mixed into markup in .aspx pages. The key to identifying .NET temporary file problems is an obfuscated file name, such as "App_Web_6bndsqgu.dll". Problems can include duplicate .dlls (as noted), inability to find or load some pages and services dynamically (ASP.NET-hosted WCF services are vulnerable to this), and more. So "clean solution" is the first thing to reach for when any of these happen.
When working with source control, it's my basic practice now to do "get latest", "clean solution", and "rebuild solution" before any further work.

Resources