A Custom View Engine with Dynamic View Location

One of the nice feature of ASP.NET MVC framework is its pluggability. This means you can completely replace the default view engine(s) with a custom one. One of the reason for using a custom view engine is to change the default views location and sometimes you need to change the views location at run-time. For doing this, you can extend the default view engine(s) and then change the default views location variables at run-time. But, you cannot directly change the default views location variables at run-time because they are static and shared among all requests. In this article, I will show you how you can dynamically change the views location without changing the default views location variables at run-time.

Description:

Let's say you need to synchronize the views location with controller name and controller namespace. So, instead of searching to the default views location(Views/ControllerName/ViewName) to locate views, this(these) custom view engine(s) will search in the Views/ControllerNameSpace/ControllerName/ViewName folder to locate views.

First of all create a sample ASP.NET MVC 3 application and then add these custom view engines to your application,

Here, I am extending the RazorViewEngine and WebFormViewEngine class and then appending /%1 in each views location variable, so that we can replace /%1at run-time. I am also overriding the FileExists, CreateView and CreatePartialView methods. In each of these method implementation, I am replacing /%1with controller namespace. Now, just register these view engines in Application_Start method in Global.asax.cs file,

Now just create a controller and put this controller's view inside Views/ControllerNameSpace/ControllerName folder and then run this application. You will find that everything works just fine.

Summary:

ASP.NET MVC uses convention over configuration to locate views. For many applications this convention to locate views is acceptable. But sometimes you may need to locate views at run-time. In this article, I showed you how you can dynamically locate your views by using a custom view engine. I am also attaching a sample application. Hopefully you will enjoy this article too.

I had the same reaction as Chris van Dam, I am also working on an MVC solution that uses multitenant architecture and found overriding the RazorViewEngine a godsend for having seperate pages for each tennant.

Just an update. I found an issue when I released my solution to a live environment that the view engine caches the cirtual path/directory of the view for each action on a controller. So when I went to one tennant's about page and then switched to the about page for another tennant where the about page for the second tennant is not in a tennant specific folder, it would try to pick it from a tennant folder. This caused a 404 error and so I resolved this by overriding the FindView method in the custom view engine like below:

As you can see in the override I'm not doing anything special apart from calling the base implementation but making sure the paramter useCache is set to false. This ensures that the ViewEngine looks for specific views each time rather than using a cached path.

Dear Imran,
Excellent short note.
Can you share your thoughts on how will the described way will work in the multi-tenant scenario where the views and controllers can be overridden by different tenants and each tenant will be in different assembly instead of the main web project assembly.

@Farooq, the location of controller is not a problem in MVC. But, if you need to move your views into a separate assembly then you can use this, http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html. The above scenario will only work for dynamic view location.

I am trying to use this approach but my Html.Action and Html.RenderAction throw exception : Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'.
Any idea why?