views:

141

answers:

3

I'm building a multi-tenant ASP .NET application. Given that each tenant can configure their application dynamically (which may involve dynamic custom assemblies being loaded into memory), I need a means of isolating each tenant.

I'd prefer not to create a new Web Application per tenant for maintenance reasons.

I've was considering using the AppDomainManager to create an AppDomain per application, but it seems this is not intended to be used for ASP .NET applications.

Does anyone have some suggestions on this subject?

Thanks.

+4  A: 

I guess the question is: If you aren't into creating a Web Application, then what type of isolation is really acceptable to you?

If you really want an OS-level guarantee that assemblies won't trod on one another, I would give each their own Web Application. This is especially true if you're allowing people to load third-party assemblies, and is super-especially true if those third-party assemblies can find ways to instantiate unmanaged code.

I can see not creating a separate Web Application if it's all your (managed) code, but once you put dynamic custom assemblies into the mix, I think it's the only way to go.

Dave Markle
I second this, the key phrase is "custom assemblies".
Andreas Paulsson
Ok, I'm definitely willing to consider that, but I have a few concerns. One - the applications should all have the same root URL...is this even possible? Two - the creation and deletion needs to be automatic...should I use WMI for that? I dont know how I feel about that... And how many webapps does IIs support anyway? Will that scale in a cloud of hardware, since the limitation there would be the os? Three - we want this solution to be Azure compatible (but not Azure specific), so how would I go about managing it for Azure?
JeffN825
Also, how would you recommend handling shared resources (pages)? A VirtualPathProvider that extracts the page from shared dlls?
JeffN825
+1  A: 

When you create different web sites, your URL root is definitely gonna change. I was thinking why not different applications inside the main application, and put them in different Application Pools if required?

One... That way, the root URL would remain the same. Two... Creation a VDir or an instance of an application. Which one needs to be dynamic? Three... I've no expertise.

If I had to share the Pages, [based on applications hosted in different VDir], I would go for creating a new VDir for all my shared pages. And use some custom code to show application related data.

Rahul Soni
How would I go about dynamically creating the applications is the question though?
JeffN825
If you are using IIS 7, you can use delegate configuration of IIS Virtual Directories to your end users so that they can configure their applications.
Rahul Soni
OR, you can use SharePoint or DotNetNuke. If I understand your question correctly, you can use SharePoint to create a Site Definition and have anyone use it as a template for their own sites.
Rahul Soni
Does each SharePoint site run in a separate AppDomain? If so, that may be a very viable solution.
JeffN825
Well, I guess so [although not 100% sure]! The good thing is that if you create a Site Definition that contains all the features that you want, you can easily have other people work on top of it. All you have to say is something like... Create new Site Collection and choose your Site Definition. At that point you allocate a Sit Collection Admin and that's about it. It takes care of isolating all the data by itself, and it is pretty easy to work with as well.
Rahul Soni
I looked it up and it does not seem like AppDomain isolation between sites is guaranteed, so unfortunately, this doesn't address the problem of preventing tenant specific code from doing stuff it shouldn't.
JeffN825
+1  A: 

I wrote multi-tenant web application in MVC2. Adding / Removing an account is as complex as adding / removing a row in a table as I opted for shared database, shared schema approach.

This is a very good article about multi-tenant database design from MSDN: Multi-Tenant Data Architecture

All I had to do in MVC is to set up routing properly, so the first part of the path is account name:

  • www.yourdomain.com/Account1/...
  • www.yourdomain.com/Account2/...
  • www.yourdomain.com/Account3/...

and I have a custom MvcHandler for looking up account for each request:

public class AccountMvcHandler : MvcHandler
{
    public AccountModel Account { get; set; }

    public AccountMvcHandler(RequestContext requestContext)
        : base(requestContext)
    {
    }

    protected override IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
    {
        string accountName = this.RequestContext.RouteData.GetRequiredString("account");
        Account = ServiceFactory.GetService<IAccountService>().GetAccount(accountName);

        // URL doesn't contain valid account name - redirect to login page with Account Name textbox
        if (Account == null)
            httpContext.Response.Redirect(FormsAuthentication.LoginUrl);

        return base.BeginProcessRequest(httpContext, callback, state);
    }
}

As it was said by Andreas Paulsson the key phrase is "custom assemblies". Why do you need 'custom assemblies' for configuration? Are you using CodeEmit? Will users upload them? I would rather think about using Windows Workflow Foundation for any client-specific business logic customisation.

Jakub Konecki
I actually have the tenant-specific MVC routes set up, which are working great. The purpose for the custom assemblies is that tenants must be able to customize their "instance" with custom pages and code behinds. Isolating any custom code for this purpose is key.
JeffN825
To further clarify, yes, users will upload the custom assemblies, which will be compiled and run in the app domain. The problem is that these assemblies need some form of isolation so as to not be able to access data from other tenants. I already have code in place that prevents the custom assemblies from making DB calls, but I'm concerned about static contexts, such as the application state or static properties/methods/fields.
JeffN825
I've considered creating app domains dynamically for these custom assemblies, but I'd prefer something integrated, since asp .net is already managing app domains for me. Plus, I'm not sure how I'd get my custom app domain into the asp .net request lifecycle (able to issue rendered aspx pages)
JeffN825
@ JeffN825 - Allowing users to upload any code is a potential can of worms IMHO. Depending on the number of custom clients you might want to provision a new web site for them - this should be possible with simple msbuild script...
Jakub Konecki
I really don't want to get into the habit of requiring a custom deployment for every new client. It is a can of worms indeed, but definitely part of the requirements. I've been looking into using the DLR to host the code, but I'm not sure there are mature enough implementations to support this yet.
JeffN825