I'm working on an MVC4 application that is designed to service two domains. Most of our content will be shared across the domains, but sometimes we will need to render different markup (using Razor) depending on which site the request came from.
Ideally, I want a convention-based approach that allows me to have a folder structure like this:
Views
+ Domain1
+ ControllerName
View1
View2
+ Domain2
+ ControllerName
View1
+ ControllerName
View1
View2
When resolving a view, I would like to check the domain-specific folder first, then the general views folder.
My first thoughts were to implement a custom view engine that inherits RazorViewEngine that would swap the ViewLocationFormats strings depending on the request domain. Unfortunately all this stuff is buried in the VirtualPathProviderEngine and can't be overridden.
It turns out that the answer was to create a custom view engine (inherited from RazorViewEngine) for each domain that knows about the domain-specific folders:
public class Domain1ViewEngine() : RazorViewEngine
{
...
ViewLocationFormats = new[]
{
"~/Views/Domain1/{1}/{0}.cshtml",
"~/Views/Domain1/Shared/{0}.cshtml"
};
...
}
I then needed to override the FindView
and FindPartialView
methods so that it only attempted to find locate views if the request had come from the right domain:
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
if ([THIS IS NOT THE RIGHT DOMAIN])
{
return new ViewEngineResult(new string[] { });
}
return base.FindView(controllerContext, viewName, masterName, useCache);
}
To complete the process I registered the view engine in Global.asax.cs
in the usual way:
protected void Application_Start()
{
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new Domain1ViewEngine());
ViewEngines.Engines.Add(new RazorViewEngine());
}