views:

171

answers:

2

In my ASP.NET MVC application, I have the following setup:

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <probing privatePath="bin;extras"/>

I have referenced assemblies located in the extras folder in the views and they have worked perfectly (using <%@ Import Namespace="myNameSpace" %>).

My questions

  1. What happens when that line is called?
  2. Where is the assembly loaded?
  3. Why is it that I can't overwrite the assembly located in the extras folder that contains myNameSpace with a newer version? (I get an error saying that the assembly is "open" in another program)
  4. Is there a way to overwrite the assembly with a newer version without having the application restart?
A: 
  1. I think this is the same as a using statement in C#, it basically means that the namespace's classes are now available to be used in yoru page.
  2. The assembly will be loaded into memory probably by the aspnetwp.exe process
  3. If the assembly is currently being used you will get this error message
  4. A restart is the safest way I know of doing this, you could use dependency injection or late binding to achieve the same result. I would jsut wonder why you would want to switch an assembly while the application is running?
Burt
#4: Replace it with an updated version. Is this possible while its running?
Baddie
IF you use dependency injection and program against an interface you could do it easily.
Burt
Could you elaborate?!
Baddie
+3  A: 

1) Import doesn't actually do anything at runtime. It's a compile-time convenience that just lets you refer to types using their unqualified names such as Environment instead of System.Environment.

2) The assembly is loaded using normal assembly probing rules. The CLR checks various locations before these private probing paths so it's important to keep that in mind. If you reference a strong-named assembly and expect to find that assembly in a private probing path, an assembly with the same strong name (name, version, public key, etc) in the GAC would be preferred. This can sometimes lead to unexpected behavior and is usually caused by hard coding an assembly version in your AssemblyInfo.cs and forgetting to update it.

3) Once loaded, an assembly cannot be unloaded without unloading the AppDomain. But ASP.NET uses "shadow copying" which means assemblies are copied to a temporary path before being loaded. This should leave the original assembly unlocked and able to be overwritten. Off the top of my head, I am not sure why you'd be getting the error about locked assemblies. In a normal Windows application, this would be totally normal and expected. But ASP.NET is designed so that you can overwrite content, code, assemblies, etc while the application is running, which leads to #4.

4) In practice, no. Because an assembly cannot be unloaded, there is no way to upgrade an assembly without the web application being restarted. Technically speaking, you can load multiple versions of an assembly but this would not give you the desired results. Any compile-time references would still reference the old assembly and you'd get all kinds of invalid cast exceptions if you tried to use the new assembly. But as I said in #3, with ASP.NET upgrading assemblies is supposed to be as simple as replacing the files and should happen automatically. You shouldn't have to restart IIS or worker processes manually.

The following links may be of interest.

How the Runtime Locates Assemblies
Best Practices for Loading Assemblies
Shadow Copying Assemblies
Unloading Assemblies - Suzanne Cook

UPDATE After reading a bit more on shadow copying, I think the reason you might be seeing the issue of locked assemblies in the extras folder is that ASP.NET probably only specifies the "bin" folder for shadow copying.

Josh Einstein