views:

216

answers:

5

Hi,

Is it possible to have one .NET MVC application, and have it accessible from different domains, in such a way that the content will be domain-dependant?

For example, both www(dot)site1(dot)com and www(dot)site2(dot)com will point to my server's IP, and to the same website in IIS. In that website my .NET MVC application will reside. Now, I want the ability to know which site (domain name) triggered the ControllerAction, and act accordingly (for example, display different content for the homepage in the Index action, or allow/prevent access to specific content assigned to a specific site).

I would appreciate any help on this. I can accept an extra parameter passed to all controller actions (probably using Routing), but if there's a more elegant solution that would be ideal.

UPDATE: I'm testing your solutions, will report back shortly. Thanks!

Itamar.

A: 

An elegant solution would be to have 2 deployments for 2 domains, and to separate content.

You could still have common content, but separating the content without hardcoding this inside the application is a win situation.

Mercer Traieste
+2  A: 

Well, you can always get the domain from the Request.RawUrl property.

As Mercer mentioned, deploying these as two separate web apps would be a better solution though. If that isn't possible, I would try to design something relatively generic that would check the domain and return different Views for each domain.

Eric Petroelje
The whole idea is to keep it DRY (= the Don't Repeat Yourself principle). I would like to have one installation of the application, so whenever an application update will be necessary, I will have to deploy it only once and have all the websites that depend on it "automatically" updated.Content seperation will be done in the database using FKs, or in different DBs (could be configurable in an XML file by the application). The MVC application for delievering the content is the generic something here...Question is how to best achieve this?
synhershko
@synhershko - If that's the case, why not put your controllers and models in a separate class library project that's shared by the two web apps? Then each web app would just have it's own views. You'd still have two deployments, but only one codebase. My biggest concern would be if the functionality for the sites starts to diverge too much it could lead to some messy code. Hard to say if that's really an issue for you though without knowing more about your app.
Eric Petroelje
I already have most of the code (what you'd call a Model and other auxiliary stuff) in a seperate class library. The controllers are a bit less generic, and so are the Views. One of the main reason I'd like to keep only one installation is to avoid the need to update several installations with every update - and there are going to be more than 2 sites, and pretty frequent updates. Both ways I'm going to have one codebase, the difference being I want to avoid several installations and publish locations.
synhershko
As for a scenario - think of a simple site with content pages and menus (my case is more complicated, but thats enough for now). I want to avoid having to maintain several folders with the application in it; I want to have one codebase and one folder on the server I will publish the compiled application into. The application will be smart enough to detect the domain used to access it, and display the content relevant for that site (using a static map loaded from XML or simiilar). Does that make more sense?
synhershko
+1  A: 

You can easily access the domain name used in the request with something along the lines of the following:

switch(Request.ServerVariables("SERVER_NAME"))
{
    case "www.site1.com":
        //do something
    case "www.site2.com":
        //do something else
    default:
        //????
}

You can do this in anywhere you have access to the Request object.

HectorMac
Thanks, that I already know, but where would I want to use this in order to locate the site ID and pass it to the controller action? or better yet, is there a smoother way of doing this without having the controller actions have an extra parameter?
synhershko
A: 

If you use different databases to keep the data separate, then in the Session Start configure the application to use one of the databases based on the Server Name variable. Then place the working connection string in the session for the user.

protected void Session_Start(Object sender, EventArgs e)
{
  NameValueCollection NVCSrvElements = Request.ServerVariables;
  switch (NVCSrvElements.Get("SERVER_NAME")) 
  { 
      case "www.whatever1.com":
          Session["ConnStr"]="db1 connection string";
          break;
      case "www.whatever2.com":
          Session["ConnStr"] = "db2 connection string";
          break;
  }                  
}

Then use this connection string in the rest of the application.

Tony Borf
A: 

I have written a blog post about how to do this with an example web application for download.

It uses an abstract base Controller that is aware of the site it is being called for - by creating controllers that inherit from this base class you have automatic access to the current "site" for the current request.

It also allows you to load all your sites from a single database - can save you a bit on hosting fees if you're on a shared host, or if you run your own server you don't have to set up a new database for each site you create.

Luke Sampson
Thanks this looks like what I've been looking for. I'll probably have to tune it a bit, but that's going in the right direction. Thanks!
synhershko
Great, you're welcome!
Luke Sampson