My Biggest Beef with VS.NET

My biggest beef with VS.NET deals with assembly references. Since I'm a component developer, these issues are near and dear to my heart. I've spent a lot of time thinking about this, and have decided to put it into three very clear scenarios to help people understand the problem. These use cases are extremely common, and the problems encountered are a royal PITA. See for yourself, and read on.


Introduction
OK, so far to add an outside assembly to your project, you have two options:

- Add Reference
       Adds a reference to a local assembly
- Add Web Reference
       Adds a reference to a web service

In practical application development, these options are great, but they're not enough. I will explain using three scenarios, and hopefully, though I will explain the solutions, they will be apparent as the scenarios are discussed.

Scenario 1:
"Rob" has a hosting account at "MyCoolHosting.com". Now, MCH.com has been kind enough to purchase .NET components and make them available to developers like Rob. However, for Rob to utilize them, Rob has to download a secret package and install the assemblies on his local machine. Rob is not happy.

Solution 1: "Add Reference From Remote GAC"
This does not require a whole lot of explanation. While connected to a IIS6 or FPSE site, allow the user to be able to browse the remote GAC. This would require an addition to GAC management on the server to allow the server administrator to manage visible GAC components just as they can Assembly Security (meaning that administrators can decide what assemblies are visible remotely and what are not). Bindings would apply the same way they would to a local GAC. Any components in the Remote GAC but not in the Local GAC would be downloaded to the "downloads" section of the Local GAC just like any other component.


Scenario 2:
"Paul" also has a hosting account at MCH.com. His web application uses two components:
- "CoolControl" from "CoolVendor" uses "ComponentLicensing" v1.1 from "LicensingVendor" to manage licensing. It's dependent assembly is named ComponentLicensing.dll. The assembly version is 1.1.5000.3.
- "AwesomeControl" From "AwesomeVendor" uses "ComponentLicensing" v2.0 from "LicensingVendor" to manage licensing. It's dependent assembly is named ComponentLicensing.dll. The assembly version is 2.0.5000.19.

When VS.NET adds CoolControl the first time, it will see a dependency on ComponentLicensing.dll (v1.1) and copy it to the "/bin" folder. When VS.NET adds AwesomeControl, it will see a dependency on ComponentLicensing.dll (v2.0) and copy it to the "/bin" folder, overwriting the ComponentLicensing.dll assembly that was already present for the first binding.

Every time you open a project, VS.NET copies the references back up to the "/bin" folder (if CopyLocal = True). Because the order VS.NET looks at these bindings in a project is unpredictable, each time you re-open the project, it is impossible to tell which version of the assembly will make it up there. Further, you cannot get version properties on files in the "/bin" folder, so unless the person has access to the remote file system through other means, there is no way to tell which version is actually in the folder.

Either way, one assembly binding will be broken. Either way, the developer will be required to add an extra step (in the form of a bindingRedirect or something) to keep the application from breaking every time it is opened in the IDE.

Chances are, Paul doesn't know about "satellite assemblies" or "assembly dependencies". He installed the component, and he expects it to work. When a binding fails, he gets a cryptic error message that he does not understand, and decides to call Tech Support. He spends hours on the phone, to which "CoolVendor" says "It's AwesomeVendor's fault." He calls AwesomeVendor and they return blame to CoolVendor.

There is currently no decent solution to this problem. Paul is pretty much screwed (and so are component vendors). Paul is not happy.

Solution 2: "Add Reference From AAC"
I've talked about this concept several times before, and it needs to be revisited with ASP.NET 2.0. This scenario is not made up. It is taken directly from an experience that I had with a licensing component.

The Framework should be able to host for Paul in his application, an "Application Assembly Cache" This is an application-specific GAC that can be configured by the server administrator, similarly to Solution 1. This AAC would be able to be configured via scripting, AND you could configure ASP.NET to automatically create an AAC and register certain components each time a new application (VROOT) is created in IIS6.

Not only does this help alleviate the same problems in Scenario 1, but it also solves the problem in Scenario 2, by allowing different versions of the same assembly with the same file name to be referenced by different individual components in an application.


Scenario 3
"Scott" also has an account at MCH.com (they are very popular). He runs several different applications out of several different virtual webs. Each application depends on the same component, which is updated frequently. Currently, Scott has to copy the assembly into the "/bin" folder for each application that uses his component. Scott is not happy.

Solution 3: "Add Reference From Web"
In this solution, Scott can bind to a web location. This location contains a manifest file, which keeps track of locations for each deployed assembly version. Scott's application will go through the same steps that the Updater Building Block currently goes through for WebForms, to ensure the most recent assembly version is available. Optionally, Scott can provide the binding with a version number, and Scott's application will always bind to that version.

This solution is more an enabler for component vendors than end users. This allows component vendors to specify a public location where assemblies are stored, and by deploying a new version and updating the manifest, our end users would automatically (or prompted, at the end user's request) when new updates are available. It also allows us to fall in line with MS' versioning policy (as discussed here and here), by releasing bug fixes and updates with the same AssemblyVersion but a different AssemblyFileVersion (thus keeping existing bindings intact while fixing major/minor bugs).

This would also make it so that Scott does not have to "install" anything. He does not have to worry about which version each application is using... it's all managed automatically.

Conclusion
I believe that these three scenarios illustrate the bulk of the problems that people deal with. If you can implement these solutions, you may very well reduce Assembly Hell even further (or maybe even eliminate it). Not only that, but these solutions will make it a Hell of a lot easier (pun intended) to develop applications, and I'll be able to keep my customers happier.


That's just my two cents. Hey Microsoft, what are the chances that these problems will be addressed in Whidbey?

2 Comments

  • There's another usage for solution 2 "Add Reference From AAC", at least for WinForm developers. E.g. the Updater Application Block creates for every new version of the application a new subfolder with the name set to the new version. With your proposal, the application would have a single subfolder, which is the AAC, where all its assemblies with all future versions would be stored. Much more elegant, that is.

  • think folders is a really bad idea, because you'd have to have a folder for each component, and then a subfolder for each component's component, etc.... it would get really ridiculous really fast. An AAC would solve it simple without the site bloat.

Comments have been disabled for this content.