3

I m building a MVC 3 applications. The application should be able to display a different layout according to the sub domaine (ex: customer1.mysite.com -> layout1; customer2.mysite.com -> layout2; etc...) it will have also a layout for mobile and IE 6.

I have seen that their is the _ViewStart.cshtml that I can leverage to do the logic to set the layout. But what I don't get is where is the controler for that? Should I write all the code in the view?

An other question with layout how to do you factor out the code for the common behaviours? Do you have a controler for that?

And a last one I have seen the concept of areas in asp.net MVC2 is it obsolete now that we have Razor?

Thank you for your help

Fred

Jason Evans
  • 28,906
  • 14
  • 90
  • 154
fred_
  • 1,486
  • 1
  • 19
  • 31
  • BTW - your system is referred to as a multi-tenant system/architecture. There are some really good mvc related questions on this topic. Eg http://stackoverflow.com/search?q=asp.net-mvc+multi-tenant. – Ahmad Mar 18 '11 at 05:57

2 Answers2

2

This sounds like a good time to use ViewBag.

The idea is that during OnActionExecuting, you would look up the subdomain and shove it into the ViewBag. This can be done in a custom BaseController from which your other controllers inherit, or from an ActionFilter.

Then, in your _ViewStart, you can write a switch statement on ViewBag to control layout.

For example, here is an ActionFilter that will populate @ViewBag.Subdomain in any of your Razor views, including _ViewStart.cshtml.

public class AddSubdomainToViewDataAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var subdomain = filterContext.HttpContext.Request.Url.Authority.Split('.').First();
        var controller = filterContext.Controller as Controller;
        controller.ViewData.Add("Subdomain", subdomain);
    }
}

Then, decorate your controllers with this new [AddSubdomainToViewData] attribute.

Finally, in _ViewStart.cshtml, do something like this:

@{
    Layout = "~/Views/Shared/" + ((@ViewContext.ViewData["Subdomain"] as String) ?? String.Empty) + "_layout.cshtml";
}

This will use a different Razor layout for each subdomain.

Portman
  • 31,785
  • 25
  • 82
  • 101
  • Thank you Portman, Would you suggest it's better to use action filter or to go directly like that : – fred_ Mar 17 '11 at 14:26
  • sorry I pressed enter... @{ var subdomain = this.Context.Request.Url.Authority.Split('.').First(); Layout = "~/Views/Shared/" + ((@ViewContext.ViewData["Subdomain"] as String) ?? String.Empty) + "_layout.cshtml"; } ' – fred_ Mar 17 '11 at 14:28
  • If you're *just* using the subdomain, then ignore the ActionFilter, and just use the HttpContext directly in your ViewStart. But I was guessing that you were going to use the subdomain to do a database lookup, in which case you should encapsulate in an ActionFilter. – Portman Mar 21 '11 at 18:04
1

While you could do this in the _ViewStart I think that a better way would be to write a custom view engine in which based on the user agent or the domain include a different layout. Then you would have common controllers and views, only the layout will differ.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thank you Darin, very interesting alternative. I have seen that but without any sample. Do you know if someone has already tried? http://weblogs.asp.net/scottgu/archive/2010/10/22/asp-net-mvc-3-layouts.aspx : : "Important: Because the _ViewStart.cshtml allows us to write code, we can optionally make our Layout selection logic richer than just a basic property set. For example: we could vary the Layout template that we use depending on what type of device is accessing the site – and have a phone or tablet optimized layout for those devices, and a desktop optimized layout for PCs/Laptops." – fred_ Mar 17 '11 at 13:57