Geeks With Blogs
Rupreet's Weblog Looking deep inside under the hood

Setting the context…

We have a web application which communicates with WCF based service façade for any business functionality. This service façade then loads assembly (based on configuration) at the runtime for making the system pluggable. By default the implementation is in the service assembly itself. Below is the sample code for loading the assembly and creating an instance of the desired class.

 

Assembly asm = Assembly.LoadFrom(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, assemblyName));

if (asm != null)

{

     Type type = asm.GetType(typeName));

     if (type != null)

     {

         return Activator.CreateInstance(type);

      }

}

 

Testing this code from a console application works like a charm but when the service façade is integrated with the web application, we get the below error:

[A]<Type> cannot be cast to [B]<Type>. Type A originates from <assembly> in the context 'Default' at location 'C:\Windows\Microsoft.NET\Framework\v4.0.21006\Temporary ASP.NET Files\root\10e649fb\634e3b21\assembly\dl3\9f96095e\325f141a_f8aaca01\<assemblydllName>. Type B originates from <assembly> in the context 'LoadNeither' at location 'D:\<myproject>\ \bin\<assemblydllName>.

 

Debugging the issue…

In the initial debugging, everything seemed correct and on inspecting the “type” of the object, it seems correct but the cast failed. When nothing helped, I revered back to the debugging basics – read the error message clearly.

The error message said - Type A originates from <assembly> in the context 'Default' at location 'C:\Windows\Microsoft.NET\Framework\v4.0.21006\Temporary ASP.NET Files\root\10e649fb\634e3b21\assembly\dl3\9f96095e\325f141a_f8aaca01\abc.dll Type B originates from <assembly> in the context 'LoadNeither' at location 'D:\work\Projects\<Project>\bin\ abc.dll.

Now – from the message we can see the abc.dll (name changed) is getting loaded twice in the application domain and from two different locations. To verify this, I debugged the application again and saw the output window which shows the assembly getting loaded again from a different location. Below is the content of the output window:

 

'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.DynamicData\v4.0_4.0.0.0__31bf3856ad364e35\System.Web.DynamicData.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.

 

'WebDev.WebServer40.EXE' (Managed (v4.0.21006)): Loaded

 

'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.CSharp\v4.0_4.0.0.0__b03f5f7f11d50a3a\Microsoft.CSharp.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.

 

'WebDev.WebServer40.EXE' (Managed (v4.0.21006)): Loaded

 

'D:\work\Projects\<Project>\bin\ abc.DLL', Symbols loaded.

 

'WebDev.WebServer40.EXE' (Managed (v4.0.21006)): Loaded

 

'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.WorkflowServices\v4.0_4.0.0.0__31bf3856ad364e35\System.WorkflowServices.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.

 

We have same assembly, loaded twice in the app domain from two different locations. When the managed environment tries to type cast the objects, it throws this error.

Conclusion:
To answer as to why the assembly loaded twice in the application domain – it is because the first assembly was loaded by the web application while calling the service façade and it was loaded from the web application temporary location. The assembly was loaded again by the code mentioned above is because we are using “LoadFrom” where we specify the path of the assembly from it needs to be loaded from and this by-passes the assembly probing mechanism. While loading this assembly, CLR thinks this assembly is a different assembly from the previously loaded assembly because the context of both the assemblies is different. Hence the type casting between these type from different assemblies fails.

How to fix?
To fix this issue, we should use Assembly.Load instead of Assembly.LoadFrom where CLR will probe the assembly and load it correctly, if not already loaded. Below code is the recommended code to load the assembly

Assembly asm = Assembly.Load(assemblyName); //assembly name is full assembly name

if (asm != null)

{

     Type type = asm.GetType(typeName));

     if (type != null)

     {

         return Activator.CreateInstance(type);

      }

}

 

 

Posted on Tuesday, February 16, 2010 12:49 AM | Back to top


Comments on this post: Avoid Assembly.LoadFrom; instead use Assembly.Load

# sorenha
Requesting Gravatar...
Thanks. I just tried that and it gives me the same "Strong name validation failed" although I point it to the correct assembly: var assemblyName = AssemblyName.GetAssemblyName(correctFileName); var assembly = Assembly.Load(assemblyName); I'm thinking this is because the correctFileName is outside the app CodeBase folder. I guess I'll just leave it and go a different route
Left by pro duo memory stick on Feb 17, 2010 12:22 AM

# re: Avoid Assembly.LoadFrom; instead use Assembly.Load
Requesting Gravatar...
Sorenha - can you please explain the problem a bit more. What exactly are you trying to do and what issue you facing? I can see if i can help you with it.
Left by Rupreet on Feb 17, 2010 9:57 PM

# re: Avoid Assembly.LoadFrom; instead use Assembly.Load
Requesting Gravatar...
This all makes sense up to one point. When the application starts it makes a copy of assemblies needed to the C:\Users\..\AppData\...\Project Assemblies\XXX\MyDll.dll. If there is a designer assembly in need of that dll, you get the same error message when trying to invoke the designer, if the MyDll.dll is also in the assembly root search path:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\AssemblyFolders

How to prevent the VS.IDE from making a copy of assemblies needed to its Project Assemblies\ folder? It does not happen for the framework assemblies for example, so there must be a way.

Left by Atmapuri on May 23, 2010 1:38 PM

# re: Avoid Assembly.LoadFrom; instead use Assembly.Load
Requesting Gravatar...
Thanks for this post. This worked for me. But using the "Assembly.Load(assemblyName)" method I've seen that at present this method is deprecated. Is there another alternative to use and avoid the above issue?
Left by Cristian on Oct 23, 2012 9:12 PM

Your comment:
 (will show your gravatar)


Copyright © Rupreet Singh Gujral | Powered by: GeeksWithBlogs.net | Join free