C# – ASPX Page Compilation Fails

asp.netc++clr

We’re developing a web-based application that allows administrators to upload plug-ins. All plug-ins are stored in a special folder outside the app root (say, C:\Plugins) and are dynamically loaded via Assembly.LoadFrom(). This works just fine for the most part: WebControls in the plug-ins are instantiated and loaded, custom classes function as expected, etc.

We’re using a custom VirtualPathProvider to get resources out of these plug-ins. So, to get an embedded ASPX file, you’d simply do like, “/MySite/embeddedResource/?Assembly=MyPlugin&Resource=MyPage.aspx”. And that works fine, too: the embedded ASPX file compiles and is served up like a normal page.

The problem, however, comes in when an embedded .aspx file (inside of a dynamically loaded plugin) references a class inside that same plug-in assembly. We get compilation errors like, “cannot find type or assembly MyPlugin.” This is odd because, clearly, it’s pulling the .aspx file out of MyPlugin; so how can it not find it?

So, I’m hoping you can help me out with this. The plugin would look like this:

MyPlugin.dll:

  • InternalHelperClass.cs
  • MyPage.aspx (resource with no .cs file)

When MyPage.aspx contains something like, “<%= InternalHelperClass.WriteHelloWorld() %>”, the compilation fails.

How can we get this to work?

UPDATE:

We have tried using fully qualified names. No difference.
It is impossible to step through – it is a compilation error when you go to the aspx page.
Namespaces would not be an issue in this case (since it was from an external plugin dll)

UPDATE2:

Joel, I think you are onto something. Unfortunately, editing the web.config to include these assemblies isn't part of the design. Basically, we want the plugins to be completely dynamic – drop them in a folder, restart the app, and be ready to go.

Best Solution

Assembly.LoadFrom is dynamic (late bound) which means the type is not included during compilation time therefore references to its contained classes are invalid. You need to specifically reference the assembly so its included as part of the compilation of the *.aspx class.

You may find some of the source code here helpful, and I recommend giving the Managed Extensibility Framework a go because it may have already solved this issue.

Update: I have found what I think is the answer to your problem. While this won't work in an ASP.NET 1.1 project, it would for 2.0+. They have restructured the building pipeline to use a BuildProvider which can be specified in the configuration file (web.config). Though you have to write your own build provider, you can make one that automatically references all the assemblies in the Plugins folder prior to compilation. Here's information on the configuration and here's what you need to subclass to do it.

Here's an out of date copy of the source code for Mono's PageBuildProvider, you'll need to check the latest implementation for ASP.NET from MS's shared source, copy it, and extend it with your custom assembly reference because the class is unfortunately sealed (but it doesn't look terribly complex).