Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Composite Web Client Guidance

Good day,

I was wondering if you could perhaps help me,

I was reading the guidance associated with the following: Composite Web Guidance

I was reading through the section titled "Define the Solution Structure for a Modular Web Application", particularily the section "Multiple-Project Modules". I seem to understand the basic concepts surrounding this, however I can't seem to figure out a reasonable way to allow this to work with my web forms in seperate projects.

I realise design time support for masterpages will not be supported here, my question however is how to use something like unity (or another container) to allow me to deploy my projects (which include web form pages and code behind files) as completely independent into a folder and plug them into a solution, the guidance seems a bit unclear as to how to support this and whenever I attempt to import these modules I get run time errors. I've had this working successfully with MVC by exporting the controllers. I would appreciate your support, however I realise that you are an extremely busy people. If you could perhaps link me to a blog or a resource explaining this in detail I would be forever greatful. Thank you for taking the time to read this. To summarise I wish to achieve the following.

  1. Create my web shell project using asp.net web forms (without silverlight or any client technology)
  2. Create my modules which exist inside their own projects, which contain my aspx and aspx code behing pages as well as any dependent assemblies
  3. I wish these pages to be exportable and importable by my shell.
  4. If possible I'd like my module assemblies to be within their own folders as to not muddy my solution.
like image 851
Elixir Avatar asked Apr 03 '12 11:04

Elixir


1 Answers

I've done something similar a while back with regards to a plugin-type system where the plugins where pages and controls but were stored in separate assemblies.

What we ended up doing was this:

Register a custom VirtualPathProvider on Application_Start:

void Application_Start(object sender, EventArgs e)
{
    System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(
        new YourCustomVirtualPathProvider());
}

Override the necessary methods in the VirtualPathProvider (based on your logic):

public class YourCustomVirtualPathProvider : System.Web.Hosting.VirtualPathProvider
{
    private const string RESERVED_PATH = "/components/external";
    public override bool FileExists(string virtualPath)
    {
        if (virtualPath.StartsWith(RESERVED_PATH))
            return true;
        else
            return base.FileExists(virtualPath);
    }

    public override VirtualFile GetFile(string virtualPath)
    {
        if (virtualPath.StartsWith(RESERVED_PATH))
            return new MyCustomVirtualFile(virtualPath);
        else
            return base.GetFile(virtualPath);
    }

    //You'll also need to override methods for directories, omitted for brevity.
}

Now create the MyCustomVirtualFile class to load the files from an assembly:

public class MyCustomVirtualFile : System.Web.Hosting.VirtualFile
{
    private string _virtualPath;
    public MyCustomVirtualFile(string virtualPath) { _virtualPath = virtualPath }

    public override System.IO.Stream Open()
    {
        //You'll need some method to tie a virtual path to an assembly
        //Then load the file from the assembly and return as a Stream
        Assembly assembly = Foo.GetAssemblyByVirtualPath(_virtualPath);
        string fileName = Foo.GetFileNameFromVirtualPath(_virtualPath);
        return assembly.GetManifestresourceStream(fileName);
    }
}

The ASPX/ASCX or resource files you want to load this way will have to be added as an embedded resource to the assembly. You can do this by changing the "Build Action" property of the file:

properties dialogue

The code behinds will be compiled into the assembly, and if you're using a shared bin folder, you shouldn't need to do anything more. If they won't be shared, you'll have to attach to the AssemblyResolve and TypeResolve events in the global application (more on this here).

We eventually scrapped this idea because of security concerns, and ended up going with MEF data contracts but if all of your other assemblies are first party, then this should be quick and easy. Hope this helps.

like image 192
lukiffer Avatar answered Sep 30 '22 09:09

lukiffer