I’ve spent a frustrating day (again) attempting to setup a web project that is a sub-project of our main application. For whatever reason, I can’t reference code in a referenced assembly unless I load it as a control reference and, at least in most cases, copy the referenced assembly to the main /bin folder.
Works like this:
- NetQuarry is installed. The core assemblies are in the <webroot>/bin folder.
- The application needs some custom controls (mostly for wizard pages).
- The application wants to reference another custom assembly. To do this, we copy the assembly to the /bin folder of the new project. We include the reference and we can use the code in the debugger.
- The application’s new web project is installed and developed in a sub-folder of NetQuarry. (<webroot>/Apps/<myapp>).
- The code compiles, but you can’t load any of the custom controls because it can’t resolve the type.
- On most machines (I can’t tell you why this isn’t all machines) all you have to do is add a reference in the .ASCX page like this:
<%@ Register TagPrefix=”myappref” Namespace=”MyApp.Common” Assembly=”MyApp.Common” %>
- On other machines, you have to copy the referenced assembly to the root /bin folder.
Incidentally, I’ve tried the new Web Application Project model to solve this and failed as well. Scott Guthrie has a good post about it: Web Application Projects that you should read. The (really) good news about this new project model is that it compiles significantly faster. The bad news is that I have a similar reference problem when I try to create a web user control dynamically unless the assembly is copied to the <webroot>/bin folder.
So, why not just copy the sub-project .DLLs to the main /bin folder? Because I really don’t like it. In NetQuarry, sub-projects are loaded dynamically (a somewhat foreign concept to everything ASP, I know) and they don’t have a dependency on the main NetQuarry Web assembly. The idea is that one installs the core NetQuarry web, then builds their own web components (web user controls), references them as components using the NetQuarry Studio and uses them as PageElements to build wizards.
NetQuarry also loads extensions dynamically, which is exactly what we want to do with these web projects. So, I tried converting to the new Web Application Project model for sub-projects and loading the assemblies dynamically. Still didn’t work. Since these are web projects, you would think that the way to do this is in two steps: first, load the assembly, and second, load the user control via its virtual path. Once the assembly is loaded .NET should understand the types in the control but for some reason it doesn’t.
The idea behind NetQuarry is that you don’t have to know any of this stuff, but just so you know, the idea (that doesn’t work) is like this:
private IWizPage LoadWizardPage(NetQuarry.ComponentInfo ci)
System.Reflection.Assembly asm = ci.LoadAssembly();
return LoadControl(ci.Component) as IWizPage;
Where the ComponentInfo.LoadAssembly method is a little complex (and ommitted here for brevity). Basically, we try and find it in the list of loaded assemblies first, then in the specified path, then in <webroot>/bin, and finally in Apps/<appid>/bin.
Turns out that after you load the assembly, the component still doesn’t load. So we’re still discussing this. Perhaps I’ll break down and have custom projects deployed to the <approot>/bin folder, but I sort of doubt it. As ususal, it feels as if we’re the only ones solving this problem, but I did find this post from over a year ago (Dynamic LoadControl of ascx with dll not in bin path) and there is a response there (from a DevelopMentor staffer) that says: “ASP.NET mandates implicit loading of assemblies from ~/bin or the GAC. You can always call Assembly.LoadFrom, but I’m not sure if the LoadControl will work with that. It’s worth a try.”
I nearly refused to believe it, but after about 2 bad days on this, I’m convinced. Love to know why, Microsoft, anyone?
For now, we are leaving it alone and leaving the hacky @Register business in place.
We did, however, convert our main project (EAP.WebHost) into the new model and boy oh boy is it better.