views:

493

answers:

2

Hi,

I am trying to create an ASP.Net Web application that stores it's "content" (ASPX/ASCX and assemblies) somewhere other than the file system (Inside a service, for example) and loads them in dynamically as required.

I have successfully created a VirtualPathProvider that takes care of reading ASPX/Master/ASCX files from alternate locations but I am running into problems when those ASPX pages Inherit a class - ie: when they have code behind.

Thanks to answers in another question I am now successfully able to load the assemblies into the application at run time. But when my the runtime attempts to compile my page I get the following error:

"Compiler Error Message: CS0400: The type or namespace name 'Web' could not be found in the global namespace (are you missing an assembly reference?)"

[System.Runtime.CompilerServices.CompilerGlobalScopeAttribute()] public class default_aspx : global::Web.Code.CodeBehind, System.Web.SessionState.IRequiresSessionState, System.Web.IHttpHandler

I have boiled down my code to a simple example of what is going wrong so that it is easy for you to see. You can download this code here.

The assembly is being loaded in dynamically at run time using the AppDomain.AssemblyResolve event. This is in the global.asax and looks like this:

        protected void Application_Start(object sender, EventArgs e)
    {
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Assembly_Resolve);
    }

    Assembly Assembly_Resolve(object sender, ResolveEventArgs args)
    {
        Assembly assembly = AppDomain.CurrentDomain.Load(Resources.Web_Code);
        if (args.Name == assembly.FullName)
        {
            return assembly;
        }
        return null;
    }

Any ideas?

EDIT If for any reason you need to update the Web.Code assembly - you will need to copy it into the "ReferencedAssemblies" folder of the web project for those changes to take effect.

A: 

OK. Can you try the following - remove the AssemblyResolve event. We will now use web.config runtime configuration to resolve this assemblies. In the <runtime> configuration add the following:

<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <probing privatePath="ReferencedAssemblies" />
</assemblyBinding>

I can't explain to myself why the two approaches - AppDomain.AssemblyResolve and this runtime AssemblyBinding give different results when dealing with PageBuildProvider. I was looking around the PageBuildProvider class to find any clues about what is happening, but still no luck. I'll probably look further into this as it got my attention and will post here if I find any solution.

Let me know if this solution with web.config file works for you. The only caveat is that you can't use resources to store your assemblies. You need to store them on the file system, any folder that is under the project one - as is currently with ReferencedAssemblies folder.

Ivan Zlatanov
Hey Ivan, I am currently investigating the possibility of using this technique - but I am really hoping to not have to write to a file system.Ideally these Assemblies will be memory resident only.A great idea though.
Gavin Osborn
A: 

I encountered the same problem when trying to load assemblies from DB (and using the AssemblyResolve event). But it seems to work fine if you load assemblies from disk or at least save a copy of the .dll file somewhere on the disk.

Sergiu